fix/podman-postgres-integration (#37)

resolves #25

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: johba <johba@harb.eth>
Reviewed-on: https://codeberg.org/johba/harb/pulls/37
This commit is contained in:
johba 2025-10-01 20:26:49 +02:00
parent 8947ec11ca
commit b4c829e4d6
25 changed files with 187 additions and 144 deletions

View file

@ -15,6 +15,7 @@ Ponder-based indexer that records Kraiken protocol activity and exposes the Grap
## Development Workflow
- Primary path: `nohup ./scripts/local_env.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.
@ -23,6 +24,18 @@ Ponder-based indexer that records Kraiken protocol activity and exposes the Grap
- Regenerate typings after schema edits by restarting Ponder; generated artifacts live in `generated/`.
- If the stack script fails during boot, check `.ponder/logs` and RPC quota usage before rerunning.
## Containerized Environment (Podman/Docker)
- **Environment Loading**: `.env.local` must be explicitly sourced in the entrypoint script before `npm run dev`. Ponder's built-in env loader may not find it in containerized environments.
- **Virtual Module Errors**: If you see `Failed to load url ponder:registry/ponder:schema/ponder:api`, check:
1. `DATABASE_URL` is properly set and accessible
2. kraiken-lib ABIs exist (`onchain/out/Kraiken.sol/Kraiken.json`)
3. kraiken-lib TypeScript is built (`kraiken-lib/dist/index.js`)
4. `ponder-env.d.ts` is writable by the container user (chmod 666 or pre-create it)
5. Ponder version is 0.13.8+ (earlier versions had virtual module generation bugs)
- **PostgreSQL Connection**: Requires `DATABASE_URL` env var; Ponder falls back to PGlite if not set. The entrypoint must export this before Ponder starts.
- **File Permissions**: Container runs as `node` user; ensure `ponder-env.d.ts` is writable (created with 666 permissions on host).
- **API Endpoint Requirement**: Ponder 0.13.8+ requires `src/api/index.ts` to exist, even if you only use GraphQL. Missing it causes "API endpoint file not found" errors.
## Quality Checks
- Avoid reintroducing legacy subgraph assumptions; rely solely on Ponder schema helpers.
- Keep handler logic deterministic and idempotent; reorgs trigger replays.

View file

@ -11,7 +11,7 @@
"@ponder/core": "^0.7.17",
"hono": "^4.5.0",
"kraiken-lib": "file:../../kraiken-lib",
"ponder": "^0.13.6",
"ponder": "^0.13.8",
"viem": "^2.21.0"
},
"devDependencies": {
@ -37,6 +37,7 @@
"@graphql-codegen/typescript-operations": "^4.2.0",
"@graphql-typed-document-node/core": "^3.2.0",
"@types/jest": "^29.5.12",
"@types/node": "^24.6.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"typescript": "^5.4.3"
@ -109,7 +110,8 @@
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.2.13.tgz",
"integrity": "sha512-YRY806NnScVqa21/1L1vaysSQ+0/cAva50z7vlwzaGiBOTS9JhdzIRHN0KfgMhobFAphbznZJ7urMso4RtMBIQ==",
"license": "Apache-2.0"
"license": "Apache-2.0",
"peer": true
},
"node_modules/@envelop/core": {
"version": "5.3.2",
@ -1011,6 +1013,7 @@
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">=8.0.0"
}
@ -1226,6 +1229,7 @@
"resolved": "https://registry.npmjs.org/kysely/-/kysely-0.26.3.tgz",
"integrity": "sha512-yWSgGi9bY13b/W06DD2OCDDHQmq1kwTGYlQ4wpZkMOJqMGCstVCFIvxCCVG4KfY1/3G0MhDAcZsip/Lw8/vJWw==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=14.0.0"
}
@ -1609,6 +1613,7 @@
"integrity": "sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==",
"devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@ -2139,6 +2144,7 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@ -2971,6 +2977,7 @@
"resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz",
"integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==",
"license": "MIT",
"peer": true,
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
@ -3028,6 +3035,7 @@
"resolved": "https://registry.npmjs.org/hono/-/hono-4.9.8.tgz",
"integrity": "sha512-JW8Bb4RFWD9iOKxg5PbUarBYGM99IcxFl2FPBo2gSJO11jjUDqlP1Bmfyqt8Z/dGhIQ63PMA9LdcLefXyIasyg==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=16.9.0"
}
@ -3967,6 +3975,7 @@
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
"integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
"license": "MIT",
"peer": true,
"dependencies": {
"pg-connection-string": "^2.9.1",
"pg-pool": "^3.10.1",
@ -4123,9 +4132,9 @@
"license": "MIT"
},
"node_modules/ponder": {
"version": "0.13.6",
"resolved": "https://registry.npmjs.org/ponder/-/ponder-0.13.6.tgz",
"integrity": "sha512-/LtSCfso7yshF7t7irNJyfQWvLfGI65quJiG4zaE902+coGm6YX9dqoVM+CxRtnOudSADTLsC3U3HAOJFfQXWQ==",
"version": "0.13.8",
"resolved": "https://registry.npmjs.org/ponder/-/ponder-0.13.8.tgz",
"integrity": "sha512-Eqj4ZBpft6/WOZdbW1XIVoUsrdMtfZMEtfX7P4wBgqc1YCSHCOFtQmLUB2QxAe/Qw+sO+eiCCk+BDCCMEXlOYA==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.23.4",
@ -4326,6 +4335,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@ -5017,6 +5027,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@ -5080,6 +5091,7 @@
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -5145,6 +5157,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"@noble/curves": "1.9.1",
"@noble/hashes": "1.8.0",
@ -5429,6 +5442,7 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10.0.0"
},

View file

@ -13,7 +13,7 @@
"@ponder/core": "^0.7.17",
"hono": "^4.5.0",
"kraiken-lib": "file:../../kraiken-lib",
"ponder": "^0.13.6",
"ponder": "^0.13.8",
"viem": "^2.21.0"
},
"devDependencies": {

View file

@ -9,12 +9,6 @@ declare module "ponder:schema" {
export * from "./ponder.schema.ts";
}
declare module "*.json" {
import type { Abi } from 'viem'
const value: { abi: Abi }
export default value
}
// This file enables type checking and editor autocomplete for this Ponder project.
// After upgrading, you may find that changes have been made to this file.
// If this happens, please commit the changes. Do not manually edit this file.

View file

@ -11,6 +11,8 @@ Automation service that maintains liquidity alignment and tax enforcement for th
- `service.js` - Main loop that polls the GraphQL endpoint, evaluates triggers, and submits transactions.
- `generateKey.js` - Utility for provisioning dedicated bot wallets.
- `package.json` scripts - `npm install`, `npm start`, and debug runs via `DEBUG=* npm start`.
- **ES Module**: This service uses `"type": "module"` and imports kraiken-lib as an ES module. All imports use ES module syntax (`import` instead of `require()`).
- **Node.js Compatibility**: Requires Node.js ≥14 with ES module support. The `__dirname` and `__filename` globals are not available; use `import.meta.url` with `fileURLToPath()` instead.
## Configuration
Set the following environment variables (automatically generated when the stack script is used):

View file

@ -1,6 +1,7 @@
{
"name": "marketMaker",
"version": "0.0.1",
"type": "module",
"main": "index.js",
"license": "GPL3",
"scripts": {

View file

@ -1,13 +1,19 @@
const path = require('path');
import path from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import { ethers } from 'ethers';
import express from 'express';
import { decodePositionId } from 'kraiken-lib/ids';
import { isPositionDelinquent } from 'kraiken-lib/staking';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const dotenvPath = process.env.TXN_BOT_ENV_FILE
? path.resolve(process.env.TXN_BOT_ENV_FILE)
: path.resolve(__dirname, '.env');
require('dotenv').config({ path: dotenvPath });
const { ethers } = require('ethers');
const express = require('express');
const { decodePositionId } = require('kraiken-lib/ids');
const { isPositionDelinquent } = require('kraiken-lib/staking');
dotenv.config({ path: dotenvPath });
const ACTIVE_POSITIONS_QUERY = `
query ActivePositions {