From 3ab2d9454a8f3f0c47c61c5823c7edbdfd3ff451 Mon Sep 17 00:00:00 2001 From: johba Date: Thu, 2 Oct 2025 14:37:59 +0200 Subject: [PATCH] health checks (#39) resolves #35 Co-authored-by: openhands Co-authored-by: johba Reviewed-on: https://codeberg.org/johba/harb/pulls/39 --- AGENTS.md | 2 +- containers/node-dev.Containerfile | 11 +- docs/podman.md | 2 +- kraiken-lib/codegen.yml | 6 +- kraiken-lib/src/__generated__/graphql.ts | 451 +++++++++++++++++- landing/AGENTS.md | 2 +- podman-compose.yml | 63 ++- scripts/dev.sh | 91 ++++ scripts/local_env.sh | 557 ----------------------- services/ponder/AGENTS.md | 2 +- services/ponder/README.md | 2 +- services/txnBot/AGENTS.md | 2 +- services/txnBot/README.md | 4 +- web-app/src/views/CheatsView.vue | 2 +- 14 files changed, 586 insertions(+), 611 deletions(-) create mode 100755 scripts/dev.sh delete mode 100755 scripts/local_env.sh diff --git a/AGENTS.md b/AGENTS.md index 59cd537..de67d93 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,7 +11,7 @@ 3. **Compete** - Snatch undervalued positions to optimise returns. ## Operating the Stack -- Start everything with `nohup ./scripts/local_env.sh start &` and stop via `./scripts/local_env.sh stop`. Do not launch services individually. +- Start everything with `nohup ./scripts/dev.sh start &` and stop via `./scripts/dev.sh stop`. Do not launch services individually. - Supported environments: `BASE_SEPOLIA_LOCAL_FORK` (default Anvil fork), `BASE_SEPOLIA`, and `BASE`. Match contract addresses and RPCs accordingly. - The stack boots Anvil, deploys contracts, seeds liquidity, starts Ponder, launches the landing site, and runs the txnBot. Wait for logs to settle before manual testing. diff --git a/containers/node-dev.Containerfile b/containers/node-dev.Containerfile index 717feaf..305fca5 100644 --- a/containers/node-dev.Containerfile +++ b/containers/node-dev.Containerfile @@ -1,8 +1,11 @@ -FROM node:20-bookworm +FROM node:20-alpine -RUN apt-get update \ - && apt-get install -y --no-install-recommends dumb-init \ - && rm -rf /var/lib/apt/lists/* +RUN apk add --no-cache \ + dumb-init \ + git \ + bash \ + postgresql-client \ + wget USER node WORKDIR /workspace diff --git a/docs/podman.md b/docs/podman.md index 6553848..868dd25 100644 --- a/docs/podman.md +++ b/docs/podman.md @@ -1,6 +1,6 @@ # Podman Staging Environment -The Podman stack mirrors `scripts/local_env.sh` using long-lived containers. Every boot spins up a fresh Base Sepolia fork, redeploys contracts, seeds liquidity, and launches the live-reload services behind Caddy on port 80. +The Podman stack mirrors `scripts/dev.sh` using long-lived containers. Every boot spins up a fresh Base Sepolia fork, redeploys contracts, seeds liquidity, and launches the live-reload services behind Caddy on port 80. ## Service Topology - `anvil` – Base Sepolia fork with optional mnemonic from `onchain/.secret.local` diff --git a/kraiken-lib/codegen.yml b/kraiken-lib/codegen.yml index f93bb1b..d3982f8 100644 --- a/kraiken-lib/codegen.yml +++ b/kraiken-lib/codegen.yml @@ -1,6 +1,6 @@ overwrite: true -schema: "./schema-with-scalars.graphql" # Or an endpoint if your schema is remote -documents: "../subgraph/base_sepolia/src/**/*.graphql" +schema: "../services/ponder/generated/schema.graphql" +documents: [] generates: src/__generated__/graphql.ts: config: @@ -11,4 +11,4 @@ generates: Int8: number plugins: - "typescript" - - "typescript-operations" \ No newline at end of file + - "typescript-operations" diff --git a/kraiken-lib/src/__generated__/graphql.ts b/kraiken-lib/src/__generated__/graphql.ts index 3915ebb..483e4e8 100644 --- a/kraiken-lib/src/__generated__/graphql.ts +++ b/kraiken-lib/src/__generated__/graphql.ts @@ -12,41 +12,442 @@ export type Scalars = { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } - BigDecimal: { input: any; output: any; } - BigInt: { input: any; output: any; } - Bytes: { input: any; output: any; } + BigInt: { input: string; output: string; } + /** The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ + JSON: { input: any; output: any; } }; -export type Position = { - __typename?: 'Position'; - creationTime: Scalars['Int']['output']; - id: Scalars['Bytes']['output']; - lastTaxTime?: Maybe; - owner: Scalars['Bytes']['output']; - share: Scalars['BigDecimal']['output']; - status: PositionStatus; - taxRate: Scalars['BigDecimal']['output']; +export type Meta = { + __typename?: 'Meta'; + status?: Maybe; }; -export enum PositionStatus { - Active = 'Active', - Closed = 'Closed' -} +export type PageInfo = { + __typename?: 'PageInfo'; + endCursor?: Maybe; + hasNextPage: Scalars['Boolean']['output']; + hasPreviousPage: Scalars['Boolean']['output']; + startCursor?: Maybe; +}; export type Query = { __typename?: 'Query'; - positions?: Maybe>>; - stats?: Maybe>>; + _meta?: Maybe; + positions?: Maybe; + positionss: PositionsPage; + stats?: Maybe; + statss: StatsPage; +}; + + +export type QueryPositionsArgs = { + id: Scalars['String']['input']; +}; + + +export type QueryPositionssArgs = { + after?: InputMaybe; + before?: InputMaybe; + limit?: InputMaybe; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + where?: InputMaybe; +}; + + +export type QueryStatsArgs = { + id: Scalars['String']['input']; +}; + + +export type QueryStatssArgs = { + after?: InputMaybe; + before?: InputMaybe; + limit?: InputMaybe; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + where?: InputMaybe; +}; + +export type Positions = { + __typename?: 'positions'; + closedAt?: Maybe; + createdAt: Scalars['BigInt']['output']; + creationTime: Scalars['BigInt']['output']; + id: Scalars['String']['output']; + kraikenDeposit: Scalars['BigInt']['output']; + lastTaxTime: Scalars['BigInt']['output']; + owner: Scalars['String']['output']; + payout: Scalars['BigInt']['output']; + share: Scalars['Float']['output']; + snatched: Scalars['Int']['output']; + stakeDeposit: Scalars['BigInt']['output']; + status: Scalars['String']['output']; + taxPaid: Scalars['BigInt']['output']; + taxRate: Scalars['Float']['output']; + totalSupplyEnd?: Maybe; + totalSupplyInit: Scalars['BigInt']['output']; +}; + +export type PositionsFilter = { + AND?: InputMaybe>>; + OR?: InputMaybe>>; + closedAt?: InputMaybe; + closedAt_gt?: InputMaybe; + closedAt_gte?: InputMaybe; + closedAt_in?: InputMaybe>>; + closedAt_lt?: InputMaybe; + closedAt_lte?: InputMaybe; + closedAt_not?: InputMaybe; + closedAt_not_in?: InputMaybe>>; + createdAt?: InputMaybe; + createdAt_gt?: InputMaybe; + createdAt_gte?: InputMaybe; + createdAt_in?: InputMaybe>>; + createdAt_lt?: InputMaybe; + createdAt_lte?: InputMaybe; + createdAt_not?: InputMaybe; + createdAt_not_in?: InputMaybe>>; + creationTime?: InputMaybe; + creationTime_gt?: InputMaybe; + creationTime_gte?: InputMaybe; + creationTime_in?: InputMaybe>>; + creationTime_lt?: InputMaybe; + creationTime_lte?: InputMaybe; + creationTime_not?: InputMaybe; + creationTime_not_in?: InputMaybe>>; + id?: InputMaybe; + id_contains?: InputMaybe; + id_ends_with?: InputMaybe; + id_in?: InputMaybe>>; + id_not?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_ends_with?: InputMaybe; + id_not_in?: InputMaybe>>; + id_not_starts_with?: InputMaybe; + id_starts_with?: InputMaybe; + kraikenDeposit?: InputMaybe; + kraikenDeposit_gt?: InputMaybe; + kraikenDeposit_gte?: InputMaybe; + kraikenDeposit_in?: InputMaybe>>; + kraikenDeposit_lt?: InputMaybe; + kraikenDeposit_lte?: InputMaybe; + kraikenDeposit_not?: InputMaybe; + kraikenDeposit_not_in?: InputMaybe>>; + lastTaxTime?: InputMaybe; + lastTaxTime_gt?: InputMaybe; + lastTaxTime_gte?: InputMaybe; + lastTaxTime_in?: InputMaybe>>; + lastTaxTime_lt?: InputMaybe; + lastTaxTime_lte?: InputMaybe; + lastTaxTime_not?: InputMaybe; + lastTaxTime_not_in?: InputMaybe>>; + owner?: InputMaybe; + owner_contains?: InputMaybe; + owner_ends_with?: InputMaybe; + owner_in?: InputMaybe>>; + owner_not?: InputMaybe; + owner_not_contains?: InputMaybe; + owner_not_ends_with?: InputMaybe; + owner_not_in?: InputMaybe>>; + owner_not_starts_with?: InputMaybe; + owner_starts_with?: InputMaybe; + payout?: InputMaybe; + payout_gt?: InputMaybe; + payout_gte?: InputMaybe; + payout_in?: InputMaybe>>; + payout_lt?: InputMaybe; + payout_lte?: InputMaybe; + payout_not?: InputMaybe; + payout_not_in?: InputMaybe>>; + share?: InputMaybe; + share_gt?: InputMaybe; + share_gte?: InputMaybe; + share_in?: InputMaybe>>; + share_lt?: InputMaybe; + share_lte?: InputMaybe; + share_not?: InputMaybe; + share_not_in?: InputMaybe>>; + snatched?: InputMaybe; + snatched_gt?: InputMaybe; + snatched_gte?: InputMaybe; + snatched_in?: InputMaybe>>; + snatched_lt?: InputMaybe; + snatched_lte?: InputMaybe; + snatched_not?: InputMaybe; + snatched_not_in?: InputMaybe>>; + stakeDeposit?: InputMaybe; + stakeDeposit_gt?: InputMaybe; + stakeDeposit_gte?: InputMaybe; + stakeDeposit_in?: InputMaybe>>; + stakeDeposit_lt?: InputMaybe; + stakeDeposit_lte?: InputMaybe; + stakeDeposit_not?: InputMaybe; + stakeDeposit_not_in?: InputMaybe>>; + status?: InputMaybe; + status_contains?: InputMaybe; + status_ends_with?: InputMaybe; + status_in?: InputMaybe>>; + status_not?: InputMaybe; + status_not_contains?: InputMaybe; + status_not_ends_with?: InputMaybe; + status_not_in?: InputMaybe>>; + status_not_starts_with?: InputMaybe; + status_starts_with?: InputMaybe; + taxPaid?: InputMaybe; + taxPaid_gt?: InputMaybe; + taxPaid_gte?: InputMaybe; + taxPaid_in?: InputMaybe>>; + taxPaid_lt?: InputMaybe; + taxPaid_lte?: InputMaybe; + taxPaid_not?: InputMaybe; + taxPaid_not_in?: InputMaybe>>; + taxRate?: InputMaybe; + taxRate_gt?: InputMaybe; + taxRate_gte?: InputMaybe; + taxRate_in?: InputMaybe>>; + taxRate_lt?: InputMaybe; + taxRate_lte?: InputMaybe; + taxRate_not?: InputMaybe; + taxRate_not_in?: InputMaybe>>; + totalSupplyEnd?: InputMaybe; + totalSupplyEnd_gt?: InputMaybe; + totalSupplyEnd_gte?: InputMaybe; + totalSupplyEnd_in?: InputMaybe>>; + totalSupplyEnd_lt?: InputMaybe; + totalSupplyEnd_lte?: InputMaybe; + totalSupplyEnd_not?: InputMaybe; + totalSupplyEnd_not_in?: InputMaybe>>; + totalSupplyInit?: InputMaybe; + totalSupplyInit_gt?: InputMaybe; + totalSupplyInit_gte?: InputMaybe; + totalSupplyInit_in?: InputMaybe>>; + totalSupplyInit_lt?: InputMaybe; + totalSupplyInit_lte?: InputMaybe; + totalSupplyInit_not?: InputMaybe; + totalSupplyInit_not_in?: InputMaybe>>; +}; + +export type PositionsPage = { + __typename?: 'positionsPage'; + items: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; }; export type Stats = { - __typename?: 'Stats'; - activeSupply: Scalars['BigInt']['output']; - id: Scalars['Bytes']['output']; - outstandingSupply: Scalars['BigInt']['output']; + __typename?: 'stats'; + burnNextHourProjected: Scalars['BigInt']['output']; + burnedLastDay: Scalars['BigInt']['output']; + burnedLastWeek: Scalars['BigInt']['output']; + id: Scalars['String']['output']; + kraikenTotalSupply: Scalars['BigInt']['output']; + lastHourlyUpdateTimestamp: Scalars['BigInt']['output']; + mintNextHourProjected: Scalars['BigInt']['output']; + mintedLastDay: Scalars['BigInt']['output']; + mintedLastWeek: Scalars['BigInt']['output']; + outstandingStake: Scalars['BigInt']['output']; + ringBuffer: Scalars['JSON']['output']; + ringBufferPointer: Scalars['Int']['output']; + stakeTotalSupply: Scalars['BigInt']['output']; + taxPaidLastDay: Scalars['BigInt']['output']; + taxPaidLastWeek: Scalars['BigInt']['output']; + taxPaidNextHourProjected: Scalars['BigInt']['output']; + totalBurned: Scalars['BigInt']['output']; + totalMinted: Scalars['BigInt']['output']; + totalTaxPaid: Scalars['BigInt']['output']; + totalUbiClaimed: Scalars['BigInt']['output']; + ubiClaimedLastDay: Scalars['BigInt']['output']; + ubiClaimedLastWeek: Scalars['BigInt']['output']; + ubiClaimedNextHourProjected: Scalars['BigInt']['output']; }; -export type GetPositionsQueryVariables = Exact<{ [key: string]: never; }>; +export type StatsFilter = { + AND?: InputMaybe>>; + OR?: InputMaybe>>; + burnNextHourProjected?: InputMaybe; + burnNextHourProjected_gt?: InputMaybe; + burnNextHourProjected_gte?: InputMaybe; + burnNextHourProjected_in?: InputMaybe>>; + burnNextHourProjected_lt?: InputMaybe; + burnNextHourProjected_lte?: InputMaybe; + burnNextHourProjected_not?: InputMaybe; + burnNextHourProjected_not_in?: InputMaybe>>; + burnedLastDay?: InputMaybe; + burnedLastDay_gt?: InputMaybe; + burnedLastDay_gte?: InputMaybe; + burnedLastDay_in?: InputMaybe>>; + burnedLastDay_lt?: InputMaybe; + burnedLastDay_lte?: InputMaybe; + burnedLastDay_not?: InputMaybe; + burnedLastDay_not_in?: InputMaybe>>; + burnedLastWeek?: InputMaybe; + burnedLastWeek_gt?: InputMaybe; + burnedLastWeek_gte?: InputMaybe; + burnedLastWeek_in?: InputMaybe>>; + burnedLastWeek_lt?: InputMaybe; + burnedLastWeek_lte?: InputMaybe; + burnedLastWeek_not?: InputMaybe; + burnedLastWeek_not_in?: InputMaybe>>; + id?: InputMaybe; + id_contains?: InputMaybe; + id_ends_with?: InputMaybe; + id_in?: InputMaybe>>; + id_not?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_ends_with?: InputMaybe; + id_not_in?: InputMaybe>>; + id_not_starts_with?: InputMaybe; + id_starts_with?: InputMaybe; + kraikenTotalSupply?: InputMaybe; + kraikenTotalSupply_gt?: InputMaybe; + kraikenTotalSupply_gte?: InputMaybe; + kraikenTotalSupply_in?: InputMaybe>>; + kraikenTotalSupply_lt?: InputMaybe; + kraikenTotalSupply_lte?: InputMaybe; + kraikenTotalSupply_not?: InputMaybe; + kraikenTotalSupply_not_in?: InputMaybe>>; + lastHourlyUpdateTimestamp?: InputMaybe; + lastHourlyUpdateTimestamp_gt?: InputMaybe; + lastHourlyUpdateTimestamp_gte?: InputMaybe; + lastHourlyUpdateTimestamp_in?: InputMaybe>>; + lastHourlyUpdateTimestamp_lt?: InputMaybe; + lastHourlyUpdateTimestamp_lte?: InputMaybe; + lastHourlyUpdateTimestamp_not?: InputMaybe; + lastHourlyUpdateTimestamp_not_in?: InputMaybe>>; + mintNextHourProjected?: InputMaybe; + mintNextHourProjected_gt?: InputMaybe; + mintNextHourProjected_gte?: InputMaybe; + mintNextHourProjected_in?: InputMaybe>>; + mintNextHourProjected_lt?: InputMaybe; + mintNextHourProjected_lte?: InputMaybe; + mintNextHourProjected_not?: InputMaybe; + mintNextHourProjected_not_in?: InputMaybe>>; + mintedLastDay?: InputMaybe; + mintedLastDay_gt?: InputMaybe; + mintedLastDay_gte?: InputMaybe; + mintedLastDay_in?: InputMaybe>>; + mintedLastDay_lt?: InputMaybe; + mintedLastDay_lte?: InputMaybe; + mintedLastDay_not?: InputMaybe; + mintedLastDay_not_in?: InputMaybe>>; + mintedLastWeek?: InputMaybe; + mintedLastWeek_gt?: InputMaybe; + mintedLastWeek_gte?: InputMaybe; + mintedLastWeek_in?: InputMaybe>>; + mintedLastWeek_lt?: InputMaybe; + mintedLastWeek_lte?: InputMaybe; + mintedLastWeek_not?: InputMaybe; + mintedLastWeek_not_in?: InputMaybe>>; + outstandingStake?: InputMaybe; + outstandingStake_gt?: InputMaybe; + outstandingStake_gte?: InputMaybe; + outstandingStake_in?: InputMaybe>>; + outstandingStake_lt?: InputMaybe; + outstandingStake_lte?: InputMaybe; + outstandingStake_not?: InputMaybe; + outstandingStake_not_in?: InputMaybe>>; + ringBufferPointer?: InputMaybe; + ringBufferPointer_gt?: InputMaybe; + ringBufferPointer_gte?: InputMaybe; + ringBufferPointer_in?: InputMaybe>>; + ringBufferPointer_lt?: InputMaybe; + ringBufferPointer_lte?: InputMaybe; + ringBufferPointer_not?: InputMaybe; + ringBufferPointer_not_in?: InputMaybe>>; + stakeTotalSupply?: InputMaybe; + stakeTotalSupply_gt?: InputMaybe; + stakeTotalSupply_gte?: InputMaybe; + stakeTotalSupply_in?: InputMaybe>>; + stakeTotalSupply_lt?: InputMaybe; + stakeTotalSupply_lte?: InputMaybe; + stakeTotalSupply_not?: InputMaybe; + stakeTotalSupply_not_in?: InputMaybe>>; + taxPaidLastDay?: InputMaybe; + taxPaidLastDay_gt?: InputMaybe; + taxPaidLastDay_gte?: InputMaybe; + taxPaidLastDay_in?: InputMaybe>>; + taxPaidLastDay_lt?: InputMaybe; + taxPaidLastDay_lte?: InputMaybe; + taxPaidLastDay_not?: InputMaybe; + taxPaidLastDay_not_in?: InputMaybe>>; + taxPaidLastWeek?: InputMaybe; + taxPaidLastWeek_gt?: InputMaybe; + taxPaidLastWeek_gte?: InputMaybe; + taxPaidLastWeek_in?: InputMaybe>>; + taxPaidLastWeek_lt?: InputMaybe; + taxPaidLastWeek_lte?: InputMaybe; + taxPaidLastWeek_not?: InputMaybe; + taxPaidLastWeek_not_in?: InputMaybe>>; + taxPaidNextHourProjected?: InputMaybe; + taxPaidNextHourProjected_gt?: InputMaybe; + taxPaidNextHourProjected_gte?: InputMaybe; + taxPaidNextHourProjected_in?: InputMaybe>>; + taxPaidNextHourProjected_lt?: InputMaybe; + taxPaidNextHourProjected_lte?: InputMaybe; + taxPaidNextHourProjected_not?: InputMaybe; + taxPaidNextHourProjected_not_in?: InputMaybe>>; + totalBurned?: InputMaybe; + totalBurned_gt?: InputMaybe; + totalBurned_gte?: InputMaybe; + totalBurned_in?: InputMaybe>>; + totalBurned_lt?: InputMaybe; + totalBurned_lte?: InputMaybe; + totalBurned_not?: InputMaybe; + totalBurned_not_in?: InputMaybe>>; + totalMinted?: InputMaybe; + totalMinted_gt?: InputMaybe; + totalMinted_gte?: InputMaybe; + totalMinted_in?: InputMaybe>>; + totalMinted_lt?: InputMaybe; + totalMinted_lte?: InputMaybe; + totalMinted_not?: InputMaybe; + totalMinted_not_in?: InputMaybe>>; + totalTaxPaid?: InputMaybe; + totalTaxPaid_gt?: InputMaybe; + totalTaxPaid_gte?: InputMaybe; + totalTaxPaid_in?: InputMaybe>>; + totalTaxPaid_lt?: InputMaybe; + totalTaxPaid_lte?: InputMaybe; + totalTaxPaid_not?: InputMaybe; + totalTaxPaid_not_in?: InputMaybe>>; + totalUbiClaimed?: InputMaybe; + totalUbiClaimed_gt?: InputMaybe; + totalUbiClaimed_gte?: InputMaybe; + totalUbiClaimed_in?: InputMaybe>>; + totalUbiClaimed_lt?: InputMaybe; + totalUbiClaimed_lte?: InputMaybe; + totalUbiClaimed_not?: InputMaybe; + totalUbiClaimed_not_in?: InputMaybe>>; + ubiClaimedLastDay?: InputMaybe; + ubiClaimedLastDay_gt?: InputMaybe; + ubiClaimedLastDay_gte?: InputMaybe; + ubiClaimedLastDay_in?: InputMaybe>>; + ubiClaimedLastDay_lt?: InputMaybe; + ubiClaimedLastDay_lte?: InputMaybe; + ubiClaimedLastDay_not?: InputMaybe; + ubiClaimedLastDay_not_in?: InputMaybe>>; + ubiClaimedLastWeek?: InputMaybe; + ubiClaimedLastWeek_gt?: InputMaybe; + ubiClaimedLastWeek_gte?: InputMaybe; + ubiClaimedLastWeek_in?: InputMaybe>>; + ubiClaimedLastWeek_lt?: InputMaybe; + ubiClaimedLastWeek_lte?: InputMaybe; + ubiClaimedLastWeek_not?: InputMaybe; + ubiClaimedLastWeek_not_in?: InputMaybe>>; + ubiClaimedNextHourProjected?: InputMaybe; + ubiClaimedNextHourProjected_gt?: InputMaybe; + ubiClaimedNextHourProjected_gte?: InputMaybe; + ubiClaimedNextHourProjected_in?: InputMaybe>>; + ubiClaimedNextHourProjected_lt?: InputMaybe; + ubiClaimedNextHourProjected_lte?: InputMaybe; + ubiClaimedNextHourProjected_not?: InputMaybe; + ubiClaimedNextHourProjected_not_in?: InputMaybe>>; +}; - -export type GetPositionsQuery = { __typename?: 'Query', positions?: Array<{ __typename?: 'Position', id: any, owner: any, share: any, creationTime: number, lastTaxTime?: number | null, taxRate: any, status: PositionStatus } | null> | null }; +export type StatsPage = { + __typename?: 'statsPage'; + items: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; diff --git a/landing/AGENTS.md b/landing/AGENTS.md index 6b71149..98df3a9 100644 --- a/landing/AGENTS.md +++ b/landing/AGENTS.md @@ -19,7 +19,7 @@ Vue 3 + Vite application that delivers the public marketing site and forthcoming - Motion relies on CSS transitions to keep runtime costs low ## Development Workflow -- Boot the full stack with `nohup ./scripts/local_env.sh start &`; the script handles landing dev server wiring. +- Boot the full stack with `nohup ./scripts/dev.sh start &`; the script handles landing dev server wiring. - Use local package scripts for targeted tasks: - `npm install` - `npm run build` diff --git a/podman-compose.yml b/podman-compose.yml index b54359d..19830bf 100644 --- a/podman-compose.yml +++ b/podman-compose.yml @@ -9,6 +9,12 @@ services: expose: - "8545" restart: unless-stopped + healthcheck: + test: ["CMD", "cast", "block-number", "--rpc-url", "http://localhost:8545"] + interval: 2s + timeout: 1s + retries: 5 + start_period: 5s postgres: image: docker.io/library/postgres:16-alpine @@ -37,10 +43,15 @@ services: - ANVIL_RPC=http://anvil:8545 depends_on: anvil: - condition: service_started + condition: service_healthy postgres: condition: service_healthy restart: "no" + healthcheck: + test: ["CMD", "test", "-f", "/workspace/tmp/podman/contracts.env"] + interval: 5s + retries: 18 + start_period: 10s ponder: build: @@ -56,12 +67,20 @@ services: - CHOKIDAR_USEPOLLING=1 depends_on: anvil: - condition: service_started + condition: service_healthy postgres: condition: service_healthy + bootstrap: + condition: service_started expose: - "42069" restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:42069/"] + interval: 5s + timeout: 3s + retries: 12 + start_period: 20s webapp: build: @@ -76,10 +95,16 @@ services: environment: - CHOKIDAR_USEPOLLING=1 depends_on: - - anvil + ponder: + condition: service_healthy expose: - "5173" restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:5173/app/"] + interval: 5s + retries: 6 + start_period: 10s landing: build: @@ -94,10 +119,16 @@ services: environment: - CHOKIDAR_USEPOLLING=1 depends_on: - - anvil + ponder: + condition: service_healthy expose: - "5174" restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:5174/"] + interval: 5s + retries: 6 + start_period: 10s txn-bot: build: @@ -111,11 +142,16 @@ services: - kraiken-node-modules:/workspace/kraiken-lib/node_modules working_dir: /workspace depends_on: - - anvil - - ponder + ponder: + condition: service_healthy expose: - "43069" restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:43069/status"] + interval: 5s + retries: 4 + start_period: 10s caddy: image: docker.io/library/caddy:2.8 @@ -124,17 +160,18 @@ services: ports: - "0.0.0.0:8081:80" depends_on: - anvil: - condition: service_started - ponder: - condition: service_started webapp: - condition: service_started + condition: service_healthy landing: - condition: service_started + condition: service_healthy txn-bot: - condition: service_started + condition: service_healthy restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "http://localhost:80"] + interval: 2s + retries: 3 + start_period: 2s volumes: postgres-data: diff --git a/scripts/dev.sh b/scripts/dev.sh new file mode 100755 index 0000000..30b0157 --- /dev/null +++ b/scripts/dev.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")/.." + +PID_FILE=/tmp/kraiken-watcher.pid +PROJECT_NAME=${COMPOSE_PROJECT_NAME:-$(basename "$PWD")} + +start_stack() { + if [[ -f "$PID_FILE" ]]; then + local existing_pid + existing_pid=$(cat "$PID_FILE") + if kill -0 "$existing_pid" 2>/dev/null; then + echo "Stopping existing kraiken-lib watcher ($existing_pid)..." + kill "$existing_pid" 2>/dev/null || true + wait "$existing_pid" 2>/dev/null || true + fi + rm -f "$PID_FILE" + fi + + echo "Building kraiken-lib..." + ./scripts/build-kraiken-lib.sh + + echo "Starting stack..." + podman-compose up -d + + echo "Watching for kraiken-lib changes..." + ./scripts/watch-kraiken-lib.sh & + echo $! > "$PID_FILE" + + echo "" + echo "[ok] Stack started" + echo " Web App: http://localhost:8081/app/" + echo " GraphQL: http://localhost:8081/graphql" +} + +stop_stack() { + if [[ -f "$PID_FILE" ]]; then + local watcher_pid + watcher_pid=$(cat "$PID_FILE") + if kill "$watcher_pid" 2>/dev/null; then + wait "$watcher_pid" 2>/dev/null || true + fi + rm -f "$PID_FILE" + fi + podman-compose down + echo "[ok] Stack stopped" +} + +check_health() { + echo "Checking health..." + local services=(anvil postgres ponder webapp landing txn-bot caddy) + for service in "${services[@]}"; do + local container + container=$(podman ps --all \ + --filter "label=com.docker.compose.project=${PROJECT_NAME}" \ + --filter "label=com.docker.compose.service=${service}" \ + --format '{{.Names}}' | head -n1) + + if [[ -z "$container" ]]; then + echo " [??] $service (not created)" + continue + fi + + if podman healthcheck run "$container" &>/dev/null; then + echo " [ok] $service" + else + echo " [!!] $service" + fi + done +} + +usage() { + echo "Usage: $0 {start|stop|health}" + exit 1 +} + +case "${1:-help}" in + start) + start_stack + ;; + stop) + stop_stack + ;; + health) + check_health + ;; + *) + usage + ;; +esac diff --git a/scripts/local_env.sh b/scripts/local_env.sh deleted file mode 100755 index 46f4f26..0000000 --- a/scripts/local_env.sh +++ /dev/null @@ -1,557 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -STATE_DIR="$ROOT_DIR/tmp/local-env" -LOG_DIR="$STATE_DIR/logs" - -ANVIL_PID_FILE="$STATE_DIR/anvil.pid" -PONDER_PID_FILE="$STATE_DIR/ponder.pid" -WEBAPP_PID_FILE="$STATE_DIR/webapp.pid" -TXNBOT_PID_FILE="$STATE_DIR/txnBot.pid" - -ANVIL_LOG="$LOG_DIR/anvil.log" -PONDER_LOG="$LOG_DIR/ponder.log" -WEBAPP_LOG="$LOG_DIR/webapp.log" -TXNBOT_LOG="$LOG_DIR/txnBot.log" -SETUP_LOG="$LOG_DIR/setup.log" -TXNBOT_ENV_FILE="$STATE_DIR/txnBot.env" -MNEMONIC_FILE="$ROOT_DIR/onchain/.secret.local" - -FORK_URL=${FORK_URL:-"https://sepolia.base.org"} -ANVIL_RPC="http://127.0.0.1:8545" -GRAPHQL_HEALTH="http://127.0.0.1:42069/health" -GRAPHQL_ENDPOINT="http://127.0.0.1:42069/graphql" -FRONTEND_URL="http://127.0.0.1:5173" -LOCAL_TXNBOT_URL="http://127.0.0.1:43069" - -FOUNDRY_BIN=${FOUNDRY_BIN:-"$HOME/.foundry/bin"} -FORGE="$FOUNDRY_BIN/forge" -CAST="$FOUNDRY_BIN/cast" -ANVIL="$FOUNDRY_BIN/anvil" - -DEFAULT_DEPLOYER_PK="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" -DEFAULT_DEPLOYER_ADDR="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" -DEPLOYER_PK=${DEPLOYER_PK:-$DEFAULT_DEPLOYER_PK} -DEPLOYER_ADDR=${DEPLOYER_ADDR:-$DEFAULT_DEPLOYER_ADDR} -FEE_DEST="0xf6a3eef9088A255c32b6aD2025f83E57291D9011" -WETH="0x4200000000000000000000000000000000000006" -SWAP_ROUTER="0x94cC0AaC535CCDB3C01d6787D6413C739ae12bc4" - -DEFAULT_TXNBOT_PRIVATE_KEY="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" -DEFAULT_TXNBOT_ADDRESS="0x70997970C51812dc3A010C7d01b50e0d17dc79C8" - -TXNBOT_PRIVATE_KEY=${TXNBOT_PRIVATE_KEY:-$DEFAULT_TXNBOT_PRIVATE_KEY} -TXNBOT_ADDRESS=${TXNBOT_ADDRESS:-$DEFAULT_TXNBOT_ADDRESS} -TXNBOT_FUND_VALUE=${TXNBOT_FUND_VALUE:-1ether} - -MAX_UINT="0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - -SKIP_CLEANUP=false -COMMAND="start" - -cleanup() { - stop_process "Frontend" "$WEBAPP_PID_FILE" - stop_process "Ponder" "$PONDER_PID_FILE" - stop_process "TxnBot" "$TXNBOT_PID_FILE" - stop_process "Anvil" "$ANVIL_PID_FILE" - - if [[ "$SKIP_CLEANUP" == true ]]; then - log "Skipping state cleanup (--no-cleanup). State preserved at $STATE_DIR" - return - fi - - if [[ -d "$STATE_DIR" ]]; then - rm -rf "$STATE_DIR" - fi -} - -stop_process() { - local name="$1" - local pid_file="$2" - - if [[ -f "$pid_file" ]]; then - local pid - pid="$(cat "$pid_file")" - if kill -0 "$pid" 2>/dev/null; then - echo "[local-env] Stopping $name (pid $pid)" - kill "$pid" 2>/dev/null || true - wait "$pid" 2>/dev/null || true - fi - rm -f "$pid_file" - fi -} - -log() { - echo "[local-env] $*" -} - -wait_for_rpc() { - local url="$1" - for _ in {1..60}; do - if curl --max-time 1 --connect-timeout 1 -s -o /dev/null -X POST "$url" -H "Content-Type: application/json" \ - -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'; then - return 0 - fi - sleep 1 - done - log "Timed out waiting for RPC at $url" - return 1 -} - -wait_for_http() { - local url="$1" - for _ in {1..60}; do - if curl --max-time 1 --connect-timeout 1 -sSf "$url" >/dev/null 2>&1; then - return 0 - fi - sleep 1 - done - log "Timed out waiting for $url" - return 1 -} - -set_deployer_credentials() { - if [[ -n "$DEPLOYER_PK" && -n "$DEPLOYER_ADDR" ]]; then - return - fi - - if [[ -f "$MNEMONIC_FILE" ]]; then - local mnemonic - mnemonic="$(tr -d '\n\r' < "$MNEMONIC_FILE")" - if [[ -n "$mnemonic" ]]; then - local derived_pk - derived_pk="$("$CAST" wallet private-key --mnemonic "$mnemonic" \ - --mnemonic-derivation-path "m/44'/60'/0'/0/0")" - local derived_addr - derived_addr="$("$CAST" wallet address --private-key "$derived_pk")" - DEPLOYER_PK=${DEPLOYER_PK:-$derived_pk} - DEPLOYER_ADDR=${DEPLOYER_ADDR:-$derived_addr} - fi - fi - - DEPLOYER_PK=${DEPLOYER_PK:-$DEFAULT_DEPLOYER_PK} - DEPLOYER_ADDR=${DEPLOYER_ADDR:-$DEFAULT_DEPLOYER_ADDR} -} - -ensure_tools() { - for cmd in "$ANVIL" "$FORGE" "$CAST" jq npm curl; do - if ! command -v "$cmd" >/dev/null 2>&1; then - log "Required command not found: $cmd" - exit 1 - fi - done -} - -start_directories() { - mkdir -p "$LOG_DIR" -} - -ensure_dependencies() { - if [[ ! -d "$ROOT_DIR/services/ponder/node_modules" ]]; then - log "Installing ponder dependencies" - pushd "$ROOT_DIR/services/ponder" >/dev/null - npm install >>"$SETUP_LOG" 2>&1 - popd >/dev/null - fi - - if [[ ! -d "$ROOT_DIR/web-app/node_modules" ]]; then - log "Installing web-app dependencies" - pushd "$ROOT_DIR/web-app" >/dev/null - npm install >>"$SETUP_LOG" 2>&1 - popd >/dev/null - fi - - if [[ ! -d "$ROOT_DIR/services/txnBot/node_modules" ]]; then - log "Installing txnBot dependencies" - pushd "$ROOT_DIR/services/txnBot" >/dev/null - npm install >>"$SETUP_LOG" 2>&1 - popd >/dev/null - fi -} - -start_anvil() { - if [[ -f "$ANVIL_PID_FILE" ]]; then - local existing_pid - existing_pid="$(cat "$ANVIL_PID_FILE")" - if kill -0 "$existing_pid" 2>/dev/null; then - log "Anvil already running (pid $existing_pid)" - return - fi - - log "Found stale Anvil pid file (pid $existing_pid); restarting Anvil" - rm -f "$ANVIL_PID_FILE" - fi - - log "Starting Anvil (forking $FORK_URL)" - local anvil_args=("--fork-url" "$FORK_URL" "--chain-id" 31337 "--block-time" 1 \ - "--host" 127.0.0.1 "--port" 8545 "--threads" 4 "--timeout" 2000 "--retries" 2 \ - "--fork-retry-backoff" 100) - - if [[ -f "$MNEMONIC_FILE" ]]; then - local mnemonic - mnemonic="$(tr -d '\n\r' < "$MNEMONIC_FILE")" - if [[ -n "$mnemonic" ]]; then - anvil_args+=("--mnemonic" "$mnemonic") - fi - fi - - "$ANVIL" "${anvil_args[@]}" >"$ANVIL_LOG" 2>&1 & - echo $! >"$ANVIL_PID_FILE" - - wait_for_rpc "$ANVIL_RPC" -} - -deploy_protocol() { - log "Deploying contracts" - pushd "$ROOT_DIR/onchain" >/dev/null - "$FORGE" script script/DeployLocal.sol --fork-url "$ANVIL_RPC" --broadcast \ - >>"$SETUP_LOG" 2>&1 - popd >/dev/null -} - -extract_addresses() { - local run_file - run_file="$(ls -t "$ROOT_DIR/onchain/broadcast/DeployLocal.sol"/*/run-latest.json 2>/dev/null | head -n1)" - if [[ -z "$run_file" || ! -f "$run_file" ]]; then - log "Deployment artifact not found under onchain/broadcast/DeployLocal.sol" - exit 1 - fi - - LIQUIDITY_MANAGER="$(jq -r '.transactions[] | select(.contractName=="LiquidityManager") | .contractAddress' "$run_file" | head -n1)" - KRAIKEN="$(jq -r '.transactions[] | select(.contractName=="Kraiken") | .contractAddress' "$run_file" | head -n1)" - STAKE="$(jq -r '.transactions[] | select(.contractName=="Stake") | .contractAddress' "$run_file" | head -n1)" - log "Using deployment artifact: ${run_file#$ROOT_DIR/}" - - if [[ -z "$LIQUIDITY_MANAGER" || "$LIQUIDITY_MANAGER" == "null" ]]; then - log "Failed to extract LiquidityManager address" - exit 1 - fi - - echo "LIQUIDITY_MANAGER=$LIQUIDITY_MANAGER" >"$STATE_DIR/contracts.env" - echo "KRAIKEN=$KRAIKEN" >>"$STATE_DIR/contracts.env" - echo "STAKE=$STAKE" >>"$STATE_DIR/contracts.env" - - # Get deployment block number - local deploy_block - deploy_block="$(jq -r '.receipts[0].blockNumber' "$run_file" | xargs printf "%d")" - - # Create .env.local for Ponder with deployed addresses - cat > "$ROOT_DIR/services/ponder/.env.local" <>"$SETUP_LOG" 2>&1 - - log "Granting recenter access" - "$CAST" rpc --rpc-url "$ANVIL_RPC" anvil_impersonateAccount "$FEE_DEST" >/dev/null - "$CAST" send --rpc-url "$ANVIL_RPC" --from "$FEE_DEST" --unlocked \ - "$LIQUIDITY_MANAGER" "setRecenterAccess(address)" "$DEPLOYER_ADDR" >>"$SETUP_LOG" 2>&1 - "$CAST" rpc --rpc-url "$ANVIL_RPC" anvil_stopImpersonatingAccount "$FEE_DEST" >/dev/null - - log "Calling recenter()" - "$CAST" send --rpc-url "$ANVIL_RPC" --private-key "$DEPLOYER_PK" \ - "$LIQUIDITY_MANAGER" "recenter()" >>"$SETUP_LOG" 2>&1 - - if [[ -n "$TXNBOT_ADDRESS" ]]; then - log "Transferring recenter access to txnBot $TXNBOT_ADDRESS" - "$CAST" rpc --rpc-url "$ANVIL_RPC" anvil_impersonateAccount "$FEE_DEST" >/dev/null - "$CAST" send --rpc-url "$ANVIL_RPC" --from "$FEE_DEST" --unlocked \ - "$LIQUIDITY_MANAGER" "setRecenterAccess(address)" "$TXNBOT_ADDRESS" >>"$SETUP_LOG" 2>&1 - "$CAST" rpc --rpc-url "$ANVIL_RPC" anvil_stopImpersonatingAccount "$FEE_DEST" >/dev/null - else - log "TXNBOT_ADDRESS not set; recenter access left with deployer" - fi -} - -prepare_application_state() { - source_addresses || { log "Contract addresses not found"; exit 1; } - - log "Wrapping 0.02 ETH into WETH" - "$CAST" send --rpc-url "$ANVIL_RPC" --private-key "$DEPLOYER_PK" \ - "$WETH" "deposit()" --value 0.02ether >>"$SETUP_LOG" 2>&1 - - log "Approving SwapRouter" \ - && "$CAST" send --rpc-url "$ANVIL_RPC" --private-key "$DEPLOYER_PK" \ - "$WETH" "approve(address,uint256)" "$SWAP_ROUTER" "$MAX_UINT" >>"$SETUP_LOG" 2>&1 - - log "Executing initial KRK buy" - "$CAST" send --legacy --gas-limit 300000 --rpc-url "$ANVIL_RPC" --private-key "$DEPLOYER_PK" \ - "$SWAP_ROUTER" "exactInputSingle((address,address,uint24,address,uint256,uint256,uint160))" \ - "($WETH,$KRAIKEN,10000,$DEPLOYER_ADDR,10000000000000000,0,0)" >>"$SETUP_LOG" 2>&1 -} - -prime_chain_for_indexing() { - log "Pre-mining blocks for indexer stability" - for _ in {1..2000}; do - "$CAST" rpc --rpc-url "$ANVIL_RPC" evm_mine > /dev/null 2>&1 || true - done -} - -write_txnbot_env() { - source_addresses || { log "Contract addresses not found"; exit 1; } - - cat > "$TXNBOT_ENV_FILE" <>"$SETUP_LOG" 2>&1 || \ - log "Funding txnBot wallet failed (see setup log)" - - # Ensure local fork balance reflects the funding even if the upstream state is zero - local fund_value_wei - fund_value_wei="$("$CAST" --to-unit "$TXNBOT_FUND_VALUE" wei)" - local fund_value_hex - fund_value_hex="$("$CAST" --to-hex "$fund_value_wei")" - "$CAST" rpc --rpc-url "$ANVIL_RPC" anvil_setBalance "$TXNBOT_ADDRESS" "$fund_value_hex" \ - >>"$SETUP_LOG" 2>&1 -} - -start_txnbot() { - if [[ -f "$TXNBOT_PID_FILE" ]]; then - log "txnBot already running (pid $(cat \"$TXNBOT_PID_FILE\"))" - return - fi - - write_txnbot_env - fund_txnbot_wallet - - log "Starting txnBot automation" - pushd "$ROOT_DIR/services/txnBot" >/dev/null - TXN_BOT_ENV_FILE="$TXNBOT_ENV_FILE" node service.js >"$TXNBOT_LOG" 2>&1 & - popd >/dev/null - echo $! >"$TXNBOT_PID_FILE" -} - -start_ponder() { - if [[ -f "$PONDER_PID_FILE" ]]; then - log "Ponder already running (pid $(cat "$PONDER_PID_FILE"))" - return - fi - - log "Starting Ponder indexer" - pushd "$ROOT_DIR/services/ponder" >/dev/null - PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK npm run dev >"$PONDER_LOG" 2>&1 & - popd >/dev/null - echo $! >"$PONDER_PID_FILE" - - wait_for_http "$GRAPHQL_HEALTH" -} - -start_frontend() { - if [[ -f "$WEBAPP_PID_FILE" ]]; then - log "Frontend already running (pid $(cat \"$WEBAPP_PID_FILE\"))" - return - fi - - source_addresses || { log "Contract addresses not found"; exit 1; } - - local vite_env=( - "VITE_DEFAULT_CHAIN_ID=31337" - "VITE_LOCAL_RPC_URL=/rpc/anvil" - "VITE_LOCAL_RPC_PROXY_TARGET=$ANVIL_RPC" - "VITE_KRAIKEN_ADDRESS=$KRAIKEN" - "VITE_STAKE_ADDRESS=$STAKE" - "VITE_LIQUIDITY_MANAGER=$LIQUIDITY_MANAGER" - "VITE_SWAP_ROUTER=$SWAP_ROUTER" - "VITE_PONDER_BASE_SEPOLIA_LOCAL_FORK=$GRAPHQL_ENDPOINT" - "VITE_TXNBOT_BASE_SEPOLIA_LOCAL_FORK=$LOCAL_TXNBOT_URL" - "VITE_ENABLE_EVENT_STREAM=false" - "VITE_POSITIONS_POLL_MS=0" - ) - - log "Starting frontend (Vite dev server)" - pushd "$ROOT_DIR/web-app" >/dev/null - env "${vite_env[@]}" npm run dev -- --host 0.0.0.0 --port 5173 >"$WEBAPP_LOG" 2>&1 & - popd >/dev/null - echo $! >"$WEBAPP_PID_FILE" - - wait_for_http "$FRONTEND_URL" -} - -start_environment() { - ensure_tools - set_deployer_credentials - start_directories - ensure_dependencies - start_anvil - deploy_protocol - extract_addresses - bootstrap_liquidity_manager - prepare_application_state - prime_chain_for_indexing - start_ponder # Re-enabled with PostgreSQL - start_txnbot - start_frontend -} - -start_and_wait() { - start_environment - source_addresses || true - log "Environment ready" - log " RPC: $ANVIL_RPC" - log " Kraiken: $KRAIKEN" - log " Stake: $STAKE" - log " LM: $LIQUIDITY_MANAGER" - log " Indexer: $GRAPHQL_HEALTH" - log " Frontend: $FRONTEND_URL" - log "Press Ctrl+C to shut everything down" - - wait "$(cat "$ANVIL_PID_FILE")" "$(cat "$PONDER_PID_FILE")" "$(cat "$WEBAPP_PID_FILE")" "$(cat "$TXNBOT_PID_FILE")" -} - -stop_environment() { - local previous_skip="$SKIP_CLEANUP" - SKIP_CLEANUP=false - cleanup - SKIP_CLEANUP="$previous_skip" - log "Environment stopped" -} - -on_exit() { - local status=$? - if [[ "$COMMAND" != "start" ]]; then - return - fi - - if [[ $status -ne 0 ]]; then - log "Start command exited with status $status" - if [[ -f "$SETUP_LOG" ]]; then - log "Last 40 lines of setup log:" - tail -n 40 "$SETUP_LOG" - fi - fi - - cleanup - - if [[ "$SKIP_CLEANUP" == true ]]; then - log "State directory preserved at $STATE_DIR" - else - log "Environment stopped" - fi -} - - -usage() { - cat </dev/null || true - printf '\n%-12s %-8s %-10s %s\n' "Service" "Status" "PID" "Details" - printf '%s\n' "-------------------------------------------------------------" - - service_status "Anvil" "$ANVIL_PID_FILE" "$ANVIL_LOG" - service_status "Ponder" "$PONDER_PID_FILE" "$PONDER_LOG" - service_status "Frontend" "$WEBAPP_PID_FILE" "$WEBAPP_LOG" - service_status "TxnBot" "$TXNBOT_PID_FILE" "$TXNBOT_LOG" - - if [[ -f "$STATE_DIR/contracts.env" ]]; then - printf '\nContracts:\n' - cat "$STATE_DIR/contracts.env" - printf '\n' - fi -} - -service_status() { - local name="$1" pid_file="$2" log_file="$3" - if [[ -f "$pid_file" ]]; then - local pid="$(cat "$pid_file")" - if kill -0 "$pid" 2>/dev/null; then - printf '%-12s %-8s %-10s %s\n' "$name" "running" "$pid" "$log_file" - return - fi - fi - printf '%-12s %-8s %-10s %s\n' "$name" "stopped" "-" "$log_file" -} - -COMMAND="start" - -while (($#)); do - case "$1" in - --no-cleanup) - SKIP_CLEANUP=true - ;; - start|stop|status) - COMMAND="$1" - ;; - *) - usage - exit 1 - ;; - esac - shift -done - -if [[ "$COMMAND" == "start" ]]; then - trap on_exit EXIT -fi - -case "$COMMAND" in - start) - trap 'log "Caught signal, stopping..."; exit 0' INT TERM - start_and_wait - ;; - stop) - stop_environment - ;; - status) - status_environment - ;; - *) - usage - exit 1 - ;; -esac diff --git a/services/ponder/AGENTS.md b/services/ponder/AGENTS.md index 488fa67..2fd3d44 100644 --- a/services/ponder/AGENTS.md +++ b/services/ponder/AGENTS.md @@ -14,7 +14,7 @@ Ponder-based indexer that records Kraiken protocol activity and exposes the Grap - `.ponder/` - Local SQLite/state cache (safe to delete when schemas change). ## Development Workflow -- Primary path: `nohup ./scripts/local_env.sh start &` boots Anvil, deploys contracts, and launches Ponder in watch mode. +- Primary path: `nohup ./scripts/dev.sh start &` boots Anvil, deploys contracts, and launches Ponder in watch mode. - Podman stack: `podman-compose up -d` starts all services including PostgreSQL; bootstrap creates `.env.local` automatically. - Focused debugging: within `services/ponder/`, run `npm install` then `PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK npm run dev` once the stack is already online. - For production-style runs, use `npm run build` followed by `PONDER_NETWORK=BASE npm run start` and point `DATABASE_URL` to PostgreSQL if persistence is required. diff --git a/services/ponder/README.md b/services/ponder/README.md index ded07fb..83764e5 100644 --- a/services/ponder/README.md +++ b/services/ponder/README.md @@ -26,7 +26,7 @@ cp .env.example .env ``` Edit `.env` to select your network: -- `PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK` - Local Anvil fork managed by `scripts/local_env.sh` +- `PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK` - Local Anvil fork managed by `scripts/dev.sh` - `PONDER_NETWORK=BASE_SEPOLIA` - Base Sepolia testnet - `PONDER_NETWORK=BASE` - Base mainnet diff --git a/services/txnBot/AGENTS.md b/services/txnBot/AGENTS.md index 8b8e30d..c5fe802 100644 --- a/services/txnBot/AGENTS.md +++ b/services/txnBot/AGENTS.md @@ -27,7 +27,7 @@ GRAPHQL_ENDPOINT= ``` ## Operations -- Launch via `nohup ./scripts/local_env.sh start &`; the script handles env injection and process supervision. +- Launch via `nohup ./scripts/dev.sh start &`; the script handles env injection and process supervision. - For focused debugging, run `npm install` then `npm start` within `services/txnBot/` after the stack is already up. - Monitor logs for transaction receipts and ensure gas pricing stays within acceptable bounds. diff --git a/services/txnBot/README.md b/services/txnBot/README.md index 174b366..ce6081a 100644 --- a/services/txnBot/README.md +++ b/services/txnBot/README.md @@ -6,7 +6,7 @@ Automation worker that monitors staking positions and calls `recenter()` / `payT The bot supports three environments shared across the stack: -- `BASE_SEPOLIA_LOCAL_FORK` – Anvil fork started by `scripts/local_env.sh` +- `BASE_SEPOLIA_LOCAL_FORK` – Anvil fork started by `scripts/dev.sh` - `BASE_SEPOLIA` – Public Base Sepolia testnet - `BASE` – Base mainnet @@ -26,7 +26,7 @@ GRAPHQL_ENDPOINT= # Optional: PORT=43069 ``` -`scripts/local_env.sh start` generates these values automatically for the local fork, writes them to a temporary file, and keeps the process running in the background. +`scripts/dev.sh start` generates these values automatically for the local fork, writes them to a temporary file, and keeps the process running in the background. ## Local Run diff --git a/web-app/src/views/CheatsView.vue b/web-app/src/views/CheatsView.vue index f5364fd..1d56364 100644 --- a/web-app/src/views/CheatsView.vue +++ b/web-app/src/views/CheatsView.vue @@ -10,7 +10,7 @@
-

Defaults to the Anvil instance from scripts/local_env.sh.

+

Defaults to the Anvil instance from scripts/dev.sh.