diff --git a/app/data/compose/docker-compose-ponder.yml b/app/data/compose/docker-compose-ponder-indexer.yml similarity index 70% rename from app/data/compose/docker-compose-ponder.yml rename to app/data/compose/docker-compose-ponder-indexer.yml index a18f4ec6..233ecbd7 100644 --- a/app/data/compose/docker-compose-ponder.yml +++ b/app/data/compose/docker-compose-ponder-indexer.yml @@ -15,16 +15,16 @@ services: extra_hosts: - "host.docker.internal:host-gateway" - ponder-app-indexer: - hostname: ponder-app-indexer + ponder-app-indexer-1: + hostname: ponder-app-indexer-1 restart: unless-stopped image: cerc/ponder:local working_dir: /app/examples/token-erc20 environment: CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99} CERC_PONDER_RPC_URL_1: ${PONDER_RPC_URL_1:-http://ipld-eth-server-2:8081} - CERC_PONDER_NITRO_PK: ${CERC_PONDER_INDEXER_NITRO_PK:-58368d20ff12f17669c06158c21d885897aa56f9be430edc789614bf9851d53f} - CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_INDEXER_NITRO_CHAIN_PK:-fb1e9af328c283ca3e2486e7c24d13582b7912057d8b9542ff41503c85bc05c0} + CERC_PONDER_NITRO_PK: ${CERC_PONDER_INDEXER_NITRO_PK_1:-58368d20ff12f17669c06158c21d885897aa56f9be430edc789614bf9851d53f} + CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_INDEXER_NITRO_CHAIN_PK_1:-fb1e9af328c283ca3e2486e7c24d13582b7912057d8b9542ff41503c85bc05c0} CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546} CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR} CERC_UPSTREAM_NITRO_ADDRESS: ${CERC_UPSTREAM_NITRO_ADDRESS:-0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e} @@ -33,44 +33,42 @@ services: command: ["bash", "./ponder-start.sh"] volumes: - ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh - - ../config/ponder/ponder.indexer.config.ts:/app/examples/token-erc20/ponder.config.ts + - ../config/ponder/ponder.indexer-1.config.ts:/app/examples/token-erc20/ponder.config.ts - ../config/ponder/base-rates-config.json:/app/examples/token-erc20/base-rates-config.json - peers_ids:/peers - nitro_deployment:/nitro - erc20_deployment:/erc20 - - ponder_indexer_nitro_data:/app/examples/token-erc20/.ponder/nitro-db + - ponder_indexer_1_nitro_data:/app/examples/token-erc20/.ponder/nitro-db ports: - - "42070" + - "127.0.0.1:42070:42070" extra_hosts: - "host.docker.internal:host-gateway" - ponder-app-watcher: - hostname: ponder-app-watcher - depends_on: - - ponder-app-indexer + ponder-app-indexer-2: + hostname: ponder-app-indexer-2 restart: unless-stopped image: cerc/ponder:local working_dir: /app/examples/token-erc20 environment: CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99} - CERC_PONDER_NITRO_PK: ${CERC_PONDER_WATCHER_NITRO_PK:-febb3b74b0b52d0976f6571d555f4ac8b91c308dfa25c7b58d1e6a7c3f50c781} - CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_WATCHER_NITRO_CHAIN_PK:-be4aa664815ea3bc3d63118649a733f6c96b243744310806ecb6d96359ab62cf} + CERC_INDEXER_GQL_ENDPOINT: ${CERC_INDEXER_GQL_ENDPOINT:-http://ponder-app-indexer-1:42070/graphql} + CERC_PONDER_NITRO_PK: ${CERC_PONDER_INDEXER_NITRO_PK_2:-0aca28ba64679f63d71e671ab4dbb32aaa212d4789988e6ca47da47601c18fe2} + CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_INDEXER_NITRO_CHAIN_PK_2:-6177345b77c4069ac4d553f8b43cf68a799ca4bb63eac93d6cf796d63694ebf0} CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546} CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR} - CERC_INDEXER_GQL_ENDPOINT: ${CERC_INDEXER_GQL_ENDPOINT:-http://ponder-app-indexer:42070/graphql} CERC_INDEXER_NITRO_ADDRESS: ${CERC_INDEXER_NITRO_ADDRESS:-0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d} - CERC_INDEXER_NITRO_PAY_AMOUNT: ${CERC_INDEXER_NITRO_PAY_AMOUNT:-50} + CERC_UPSTREAM_NITRO_PAY_AMOUNT: ${CERC_UPSTREAM_NITRO_PAY_AMOUNT:-100} command: ["bash", "./ponder-start.sh"] volumes: - ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh - - ../config/ponder/ponder.watcher.config.ts:/app/examples/token-erc20/ponder.config.ts + - ../config/ponder/ponder.indexer-2.config.ts:/app/examples/token-erc20/ponder.config.ts - ../config/ponder/base-rates-config.json:/app/examples/token-erc20/base-rates-config.json - peers_ids:/peers - nitro_deployment:/nitro - erc20_deployment:/erc20 - - ponder_watcher_nitro_data:/app/examples/token-erc20/.ponder/nitro-db + - ponder_indexer_2_nitro_data:/app/examples/token-erc20/.ponder/nitro-db ports: - - "42069" + - "127.0.0.1:42071:42070" extra_hosts: - "host.docker.internal:host-gateway" @@ -78,5 +76,5 @@ volumes: peers_ids: nitro_deployment: erc20_deployment: - ponder_indexer_nitro_data: - ponder_watcher_nitro_data: + ponder_indexer_1_nitro_data: + ponder_indexer_2_nitro_data: diff --git a/app/data/compose/docker-compose-ponder-watcher.yml b/app/data/compose/docker-compose-ponder-watcher.yml new file mode 100644 index 00000000..030782d7 --- /dev/null +++ b/app/data/compose/docker-compose-ponder-watcher.yml @@ -0,0 +1,39 @@ + +version: '3.7' + +services: + ponder-app-watcher: + hostname: ponder-app-watcher + depends_on: + - ponder-app-indexer-1 + restart: unless-stopped + image: cerc/ponder:local + working_dir: /app/examples/token-erc20 + environment: + CERC_PONDER_CHAIN_ID: ${PONDER_CHAIN_ID:-99} + CERC_PONDER_NITRO_PK: ${CERC_PONDER_WATCHER_NITRO_PK:-febb3b74b0b52d0976f6571d555f4ac8b91c308dfa25c7b58d1e6a7c3f50c781} + CERC_PONDER_NITRO_CHAIN_PK: ${CERC_PONDER_WATCHER_NITRO_CHAIN_PK:-be4aa664815ea3bc3d63118649a733f6c96b243744310806ecb6d96359ab62cf} + CERC_PONDER_NITRO_CHAIN_URL: ${CERC_PONDER_NITRO_CHAIN_URL:-http://fixturenet-eth-geth-1:8546} + CERC_RELAY_MULTIADDR: ${CERC_RELAY_MULTIADDR} + CERC_INDEXER_GQL_ENDPOINT: ${CERC_INDEXER_GQL_ENDPOINT:-http://ponder-app-indexer-2:42070/graphql} + CERC_INDEXER_NITRO_ADDRESS: ${CERC_INDEXER_NITRO_ADDRESS:-0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01} + CERC_INDEXER_NITRO_PAY_AMOUNT: ${CERC_INDEXER_NITRO_PAY_AMOUNT:-50} + command: ["bash", "./ponder-start.sh"] + volumes: + - ../config/ponder/ponder-start.sh:/app/examples/token-erc20/ponder-start.sh + - ../config/ponder/ponder.watcher.config.ts:/app/examples/token-erc20/ponder.config.ts + - ../config/ponder/base-rates-config.json:/app/examples/token-erc20/base-rates-config.json + - peers_ids:/peers + - nitro_deployment:/nitro + - erc20_deployment:/erc20 + - ponder_watcher_nitro_data:/app/examples/token-erc20/.ponder/nitro-db + ports: + - "127.0.0.1:42069:42069" + extra_hosts: + - "host.docker.internal:host-gateway" + +volumes: + peers_ids: + nitro_deployment: + erc20_deployment: + ponder_watcher_nitro_data: diff --git a/app/data/config/ponder/base-rates-config.json b/app/data/config/ponder/base-rates-config.json index 5012f980..1b385875 100644 --- a/app/data/config/ponder/base-rates-config.json +++ b/app/data/config/ponder/base-rates-config.json @@ -2,7 +2,9 @@ "freeQueriesLimit": 10, "freeQueriesList": [], "queries": { - "getLogEvents": "50" + "getLogEvents": "50", + "getEthLogs": "50", + "getEthBlock": "50" }, "mutations": {} } diff --git a/app/data/config/ponder/deploy-erc20-contract.sh b/app/data/config/ponder/deploy-erc20-contract.sh index 4387bc19..ea8111bb 100755 --- a/app/data/config/ponder/deploy-erc20-contract.sh +++ b/app/data/config/ponder/deploy-erc20-contract.sh @@ -7,11 +7,16 @@ fi erc20_address_file="/app/deployment/erc20-address.json" -# Check and exit if a deployment already exists (on restarts) +echo ETH_RPC_URL=${CERC_ETH_RPC_ENDPOINT} > .env +echo ACCOUNT_PRIVATE_KEY=${CERC_PRIVATE_KEY_DEPLOYER} >> .env + +# Check and keep container running if a deployment already exists (on restarts) if [ -f ${erc20_address_file} ]; then echo "${erc20_address_file} already exists, skipping ERC20 contract deployment" cat ${erc20_address_file} - exit + + # Keep the container running + tail -f fi wait_for_chain_endpoint() { @@ -46,8 +51,6 @@ wait_for_chain_endpoint echo "Using CERC_PRIVATE_KEY_DEPLOYER from env" -echo ETH_RPC_URL=${CERC_ETH_RPC_ENDPOINT} > .env -echo ACCOUNT_PRIVATE_KEY=${CERC_PRIVATE_KEY_DEPLOYER} >> .env yarn token:deploy:docker --file ${erc20_address_file} # Keep the container running diff --git a/app/data/config/ponder/ponder.indexer.config.ts b/app/data/config/ponder/ponder.indexer-1.config.ts similarity index 98% rename from app/data/config/ponder/ponder.indexer.config.ts rename to app/data/config/ponder/ponder.indexer-1.config.ts index dac02724..31ae699c 100644 --- a/app/data/config/ponder/ponder.indexer.config.ts +++ b/app/data/config/ponder/ponder.indexer-1.config.ts @@ -35,7 +35,7 @@ export const config: Config = { network: "fixturenet", abi: "./abis/AdventureGold.json", address: process.env.ERC20_CONTRACT, - startBlock: 5, + startBlock: 1, maxBlockRange: 100, }, ], diff --git a/app/data/config/ponder/ponder.indexer-2.config.ts b/app/data/config/ponder/ponder.indexer-2.config.ts new file mode 100644 index 00000000..c8e1b610 --- /dev/null +++ b/app/data/config/ponder/ponder.indexer-2.config.ts @@ -0,0 +1,64 @@ +import { type Config, AppMode } from "@ponder/core"; + +import contractAddresses from "./nitro-addresses.json" assert { type: "json" }; + +export const config: Config = { + networks: [ + { + name: "fixturenet", + chainId: Number(process.env.PONDER_CHAIN_ID), + indexerUrl: process.env.INDEXER_GQL_ENDPOINT, + maxRpcRequestConcurrency: 1, + pollingInterval: 5000, + payments: { + nitro: { + address: process.env.INDEXER_NITRO_ADDRESS!, + fundingAmounts: { + // TODO: Pass amounts from env + directFund: "1000000000000", + virtualFund: "1000000000", + }, + }, + paidRPCMethods: [ + "eth_getLogs", + "eth_getBlockByNumber", + "eth_getBlockByHash", + ], + amount: process.env.UPSTREAM_NITRO_PAY_AMOUNT!, + }, + }, + ], + contracts: [ + { + name: "AdventureGold", + network: "fixturenet", + abi: "./abis/AdventureGold.json", + address: process.env.ERC20_CONTRACT, + startBlock: 1, + maxBlockRange: 100, + }, + ], + options: { + mode: AppMode.Indexer, + }, + nitro: { + privateKey: process.env.PONDER_NITRO_PK!, + chainPrivateKey: process.env.PONDER_NITRO_CHAIN_PK!, + chainUrl: process.env.PONDER_NITRO_CHAIN_URL!, + contractAddresses, + relayMultiAddr: process.env.RELAY_MULTIADDR!, + store: "./.ponder/nitro-db", + payments: { + cache: { + maxAccounts: 1000, + accountTTLInSecs: 1800, + maxVouchersPerAccount: 1000, + voucherTTLInSecs: 300, + maxPaymentChannels: 10000, + paymentChannelTTLInSecs: 1800, + }, + ratesFile: "./base-rates-config.json", + requestTimeoutInSecs: 10, + }, + }, +}; diff --git a/app/data/config/ponder/ponder.watcher.config.ts b/app/data/config/ponder/ponder.watcher.config.ts index ab62f246..19e4ecb1 100644 --- a/app/data/config/ponder/ponder.watcher.config.ts +++ b/app/data/config/ponder/ponder.watcher.config.ts @@ -15,7 +15,7 @@ export const config: Config = { network: "fixturenet", abi: "./abis/AdventureGold.json", address: process.env.ERC20_CONTRACT, - startBlock: 5, + startBlock: 1, maxBlockRange: 100, }, ], diff --git a/app/data/stacks/fixturenet-payments/README.md b/app/data/stacks/fixturenet-payments/README.md index 3fe66bba..ebde79ee 100644 --- a/app/data/stacks/fixturenet-payments/README.md +++ b/app/data/stacks/fixturenet-payments/README.md @@ -29,7 +29,7 @@ laconic-so --stack fixturenet-payments deploy --cluster payments up # 32***: geth in statediffing mode and ipld-eth-server(s) # 4005: in-process go-nitro node's RPC endpoint # 3005: in-process go-nitro node's p2p TCP endpoint -# 5005: in-process go-nitro node's p2p WS endpoin +# 5005: in-process go-nitro node's p2p WS endpoint # 4006: out-of-process go-nitro node's RPC endpoint # 3006: out-of-process go-nitro node's p2p TCP endpoint # 5006: out-of-process go-nitro node's p2p WS endpoint @@ -38,7 +38,9 @@ laconic-so --stack fixturenet-payments deploy --cluster payments up # 9090: MobyMask v3 watcher relay node endpoint # 8080: MobyMask snap # 3004: MobyMask v3 app -# 32***: geth with statediffing +# 42070: Ponder indexer-1 +# 42071: Ponder indexer-2 +# 42069: Ponder watcher ``` If running in the cloud, ensure all the of the above ports are open. The geth port can be retrieved with: @@ -60,7 +62,8 @@ This will allow you to access the entirety of the app as if it were running loca ## Demo -Follow the [demo](./demo.md) to try out end-to-end payments. +- Follow the [mobymask-demo](./mobymask-demo.md) to try out MobyMask end-to-end payments. +- Follow the [ponder-demo](./ponder-demo.md) to try out Ponder end-to-end payments. ## Clean up diff --git a/app/data/stacks/fixturenet-payments/demo.md b/app/data/stacks/fixturenet-payments/mobymask-demo.md similarity index 64% rename from app/data/stacks/fixturenet-payments/demo.md rename to app/data/stacks/fixturenet-payments/mobymask-demo.md index 910f0dde..65d93e85 100644 --- a/app/data/stacks/fixturenet-payments/demo.md +++ b/app/data/stacks/fixturenet-payments/mobymask-demo.md @@ -3,13 +3,10 @@ Stack components: * `ipld-eth-db` database for statediffed data * Local geth + lighthouse blockchain "fixturenet" running in statediffing mode -* `ipld-eth-server-1` and `ipld-eth-server-2` both of which run an ETH RPC API and a GQL server; they both serve data from `ipld-eth-db` -* `ipld-eth-server-1` runs an in-process go-nitro node for payments required for configured RPC requests -* A go-nitro deployment acting as the remote Nitro node for `ipld-eth-server-2` +* `ipld-eth-server-1` which runs an ETH RPC API and a GQL server; they both serve data from `ipld-eth-db` + * It runs an in-process go-nitro node for payments required for configured RPC requests * A MobyMask v3 watcher that pays the `ipld-eth-server-1` for ETH RPC requests * A MobyMask v3 app that pays the watcher for reads (GQL queries) and writes -* An example ERC20 Ponder indexer app that pays the `ipld-eth-server-2` for ETH RPC requests -* An example ERC20 Ponder watcher app that pays the Ponder indexer app for GQL queries ## Setup @@ -61,12 +58,6 @@ Stack components: docker logs -f $(docker ps -aq --filter name="ipld-eth-server-1") ``` -* In another terminal, check `ipld-eth-server-2`'s logs to keep track of incoming RPC requests from the Ponder app in indexer mode: - - ```bash - docker logs -f $(docker ps -aq --filter name="ipld-eth-server-2") - ``` - * MetaMask flask wallet setup for running the MobyMask app: * Get the geth node’s port mapped to host: @@ -213,96 +204,6 @@ Stack components: # } ``` -### ERC20 Ponder App - -* Run the ponder app in indexer mode: - - ```bash - docker exec -it payments-ponder-app-indexer-1 bash -c "DEBUG=laconic:payments pnpm start" - - # Expected output: - # 08:00:28.701 INFO payment Nitro node setup with address 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d - # laconic:payments Starting voucher subscription... +0ms - # ... - # 09:58:54.288 INFO payment Creating ledger channel with nitro node 0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e - # ... - # 09:59:14.230 INFO payment Creating payment channel with nitro node 0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e - # ... - # 09:59:14.329 INFO payment Using payment channel 0x10f049519bc3f862e2b26e974be8666886228f30ea54aab06e2f23718afffab0 - ``` - -* Export the payment channel id to a variable: - - ```bash - export PONDER_UPSTREAM_PAYMENT_CHANNEL= - ``` - -* On starting the Ponder app in indexer mode, it creates a payment channel with the `ipld-eth-server-2`'s (external) Nitro node and then starts the historical sync service - -* The sync service makes several ETH RPC requests to the `ipld-eth-server-2` to fetch required data; check the `ipld-eth-server-2` logs for charged RPC requests (`eth_getBlockByNumber`, `eth_getLogs`): - - ```bash - # Expected output: - # ... - # 2023/10/18 05:29:38 INFO Serving a paid RPC request method=eth_getBlockByNumber cost=50 sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d - # time="2023-10-18T05:29:38Z" level=debug msg=START api_method=eth_getBlockByNumber api_params="[latest true]" api_reqid=0 conn="172.26.0.19:42306" user_id= uuid=54992dc3-6d77-11ee-9ede-0242ac1a000f - # WARN [10-18|05:29:38.292] Attempting GerRPCCalls, but default PluginLoader has not been initialized - # time="2023-10-18T05:29:38Z" level=debug msg=END api_method=eth_getBlockByNumber api_params="[latest true]" api_reqid=0 conn="172.26.0.19:42306" duration=22 user_id= uuid=54992dc3-6d77-11ee-9ede-0242ac1a000f - # time="2023-10-18T05:29:40Z" level=debug msg=START api_method=eth_getLogs api_params="[map[address:0x32353a6c91143bfd6c7d363b546e62a9a2489a20 fromBlock:0x5 toBlock:0x68]]" api_reqid=1 conn="172.26.0.19:42306" user_id= uuid=55d19200-6d77-11ee-9ede-0242ac1a000f - # 2023/10/18 05:29:40 INFO Serving a paid RPC request method=eth_getLogs cost=50 sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d - # WARN [10-18|05:29:40.340] Attempting GerRPCCalls, but default PluginLoader has not been initialized - # time="2023-10-18T05:29:40Z" level=debug msg="retrieving log cids for receipt ids" - # time="2023-10-18T05:29:40Z" level=debug msg=END api_method=eth_getLogs api_params="[map[address:0x32353a6c91143bfd6c7d363b546e62a9a2489a20 fromBlock:0x5 toBlock:0x68]]" api_reqid=1 conn="172.26.0.19:42306" duration=20 user_id= uuid=55d19200-6d77-11ee-9ede-0242ac1a000f - # ... - ``` - -* Check the ponder - ipld-eth-server-2 payment channel status: - - ```bash - docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $PONDER_UPSTREAM_PAYMENT_CHANNEL -s false -h go-nitro -p 4006" - - # Expected output ('PaidSoFar' is non zero): - # { - # ID: '0x1178ac0f2a43e54a122216fa6afdd30333b590e49e50317a1f9274a591da0f96', - # Status: 'Open', - # Balance: { - # AssetAddress: '0x0000000000000000000000000000000000000000', - # Payee: '0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce', - # Payer: '0x67d5b55604d1af90074fcb69b8c51838fff84f8d', - # PaidSoFar: 215000n, - # RemainingFunds: 999785000n - # } - # } - ``` - -* In another terminal run the ponder app in watcher mode: - - ```bash - docker exec -it payments-ponder-app-watcher-1 bash -c "DEBUG=laconic:payments pnpm start" - - # Expected output: - # 11:23:22.057 DEBUG app Started using config file: ponder.config.ts - # 08:02:12.548 INFO payment Nitro node setup with address 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db - # laconic:payments Starting voucher subscription... +0ms - # 08:02:17.417 INFO payment Creating ledger channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ... - # 08:02:37.135 INFO payment Creating payment channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ... - # 08:02:37.313 INFO payment Using payment channel 0x4b8e67f6a6fcfe114fdd60b85f963344ece4c77d4eea3825688c74b45ff5509b - # ... - # 11:23:22.436 INFO server Started responding as healthy - ``` - -* Check the terminal in which ponder is running in indexer mode. Logs of payment for `eth_getLogs` queries can be seen: - - ```bash - # ... - # 08:02:37.763 DEBUG realtime Finished processing new head block 89 (network=fixturenet) - # laconic:payments Received a payment voucher of 50 from 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +444ms - # laconic:payments Serving a paid query for 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +1ms - # 08:02:37.804 DEBUG payment Verified payment for GQL queries getLogEvents - # laconic:payments Received a payment voucher of 50 from 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +45ms - # laconic:payments Serving a paid query for 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +0ms - # 08:02:37.849 DEBUG payment Verified payment for GQL queries getLogEvents - ``` ## Clean Up diff --git a/app/data/stacks/fixturenet-payments/ponder-demo.md b/app/data/stacks/fixturenet-payments/ponder-demo.md new file mode 100644 index 00000000..c915883b --- /dev/null +++ b/app/data/stacks/fixturenet-payments/ponder-demo.md @@ -0,0 +1,182 @@ +# Demo + +Stack components: +* `ipld-eth-db` database for statediffed data +* Local geth + lighthouse blockchain "fixturenet" running in statediffing mode +* `ipld-eth-server-2` which runs an ETH RPC API and a GQL server; they both serve data from `ipld-eth-db` +* A go-nitro deployment acting as the remote Nitro node for `ipld-eth-server-2` +* Example ERC20 Ponder apps + * `ponder-app-indexer-1` that pays the `ipld-eth-server-2` for ETH RPC requests + * `ponder-app-indexer-2` that pays `ponder-app-indexer-1` for GQL queries + * `ponder-app-watcher` that pays `ponder-app-indexer-2` for GQL queries + +## Setup + +* In a terminal, check `ipld-eth-server-2`'s logs to keep track of incoming RPC requests from the `ponder-app-indexer-1`: + + ```bash + docker logs -f $(docker ps -aq --filter name="ipld-eth-server-2") + ``` + +## Run + +### ERC20 Ponder App + +* Run the first indexer Ponder app: + + ```bash + docker exec -it payments-ponder-app-indexer-1-1 bash -c "DEBUG=laconic:payments pnpm start" + + # Expected output: + # 12:57:03.751 INFO payment Nitro node setup with address 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d + # laconic:payments Starting voucher subscription... +0ms + # ... + # 09:58:54.288 INFO payment Creating ledger channel with nitro node 0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e ... + # 09:59:14.230 INFO payment Creating payment channel with nitro node 0x660a4bEF3fbC863Fcd8D3CDB39242aE513d7D92e ... + # 09:59:14.329 INFO payment Using payment channel 0x1ff59db391b7a55bed723b930ab53c80e7ce857487c1e58771aa5a0737d71625 + ``` + +* Export the payment channel id to a variable: + + ```bash + export PONDER_UPSTREAM_PAYMENT_CHANNEL= + ``` + +* On starting the Ponder app in indexer mode, it creates a payment channel with the `ipld-eth-server-2`'s (external) Nitro node and then starts the historical sync service + +* The sync service makes several ETH RPC requests to the `ipld-eth-server-2` to fetch required data; check the `ipld-eth-server-2` logs for charged RPC requests (`eth_getBlockByNumber`, `eth_getLogs`): + + ```bash + # Expected output: + # ... + # 2023/10/18 05:29:38 INFO Serving a paid RPC request method=eth_getBlockByNumber cost=50 sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d + # time="2023-10-18T05:29:38Z" level=debug msg=START api_method=eth_getBlockByNumber api_params="[latest true]" api_reqid=0 conn="172.26.0.19:42306" user_id= uuid=54992dc3-6d77-11ee-9ede-0242ac1a000f + # WARN [10-18|05:29:38.292] Attempting GerRPCCalls, but default PluginLoader has not been initialized + # time="2023-10-18T05:29:38Z" level=debug msg=END api_method=eth_getBlockByNumber api_params="[latest true]" api_reqid=0 conn="172.26.0.19:42306" duration=22 user_id= uuid=54992dc3-6d77-11ee-9ede-0242ac1a000f + # ... + # 2023/10/18 05:29:40 INFO Serving a paid RPC request method=eth_getLogs cost=50 sender=0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d + # WARN [10-18|05:29:40.340] Attempting GerRPCCalls, but default PluginLoader has not been initialized + # time="2023-10-18T05:29:40Z" level=debug msg="retrieving log cids for receipt ids" + # ... + ``` + +* Check the Ponder - ipld-eth-server-2 payment channel status: + + ```bash + docker exec payments-nitro-rpc-client-1 npm exec -c "nitro-rpc-client get-payment-channel $PONDER_UPSTREAM_PAYMENT_CHANNEL -s false -h go-nitro -p 4006" + + # Expected output ('PaidSoFar' is non zero): + # { + # ID: '0x1ff59db391b7a55bed723b930ab53c80e7ce857487c1e58771aa5a0737d71625', + # Status: 'Open', + # Balance: { + # AssetAddress: '0x0000000000000000000000000000000000000000', + # Payee: '0x660a4bef3fbc863fcd8d3cdb39242ae513d7d92e', + # Payer: '0x67d5b55604d1af90074fcb69b8c51838fff84f8d', + # PaidSoFar: 7200n, + # RemainingFunds: 999992800n + # } + # } + ``` + +* In another terminal run the second indexer Ponder app: + + ```bash + docker exec -it payments-ponder-app-indexer-2-1 bash -c "DEBUG=laconic:payments pnpm start" + + # Expected output: + # 08:00:28.701 INFO payment Nitro node setup with address 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 + # laconic:payments Starting voucher subscription... +0ms + # ... + # 09:58:54.288 INFO payment Creating ledger channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ... + # 09:59:14.230 INFO payment Creating payment channel with nitro node 0x67D5b55604d1aF90074FcB69b8C51838FFF84f8d ... + # 09:59:14.329 INFO payment Using payment channel 0xfbf9d7eb7c18446883c7f57f4c94db5607f414a224b3e921c787db07371d2a70 + ``` + +* On starting indexer Ponder app, it creates a payment channel with first indexer and then starts the sync services + +* Check logs in `ponder-indexer-1` to see payments made from `ponder-indexer-2` from GQL queries to fetch network data + + ```bash + # ... + # laconic:payments Received a payment voucher of 100 from 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +23ms + # laconic:payments Serving a paid query for 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +0ms + # 13:01:05.671 DEBUG payment Verified payment for GQL queries getEthLogs + # laconic:payments Received a payment voucher of 100 from 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +20ms + # laconic:payments Serving a paid query for 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 +0ms + # 13:01:05.691 DEBUG payment Verified payment for GQL queries getEthBlock + # 13:01:07.598 INFO realtime Fetched missing blocks [686, 687] (network=fixturenet) + # 13:01:07.598 DEBUG realtime Started processing new head block 686 (network=fixturenet) + # ... + ``` + +* In another terminal run the Ponder app in watcher mode: + + ```bash + docker exec -it payments-ponder-app-watcher-1 bash -c "DEBUG=laconic:payments pnpm start" + + # Expected output: + # 11:23:22.057 DEBUG app Started using config file: ponder.config.ts + # 08:02:12.548 INFO payment Nitro node setup with address 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db + # laconic:payments Starting voucher subscription... +0ms + # 08:02:17.417 INFO payment Creating ledger channel with nitro node 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 ... + # 08:02:37.135 INFO payment Creating payment channel with nitro node 0xB2B22ec3889d11f2ddb1A1Db11e80D20EF367c01 ... + # 08:02:37.313 INFO payment Using payment channel 0xc48622577dfa389283beb19ed946274eb034587d72e61445dc997304be671f1a + # ... + # 11:23:22.436 INFO server Started responding as healthy + ``` + +* Check the terminal of the second indexer Ponder app. Logs of payment for `getLogEvents` queries can be seen: + + ```bash + # ... + # 08:02:37.763 DEBUG realtime Finished processing new head block 89 (network=fixturenet) + # laconic:payments Received a payment voucher of 50 from 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +444ms + # laconic:payments Serving a paid query for 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +1ms + # 08:02:37.804 DEBUG payment Verified payment for GQL queries getLogEvents + # laconic:payments Received a payment voucher of 50 from 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +45ms + # laconic:payments Serving a paid query for 0x111A00868581f73AB42FEEF67D235Ca09ca1E8db +0ms + # 08:02:37.849 DEBUG payment Verified payment for GQL queries getLogEvents + ``` + +* Open watcher Ponder app endpoint http://localhost:42069 + + * Try GQL query to see transfer events + + ```graphql + { + transferEvents (orderBy: "timestamp", orderDirection: "desc") { + id + amount + from { + id + } + to { + id + } + timestamp + } + } + ``` + +* Transfer an ERC20 token on chain + + * Get the deployed ERC20 token address + + ```bash + export TOKEN_ADDRESS=$(docker exec payments-ponder-er20-contracts-1 jq -r '.address' ./deployment/erc20-address.json) + ``` + + * Transfer token + + ```bash + docker exec -it payments-ponder-er20-contracts-1 bash -c "yarn token:transfer:docker --token ${TOKEN_ADDRESS} --to 0xe22AD83A0dE117bA0d03d5E94Eb4E0d80a69C62a --amount 5000" + ``` + +* Wait for a log in watcher Ponder app + + ```bash + 06:40:47.567 INFO handlers Processed 1 event (up to Oct 19, 2023) + ``` + +* Check the GQL query again in http://localhost:42069 to see a new `TransferEvent` entity diff --git a/app/data/stacks/fixturenet-payments/stack.yml b/app/data/stacks/fixturenet-payments/stack.yml index 27d73b30..e13d303c 100644 --- a/app/data/stacks/fixturenet-payments/stack.yml +++ b/app/data/stacks/fixturenet-payments/stack.yml @@ -10,7 +10,7 @@ repos: - git.vdb.to/cerc-io/ipld-eth-server@payments # nitro repo - github.com/cerc-io/ts-nitro@v0.1.15 - - github.com/cerc-io/go-nitro@ts-interop # TODO: Use release + - github.com/cerc-io/go-nitro@v0.1.2-ts-port-0.1.9 # mobymask watcher repos - github.com/cerc-io/watcher-ts@v0.2.66 # this is mobymask-v3 @@ -55,4 +55,5 @@ pods: - watcher-mobymask-v3 - mobymask-snap - mobymask-app-v3 - - ponder + - ponder-indexer + - ponder-watcher