From 17e49d60dc4ec23deee02d228bf4dcfff7654c04 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Sun, 7 Sep 2025 20:46:52 -0300 Subject: [PATCH 01/17] fixed configs and scripts to run avail in port 9955 --- .../binaries/avail-light-client/config.yml | 48 +++++++++---------- .../shared/contracts/avail/config.yml | 46 ++++++++---------- .../packages/shared/contracts/avail/deno.json | 6 +-- 3 files changed, 46 insertions(+), 54 deletions(-) diff --git a/packages/binaries/avail-light-client/config.yml b/packages/binaries/avail-light-client/config.yml index 6ed0e9ff5..cde3e9728 100644 --- a/packages/binaries/avail-light-client/config.yml +++ b/packages/binaries/avail-light-client/config.yml @@ -1,31 +1,27 @@ -# Default configuration for avail-light-client -# For a full list of options, see the official Avail documentation. +# Avail Light Client config (no --network needed) -log_level="info" -http_server_host="127.0.0.1" -http_server_port=7007 +# Logging +log_level = "info" -# Secret key for libp2p keypair. Can be either set to 'seed' or to 'key'. -# If set to seed, keypair will be generated from that seed. -# If 'secret_key' is not set, a random seed will be used. -# secret_key={ seed: "avail" } +# API server +http_server_host = "127.0.0.1" +http_server_port = 7007 -# P2P TCP listener port (default: 37000). -port=37000 - -# WebSocket endpoint of a full node. +# RPC to full node (custom 9955) full_node_ws = ["ws://127.0.0.1:9944"] -# Application ID. If not set or set to 0, application client is not started. -app_id=0 - -# Confidence threshold (default: 92.0). -confidence=92.0 - -# File system path where RocksDB used by the light client stores its data. -# This path is relative to the location of this config file. -avail_path="avail_path" - -# Vector of Light Client bootstrap nodes. -# This is for a local setup. Replace with public bootstraps for testnet/mainnet. -bootstraps=["/ip4/127.0.0.1/tcp/39000/p2p/12D3KooWMm1c4pzeLPGkkCJMAgFbsfQ8xmVDusg272icWsaNHWzN"] \ No newline at end of file +# App / LC behavior +app_id = 0 +confidence = 92.0 +avail_path = "avail_path" +network_mode = "both" # both | p2p-only | rpc-only + +# LibP2P +port = 37000 +webrtc_port = 37001 +# secret_key = { seed = "avail" } # optional deterministic key +bootstraps = ["/ip4/127.0.0.1/tcp/39000/p2p/12D3KooWMm1c4pzeLPGkkCJMAgFbsfQ8xmVDusg272icWsaNHWzN"] + +# Telemetry / network identity (equivalent to local --network defaults) +ot_collector_endpoint = "http://127.0.0.1:4317" +genesis_hash = "DEV" \ No newline at end of file diff --git a/templates/evm-midnight/packages/shared/contracts/avail/config.yml b/templates/evm-midnight/packages/shared/contracts/avail/config.yml index 6ed0e9ff5..8d562b558 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/config.yml +++ b/templates/evm-midnight/packages/shared/contracts/avail/config.yml @@ -1,31 +1,27 @@ -# Default configuration for avail-light-client -# For a full list of options, see the official Avail documentation. +# Avail Light Client config (no --network needed) -log_level="info" -http_server_host="127.0.0.1" -http_server_port=7007 +# Logging +log_level = "info" -# Secret key for libp2p keypair. Can be either set to 'seed' or to 'key'. -# If set to seed, keypair will be generated from that seed. -# If 'secret_key' is not set, a random seed will be used. -# secret_key={ seed: "avail" } +# API server +http_server_host = "127.0.0.1" +http_server_port = 7007 -# P2P TCP listener port (default: 37000). -port=37000 +# RPC to full node (custom 9955) +full_node_ws = ["ws://127.0.0.1:9955"] -# WebSocket endpoint of a full node. -full_node_ws = ["ws://127.0.0.1:9944"] +# App / LC behavior +app_id = 0 +confidence = 92.0 +avail_path = "avail_path" +network_mode = "both" # both | p2p-only | rpc-only -# Application ID. If not set or set to 0, application client is not started. -app_id=0 +# LibP2P +port = 37000 +webrtc_port = 37001 +# secret_key = { seed = "avail" } # optional deterministic key +bootstraps = ["/ip4/127.0.0.1/tcp/39000/p2p/12D3KooWMm1c4pzeLPGkkCJMAgFbsfQ8xmVDusg272icWsaNHWzN"] -# Confidence threshold (default: 92.0). -confidence=92.0 - -# File system path where RocksDB used by the light client stores its data. -# This path is relative to the location of this config file. -avail_path="avail_path" - -# Vector of Light Client bootstrap nodes. -# This is for a local setup. Replace with public bootstraps for testnet/mainnet. -bootstraps=["/ip4/127.0.0.1/tcp/39000/p2p/12D3KooWMm1c4pzeLPGkkCJMAgFbsfQ8xmVDusg272icWsaNHWzN"] \ No newline at end of file +# Telemetry / network identity (equivalent to local --network defaults) +ot_collector_endpoint = "http://127.0.0.1:4317" +genesis_hash = "DEV" \ No newline at end of file diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deno.json b/templates/evm-midnight/packages/shared/contracts/avail/deno.json index 8ae4c2990..d3b058199 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/deno.json +++ b/templates/evm-midnight/packages/shared/contracts/avail/deno.json @@ -3,9 +3,9 @@ "version": "0.3.22", "exports": {}, "tasks": { - "avail-node:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-node --dev", - "avail-node:wait": "wait-on tcp:9944", - "avail-light-client:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-light-client --network local --config ./config.yml", + "avail-node:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", + "avail-node:wait": "wait-on tcp:9955", + "avail-light-client:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-light-client --config ./config.yml --app-id 16", "avail-light-client:wait": "wait-on tcp:7007" }, "imports": { From 87d9ec98bee7347d206ac73e85cf543e56e4d56e Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Sun, 7 Sep 2025 22:54:34 -0300 Subject: [PATCH 02/17] deploy scripts for registering app_id. Added launch of avail light client as subprocess of deploy --- e2e/shared/contracts/avail/deploy.ts | 80 +++++++++++++++++++ .../orchestrator/scripts/launch-avail.ts | 2 +- .../packages/shared/contracts/avail/deno.json | 5 +- .../packages/shared/contracts/avail/deploy.ts | 80 +++++++++++++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 e2e/shared/contracts/avail/deploy.ts create mode 100644 templates/evm-midnight/packages/shared/contracts/avail/deploy.ts diff --git a/e2e/shared/contracts/avail/deploy.ts b/e2e/shared/contracts/avail/deploy.ts new file mode 100644 index 000000000..9fcf97be0 --- /dev/null +++ b/e2e/shared/contracts/avail/deploy.ts @@ -0,0 +1,80 @@ +import { Account, Pallets, SDK } from "avail-js-sdk"; + +const sdk = await SDK.New("ws://localhost:9955/ws"); +const seed: string = Deno.env.get("SEED") ?? "//Alice"; +if (!seed) { + throw new Error("SEED environment variable is not set"); +} +const account = Account.new(seed); +console.log("Account Address: ", account.address); +// Use a fixed key string +const ApplicationKey = "app_key_" + Date.now(); + +export async function createApplicationKey() { + // Create application key transaction + const tx = sdk.tx.dataAvailability.createApplicationKey(ApplicationKey); + console.log("Submitting transaction to create application key..."); + + // Execute and wait for inclusion + const res = await tx.executeWaitForInclusion(account, {}); + + // Check if transaction was successful + const isOk = res.isSuccessful(); + if (isOk === undefined) { + throw new Error("Cannot check if transaction was successful"); + } else if (!isOk) { + console.log("Transaction failed", res); + throw new Error("Transaction failed"); + } + + // Extract event data + if (res.events === undefined) throw new Error("No events found"); + + const event = res.events.findFirst( + Pallets.DataAvailabilityEvents.ApplicationKeyCreated, + ); + if (event === undefined) { + throw new Error("ApplicationKeyCreated event not found"); + } + + const appId = event.id; + console.log(`Application created successfully:`); + console.log(`Owner: ${event.owner}`); + console.log(`Key: ${event.keyToString()}`); + console.log(`App Id: ${appId}`); + console.log(`Transaction Hash: ${res.txHash}`); + return { appId, txHash: res.txHash }; +} + +const { appId, txHash } = await createApplicationKey(); +console.log("Transaction Hash: ", txHash.toString()); +const data = JSON.stringify({ appId, txHash, ApplicationKey }); +const fileName = Deno.cwd() + "avail_app.json"; +console.log("Writing to file: ", fileName); +await Deno.writeTextFile(fileName, data); + +const child = new Deno.Command("deno", { + args: ["task", "-f", "@e2e/avail-contracts", "avail-light-client:start"], + env: { + AVAIL_APP_ID: appId.toString(), + }, +}).spawn(); + +console.log("Light Client Started"); + +// Attach light client stdout to the console +child.stdout.pipeTo( + new WritableStream({ + write: (chunk) => { + console.log(chunk); + }, + }), +); +child.stderr.pipeTo( + new WritableStream({ + write: (chunk) => { + console.error(chunk); + }, + }), +); +await child.status; diff --git a/packages/build-tools/orchestrator/scripts/launch-avail.ts b/packages/build-tools/orchestrator/scripts/launch-avail.ts index 5829ba192..67e2acda5 100644 --- a/packages/build-tools/orchestrator/scripts/launch-avail.ts +++ b/packages/build-tools/orchestrator/scripts/launch-avail.ts @@ -18,7 +18,7 @@ import { ComponentNames } from "@paima/log"; // packageName: the name of the package that implements the tasks. // export const launchAvail = (packageName: string) => ({ - stopProcessAtPort: [9944, 7007], + stopProcessAtPort: [9955, 7007], processes: [ { name: ComponentNames.AVAIL_NODE, diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deno.json b/templates/evm-midnight/packages/shared/contracts/avail/deno.json index d3b058199..2f1722cdd 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/deno.json +++ b/templates/evm-midnight/packages/shared/contracts/avail/deno.json @@ -5,11 +5,12 @@ "tasks": { "avail-node:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", "avail-node:wait": "wait-on tcp:9955", - "avail-light-client:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-light-client --config ./config.yml --app-id 16", + "avail-light-client:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-light-client --config ./config.yml --app-id ${AVAIL_APP_ID}", "avail-light-client:wait": "wait-on tcp:7007" }, "imports": { "@paimaexample/npm-avail-node": "npm:@paimaexample/npm-avail-node@0.3.30", - "@paimaexample/npm-avail-light-client": "npm:@paimaexample/npm-avail-light-client@0.3.30" + "@paimaexample/npm-avail-light-client": "npm:@paimaexample/npm-avail-light-client@0.3.30", + "avail-js-sdk": "npm:avail-js-sdk@^0.4.2" } } \ No newline at end of file diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts b/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts new file mode 100644 index 000000000..f58b7bc8e --- /dev/null +++ b/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts @@ -0,0 +1,80 @@ +import { Account, Pallets, SDK } from "avail-js-sdk"; + +const sdk = await SDK.New("ws://localhost:9955/ws"); +const seed: string = Deno.env.get("SEED") ?? "//Alice"; +if (!seed) { + throw new Error("SEED environment variable is not set"); +} +const account = Account.new(seed); +console.log("Account Address: ", account.address); +// Use a fixed key string +const ApplicationKey = "app_key_" + Date.now(); + +export async function createApplicationKey() { + // Create application key transaction + const tx = sdk.tx.dataAvailability.createApplicationKey(ApplicationKey); + console.log("Submitting transaction to create application key..."); + + // Execute and wait for inclusion + const res = await tx.executeWaitForInclusion(account, {}); + + // Check if transaction was successful + const isOk = res.isSuccessful(); + if (isOk === undefined) { + throw new Error("Cannot check if transaction was successful"); + } else if (!isOk) { + console.log("Transaction failed", res); + throw new Error("Transaction failed"); + } + + // Extract event data + if (res.events === undefined) throw new Error("No events found"); + + const event = res.events.findFirst( + Pallets.DataAvailabilityEvents.ApplicationKeyCreated, + ); + if (event === undefined) { + throw new Error("ApplicationKeyCreated event not found"); + } + + const appId = event.id; + console.log(`Application created successfully:`); + console.log(`Owner: ${event.owner}`); + console.log(`Key: ${event.keyToString()}`); + console.log(`App Id: ${appId}`); + console.log(`Transaction Hash: ${res.txHash}`); + return { appId, txHash: res.txHash }; +} + +const { appId, txHash } = await createApplicationKey(); +console.log("Transaction Hash: ", txHash.toString()); +const data = JSON.stringify({ appId, txHash, ApplicationKey }); +const fileName = Deno.cwd() + "avail_app.json"; +console.log("Writing to file: ", fileName); +await Deno.writeTextFile(fileName, data); + +const child = new Deno.Command("deno", { + args: ["task", "-f", "@example/avail-contracts", "avail-light-client:start"], + env: { + AVAIL_APP_ID: appId.toString(), + }, +}).spawn(); + +console.log("Light Client Started"); + +// Attach light client stdout to the console +child.stdout.pipeTo( + new WritableStream({ + write: (chunk) => { + console.log(chunk); + }, + }), +); +child.stderr.pipeTo( + new WritableStream({ + write: (chunk) => { + console.error(chunk); + }, + }), +); +await child.status; From 39b99f7797b406c9ff4cc283e3547e4be4d93a2d Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 00:14:57 -0300 Subject: [PATCH 03/17] fixed launch and deploy for avail --- e2e/client/node/scripts/start.ts | 3 +-- e2e/shared/contracts/avail/.gitignore | 3 ++- e2e/shared/contracts/avail/config.yml | 2 +- e2e/shared/contracts/avail/deno.json | 13 +++++++++---- e2e/shared/contracts/avail/deploy.ts | 17 +---------------- .../orchestrator/scripts/launch-avail.ts | 10 +++++----- .../packages/shared/contracts/avail/deno.json | 5 +++-- .../packages/shared/contracts/avail/deploy.ts | 17 +---------------- 8 files changed, 23 insertions(+), 47 deletions(-) diff --git a/e2e/client/node/scripts/start.ts b/e2e/client/node/scripts/start.ts index 242cac301..530d96f24 100644 --- a/e2e/client/node/scripts/start.ts +++ b/e2e/client/node/scripts/start.ts @@ -30,8 +30,7 @@ const config = Value.Parse(OrchestratorConfig, { launchEvm("@e2e/evm-contracts"), yaci_enabled ? launchCardano("@e2e/cardano-contracts") : {}, launchMidnight("@e2e/midnight-contracts"), - // Uncomment to enable Avail Process - // launchAvail("@e2e/avail-contracts"), + launchAvail("@e2e/avail-contracts"), { stopProcessAtPort: [10590], processes: [ diff --git a/e2e/shared/contracts/avail/.gitignore b/e2e/shared/contracts/avail/.gitignore index 02d630e32..9b35cef71 100644 --- a/e2e/shared/contracts/avail/.gitignore +++ b/e2e/shared/contracts/avail/.gitignore @@ -1 +1,2 @@ -avail_path \ No newline at end of file +avail_path +avail_app.json diff --git a/e2e/shared/contracts/avail/config.yml b/e2e/shared/contracts/avail/config.yml index 6ed0e9ff5..246669cd5 100644 --- a/e2e/shared/contracts/avail/config.yml +++ b/e2e/shared/contracts/avail/config.yml @@ -14,7 +14,7 @@ http_server_port=7007 port=37000 # WebSocket endpoint of a full node. -full_node_ws = ["ws://127.0.0.1:9944"] +full_node_ws = ["ws://127.0.0.1:9955"] # Application ID. If not set or set to 0, application client is not started. app_id=0 diff --git a/e2e/shared/contracts/avail/deno.json b/e2e/shared/contracts/avail/deno.json index d8c8a0334..9add2c045 100644 --- a/e2e/shared/contracts/avail/deno.json +++ b/e2e/shared/contracts/avail/deno.json @@ -3,10 +3,15 @@ "version": "0.3.0", "exports": {}, "tasks": { - "avail-node:start": "deno run -A --unstable-detect-cjs @paima/npm-avail-node --dev", - "avail-node:wait": "wait-on tcp:9944", - "avail-light-client:start": "deno run -A --unstable-detect-cjs @paima/npm-avail-light-client --network local --config ./config.yml", + "avail-node:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", + "avail-node:wait": "wait-on tcp:9955", + "avail-light-client:deploy": "deno run -A --unstable-detect-cjs ./deploy.ts", + "avail-light-client:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-light-client --config ./config.yml --app-id $AVAIL_APP_ID", "avail-light-client:wait": "wait-on tcp:7007" }, - "imports": {} + "imports": { + "avail-js-sdk": "npm:avail-js-sdk@^0.4.2", + "@paimaexample/npm-avail-node": "npm:@paimaexample/npm-avail-node@0.3.30", + "@paimaexample/npm-avail-light-client": "npm:@paimaexample/npm-avail-light-client@0.3.30" + } } \ No newline at end of file diff --git a/e2e/shared/contracts/avail/deploy.ts b/e2e/shared/contracts/avail/deploy.ts index 9fcf97be0..368eabe8b 100644 --- a/e2e/shared/contracts/avail/deploy.ts +++ b/e2e/shared/contracts/avail/deploy.ts @@ -49,7 +49,7 @@ export async function createApplicationKey() { const { appId, txHash } = await createApplicationKey(); console.log("Transaction Hash: ", txHash.toString()); const data = JSON.stringify({ appId, txHash, ApplicationKey }); -const fileName = Deno.cwd() + "avail_app.json"; +const fileName = Deno.cwd() + "/avail_app.json"; console.log("Writing to file: ", fileName); await Deno.writeTextFile(fileName, data); @@ -62,19 +62,4 @@ const child = new Deno.Command("deno", { console.log("Light Client Started"); -// Attach light client stdout to the console -child.stdout.pipeTo( - new WritableStream({ - write: (chunk) => { - console.log(chunk); - }, - }), -); -child.stderr.pipeTo( - new WritableStream({ - write: (chunk) => { - console.error(chunk); - }, - }), -); await child.status; diff --git a/packages/build-tools/orchestrator/scripts/launch-avail.ts b/packages/build-tools/orchestrator/scripts/launch-avail.ts index 67e2acda5..56b18a66d 100644 --- a/packages/build-tools/orchestrator/scripts/launch-avail.ts +++ b/packages/build-tools/orchestrator/scripts/launch-avail.ts @@ -27,21 +27,21 @@ export const launchAvail = (packageName: string) => ({ logs: "none", type: "system-dependency", }, + { + name: ComponentNames.AVAIL_NODE_WAIT, + args: ["task", "-f", packageName, "avail-node:wait"], + }, { name: ComponentNames.AVAIL_CLIENT, args: [ "task", "-f", packageName, - "avail-light-client:start", + "avail-light-client:deploy", ], waitToExit: false, type: "system-dependency", }, - { - name: ComponentNames.AVAIL_NODE_WAIT, - args: ["task", "-f", packageName, "avail-node:wait"], - }, { name: ComponentNames.AVAIL_CLIENT_WAIT, args: [ diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deno.json b/templates/evm-midnight/packages/shared/contracts/avail/deno.json index 2f1722cdd..e6f9c53e7 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/deno.json +++ b/templates/evm-midnight/packages/shared/contracts/avail/deno.json @@ -3,9 +3,10 @@ "version": "0.3.22", "exports": {}, "tasks": { - "avail-node:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", + "avail-node:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", "avail-node:wait": "wait-on tcp:9955", - "avail-light-client:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-light-client --config ./config.yml --app-id ${AVAIL_APP_ID}", + "avail-light-client:deploy": "deno run -A --unstable-detect-cjs ./deploy.ts", + "avail-light-client:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-light-client --config ./config.yml --app-id ${AVAIL_APP_ID}", "avail-light-client:wait": "wait-on tcp:7007" }, "imports": { diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts b/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts index f58b7bc8e..4f1534411 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts +++ b/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts @@ -49,7 +49,7 @@ export async function createApplicationKey() { const { appId, txHash } = await createApplicationKey(); console.log("Transaction Hash: ", txHash.toString()); const data = JSON.stringify({ appId, txHash, ApplicationKey }); -const fileName = Deno.cwd() + "avail_app.json"; +const fileName = Deno.cwd() + "/avail_app.json"; console.log("Writing to file: ", fileName); await Deno.writeTextFile(fileName, data); @@ -62,19 +62,4 @@ const child = new Deno.Command("deno", { console.log("Light Client Started"); -// Attach light client stdout to the console -child.stdout.pipeTo( - new WritableStream({ - write: (chunk) => { - console.log(chunk); - }, - }), -); -child.stderr.pipeTo( - new WritableStream({ - write: (chunk) => { - console.error(chunk); - }, - }), -); await child.status; From b9016f92c68b13991ef19248aeb94300752fb388 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 00:30:53 -0300 Subject: [PATCH 04/17] updated config --- e2e/shared/data-types/src/config.ts | 27 +++++++++++++++++++ .../src/schema/network/substrate/avail.ts | 4 +-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index 51290b14c..cca11d8f4 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -89,6 +89,12 @@ export const localhostConfig = new ConfigBuilder() "0x0000000000000000000000000000000000000000000000000000000000000001", networkId: 0, nodeUrl: "http://127.0.0.1:9944", + }) + .addNetwork({ + name: "avail", + type: ConfigNetworkType.AVAIL, + genesisSeed: "//Alice", + nodeUrl: "ws://127.0.0.1:9955/ws", }); if (yaci_enabled) { @@ -175,6 +181,17 @@ export const localhostConfig = new ConfigBuilder() indexer: "http://127.0.0.1:8088/api/v1/graphql", indexerWs: "ws://127.0.0.1:8088/api/v1/graphql/ws", }), + ) + .addParallel( + (networks) => networks., + (network, deployments) => ({ + name: "parallelAvail", + type: ConfigSyncProtocolType.AVAIL_PARALLEL, + rpc: network.nodeUrl, + lightClient: network.nodeUrl, + startBlockHeight: 0, + pollingInterval: 10_000, + }), ); if (yaci_enabled) { @@ -279,5 +296,15 @@ export const localhostConfig = new ConfigBuilder() scheduledPrefix: "transfer-erc20-2", }), ) + .addPrimitive( + (syncProtocols) => syncProtocols.parallelAvail, + (network, deployments, syncProtocol) => ({ + name: "AvailContractState", + type: ConfigPrimitiveType.AvailContractState, + startBlockHeight: 1, + contractAddress: readAvailApplication().appId, + scheduledPrefix: "availAppState", + }), + ) ) .build(); diff --git a/packages/paima-sdk/config/src/schema/network/substrate/avail.ts b/packages/paima-sdk/config/src/schema/network/substrate/avail.ts index 3ae2fd5cf..b6e1c1ee2 100644 --- a/packages/paima-sdk/config/src/schema/network/substrate/avail.ts +++ b/packages/paima-sdk/config/src/schema/network/substrate/avail.ts @@ -3,7 +3,6 @@ import type { Static } from "@sinclair/typebox"; import { ConfigSchema } from "../../utils.ts"; import { ConfigNetworkType } from "../types.ts"; import type { MergeIntersects } from "@paima/utils"; -import { SubstrateGenesisHash } from "./common.ts"; // ===== // Utils @@ -19,7 +18,8 @@ export const ConfigNetworkSchemaAvail = new ConfigSchema({ required: Type.Object({ name: Type.String(), type: Type.Literal(ConfigNetworkType.AVAIL), - genesisHash: SubstrateGenesisHash, + genesisSeed: Type.String(), + nodeUrl: Type.String(), }), optional: Type.Object({}), }); From 1805d77b93aa3082978851073699abfc1cccbc96 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 09:28:26 -0300 Subject: [PATCH 05/17] read avail app info --- e2e/shared/contracts/avail/deno.json | 4 +++- e2e/shared/contracts/avail/read-app.ts | 27 ++++++++++++++++++++++++++ e2e/shared/data-types/src/config.ts | 9 +++++---- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 e2e/shared/contracts/avail/read-app.ts diff --git a/e2e/shared/contracts/avail/deno.json b/e2e/shared/contracts/avail/deno.json index 9add2c045..6ed2775dc 100644 --- a/e2e/shared/contracts/avail/deno.json +++ b/e2e/shared/contracts/avail/deno.json @@ -1,7 +1,9 @@ { "name": "@e2e/avail-contracts", "version": "0.3.0", - "exports": {}, + "exports": { + ".": "./read-app.ts" + }, "tasks": { "avail-node:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", "avail-node:wait": "wait-on tcp:9955", diff --git a/e2e/shared/contracts/avail/read-app.ts b/e2e/shared/contracts/avail/read-app.ts new file mode 100644 index 000000000..5f98ee956 --- /dev/null +++ b/e2e/shared/contracts/avail/read-app.ts @@ -0,0 +1,27 @@ +export type AvailApplicationInfo = { + appId: number; + txHash: { // The txHash of the apps creation transaction + value: string; + }; + ApplicationKey: string; +}; + +let cachedAppInfo: AvailApplicationInfo | undefined; +export function readAvailApplication(): AvailApplicationInfo { + if (cachedAppInfo) return cachedAppInfo; + try { + // Get the directory of the current module file using Deno's URL API + const dir = new URL(".", import.meta.url); + // Construct the full path to avail_app.json + const appInfoPath = new URL("avail_app.json", dir); + const appInfoJson = Deno.readTextFileSync(appInfoPath); + const appInfo = JSON.parse(appInfoJson) as AvailApplicationInfo; + cachedAppInfo = appInfo; + return appInfo; + } catch (err) { + if (err instanceof Deno.errors.NotFound) { + throw new Error("avail_app.json not found in the current directory"); + } + throw new Error(`Failed to read avail_app.json: ${String(err)}`); + } +} diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index cca11d8f4..7247ae745 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -1,5 +1,6 @@ import { readMidnightContract } from "@e2e/midnight-contracts"; import { contractAddressesEvmMain } from "@e2e/evm-contracts"; +import { readAvailApplication } from "@e2e/avail-contracts"; import { getConnection } from "@paima/db"; import { ConfigBuilder, @@ -183,7 +184,7 @@ export const localhostConfig = new ConfigBuilder() }), ) .addParallel( - (networks) => networks., + (networks) => networks.avail, (network, deployments) => ({ name: "parallelAvail", type: ConfigSyncProtocolType.AVAIL_PARALLEL, @@ -300,10 +301,10 @@ export const localhostConfig = new ConfigBuilder() (syncProtocols) => syncProtocols.parallelAvail, (network, deployments, syncProtocol) => ({ name: "AvailContractState", - type: ConfigPrimitiveType.AvailContractState, + type: ConfigPrimitiveType.AvailPaimaL2, startBlockHeight: 1, - contractAddress: readAvailApplication().appId, - scheduledPrefix: "availAppState", + appId: readAvailApplication().appId, + contractAddress: readAvailApplication().ApplicationKey, }), ) ) From 0f34d5e516e06bf1688179c9f4f22b5f41ee0896 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 16:10:44 -0300 Subject: [PATCH 06/17] Add AvailClient and types for block handling AvailClient class --- .../src/sync-protocols/avail/AvailClient.ts | 53 +++++++++++++++++++ .../sync/src/sync-protocols/avail/types.ts | 34 ++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts create mode 100644 packages/node-sdk/sync/src/sync-protocols/avail/types.ts diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts new file mode 100644 index 000000000..188074a64 --- /dev/null +++ b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts @@ -0,0 +1,53 @@ +import { SDK } from "avail-js-sdk"; +import type { + AvailBlock, + AvailBlockDataItem, + AvailBlockHeader, +} from "./types.ts"; + +const AVAIL_CLIENT_DEFAULT_URL = "http://localhost:7007"; +const AVAIL_NODE_DEFAULT_URL = "ws://localhost:9955/ws"; + +export class AvailClient { + private readonly url: string; + private readonly sdk: Promise; + constructor(nodeUrl: string, lightClientUrl: string) { + this.url = lightClientUrl ?? AVAIL_CLIENT_DEFAULT_URL; + this.sdk = SDK.New(nodeUrl ?? AVAIL_NODE_DEFAULT_URL); + } + + async getBlockFromHash(hash: string): Promise { + const block = await (await this.sdk).client.api.rpc.chain.getBlock(hash); + return { + header: block.block.header as unknown as AvailBlockHeader, + extrinsics: block.block.extrinsics as unknown as string[], + }; + } + + async getBlockHeaderFromHeight(height: number): Promise { + const response = await fetch(`${this.url}/v2/blocks/${height}/header`); + if (!response.ok) { + throw new Error( + `Failed to get block header from height ${height}, status: ${response.status}`, + ); + } + const blockHeader = await response.json() as AvailBlockHeader; + if (!blockHeader) { + throw new Error( + `Failed to get block header from height ${height}, no header found`, + ); + } + return blockHeader; + } + + async getBlockDataFromHeight(height: number): Promise { + const response = await fetch(`${this.url}/v2/blocks/${height}/data`); + if (!response.ok) { + throw new Error( + `Failed to get block data from height ${height}, status: ${response.status}`, + ); + } + const blockData = await response.json() as AvailBlockDataItem; + return blockData; + } +} diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/types.ts b/packages/node-sdk/sync/src/sync-protocols/avail/types.ts new file mode 100644 index 000000000..28792a207 --- /dev/null +++ b/packages/node-sdk/sync/src/sync-protocols/avail/types.ts @@ -0,0 +1,34 @@ +export type AvailBlockHeader = { + hash: `0x${string}`; + parent_hash: `0x${string}`; + number: number; + state_root: `0x${string}`; + extrinsics_root: `0x${string}`; + extension: { + rows: number; + cols: number; + data_root: `0x${string}`; + commitments: string[]; + app_lookup: { + size: number; + index: { + appId: number; + start: number; + }[]; + }; + }; + received_at: number; +}; + +export type AvailBlockDataItem = { + block_number: number; + data_transactions: { + data: string; // BASE64 encoded data + extrinsic: string; + }[]; +}; + +export type AvailBlock = { + header: AvailBlockHeader; + extrinsics: string[]; +}; From 039c0e51a788ddf2357cc2c30a79feb205655a54 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 16:18:18 -0300 Subject: [PATCH 07/17] added genesisHash to avail network schema --- e2e/shared/contracts/avail/deploy.ts | 3 ++- e2e/shared/contracts/avail/read-app.ts | 1 + e2e/shared/data-types/src/config.ts | 2 ++ packages/node-sdk/sync/deno.json | 3 ++- .../paima-sdk/config/src/schema/network/substrate/avail.ts | 1 + packages/paima-sdk/config/src/schema/primitive/config/avail.ts | 1 + .../evm-midnight/packages/shared/contracts/avail/deno.json | 2 +- .../evm-midnight/packages/shared/contracts/avail/deploy.ts | 3 ++- 8 files changed, 12 insertions(+), 4 deletions(-) diff --git a/e2e/shared/contracts/avail/deploy.ts b/e2e/shared/contracts/avail/deploy.ts index 368eabe8b..401a72ea0 100644 --- a/e2e/shared/contracts/avail/deploy.ts +++ b/e2e/shared/contracts/avail/deploy.ts @@ -6,6 +6,7 @@ if (!seed) { throw new Error("SEED environment variable is not set"); } const account = Account.new(seed); +const genesisHash = await sdk.client.api.rpc.chain.getBlockHash(0); console.log("Account Address: ", account.address); // Use a fixed key string const ApplicationKey = "app_key_" + Date.now(); @@ -48,7 +49,7 @@ export async function createApplicationKey() { const { appId, txHash } = await createApplicationKey(); console.log("Transaction Hash: ", txHash.toString()); -const data = JSON.stringify({ appId, txHash, ApplicationKey }); +const data = JSON.stringify({ appId, txHash, ApplicationKey, genesisHash }); const fileName = Deno.cwd() + "/avail_app.json"; console.log("Writing to file: ", fileName); await Deno.writeTextFile(fileName, data); diff --git a/e2e/shared/contracts/avail/read-app.ts b/e2e/shared/contracts/avail/read-app.ts index 5f98ee956..04c10ef4a 100644 --- a/e2e/shared/contracts/avail/read-app.ts +++ b/e2e/shared/contracts/avail/read-app.ts @@ -4,6 +4,7 @@ export type AvailApplicationInfo = { value: string; }; ApplicationKey: string; + genesisHash: string; }; let cachedAppInfo: AvailApplicationInfo | undefined; diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index 7247ae745..a9efc686e 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -96,6 +96,7 @@ export const localhostConfig = new ConfigBuilder() type: ConfigNetworkType.AVAIL, genesisSeed: "//Alice", nodeUrl: "ws://127.0.0.1:9955/ws", + genesisHash: readAvailApplication().genesisHash, }); if (yaci_enabled) { @@ -305,6 +306,7 @@ export const localhostConfig = new ConfigBuilder() startBlockHeight: 1, appId: readAvailApplication().appId, contractAddress: readAvailApplication().ApplicationKey, + genesisHash: readAvailApplication().genesisHash, }), ) ) diff --git a/packages/node-sdk/sync/deno.json b/packages/node-sdk/sync/deno.json index 853aff120..5879d4f15 100644 --- a/packages/node-sdk/sync/deno.json +++ b/packages/node-sdk/sync/deno.json @@ -14,6 +14,7 @@ "json-stable-stringify": "npm:json-stable-stringify@^1.2.1", "@utxorpc/sdk": "npm:@utxorpc/sdk@^0.6.8", "@utxorpc/spec": "npm:@utxorpc/spec@^0.16.0", - "@sinclair/typebox": "npm:@sinclair/typebox@^0.34.30" + "@sinclair/typebox": "npm:@sinclair/typebox@^0.34.30", + "avail-js-sdk": "npm:avail-js-sdk@^0.4.2" } } \ No newline at end of file diff --git a/packages/paima-sdk/config/src/schema/network/substrate/avail.ts b/packages/paima-sdk/config/src/schema/network/substrate/avail.ts index b6e1c1ee2..0576c374b 100644 --- a/packages/paima-sdk/config/src/schema/network/substrate/avail.ts +++ b/packages/paima-sdk/config/src/schema/network/substrate/avail.ts @@ -20,6 +20,7 @@ export const ConfigNetworkSchemaAvail = new ConfigSchema({ type: Type.Literal(ConfigNetworkType.AVAIL), genesisSeed: Type.String(), nodeUrl: Type.String(), + genesisHash: Type.String(), }), optional: Type.Object({}), }); diff --git a/packages/paima-sdk/config/src/schema/primitive/config/avail.ts b/packages/paima-sdk/config/src/schema/primitive/config/avail.ts index d498434ab..c334e243d 100644 --- a/packages/paima-sdk/config/src/schema/primitive/config/avail.ts +++ b/packages/paima-sdk/config/src/schema/primitive/config/avail.ts @@ -16,6 +16,7 @@ export const PrimitiveAvailPaimaL2Config = PrimitiveConfigBaseAvail.cloneMerge({ type: Type.Literal(ConfigPrimitiveType.AvailPaimaL2), contractAddress: TypeboxHelpers.Avail.Address, appId: Type.Number(), + genesisHash: Type.String(), }), optional: Type.Object({}), }); diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deno.json b/templates/evm-midnight/packages/shared/contracts/avail/deno.json index e6f9c53e7..a6170d3e5 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/deno.json +++ b/templates/evm-midnight/packages/shared/contracts/avail/deno.json @@ -3,7 +3,7 @@ "version": "0.3.22", "exports": {}, "tasks": { - "avail-node:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry", + "avail-node:start": "deno run -A --unstable-detect-cjs @paimaexample/npm-avail-node --dev --rpc-port 9955 --no-telemetry --tmp", "avail-node:wait": "wait-on tcp:9955", "avail-light-client:deploy": "deno run -A --unstable-detect-cjs ./deploy.ts", "avail-light-client:start": "deno run -A --unstable-detect-cjs npm:@paimaexample/npm-avail-light-client --config ./config.yml --app-id ${AVAIL_APP_ID}", diff --git a/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts b/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts index 4f1534411..d49401d6f 100644 --- a/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts +++ b/templates/evm-midnight/packages/shared/contracts/avail/deploy.ts @@ -6,6 +6,7 @@ if (!seed) { throw new Error("SEED environment variable is not set"); } const account = Account.new(seed); +const genesisHash = await sdk.client.api.rpc.chain.getBlockHash(0); console.log("Account Address: ", account.address); // Use a fixed key string const ApplicationKey = "app_key_" + Date.now(); @@ -48,7 +49,7 @@ export async function createApplicationKey() { const { appId, txHash } = await createApplicationKey(); console.log("Transaction Hash: ", txHash.toString()); -const data = JSON.stringify({ appId, txHash, ApplicationKey }); +const data = JSON.stringify({ appId, txHash, ApplicationKey, genesisHash }); const fileName = Deno.cwd() + "/avail_app.json"; console.log("Writing to file: ", fileName); await Deno.writeTextFile(fileName, data); From b3fb1e0240b481583764b688f2d0fdb9eca9e37a Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 17:26:06 -0300 Subject: [PATCH 08/17] fetcher and state --- e2e/shared/data-types/src/config.ts | 1 + .../src/sync-protocols/avail/AvailClient.ts | 7 + .../sync/src/sync-protocols/avail/fetcher.ts | 173 ++++++++++++++++++ .../sync/src/sync-protocols/avail/state.ts | 130 +++++++++++++ .../sync/src/sync-protocols/avail/types.ts | 38 ++++ .../node-sdk/sync/src/sync-protocols/types.ts | 4 +- .../node-sdk/sync/src/syncProtocolFactory.ts | 12 ++ .../src/schema/network/substrate/avail.ts | 2 + 8 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts create mode 100644 packages/node-sdk/sync/src/sync-protocols/avail/state.ts diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index a9efc686e..2e5699eb9 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -97,6 +97,7 @@ export const localhostConfig = new ConfigBuilder() genesisSeed: "//Alice", nodeUrl: "ws://127.0.0.1:9955/ws", genesisHash: readAvailApplication().genesisHash, + caip2: `avail:local`, }); if (yaci_enabled) { diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts index 188074a64..d1fc1eb90 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts @@ -16,6 +16,13 @@ export class AvailClient { this.sdk = SDK.New(nodeUrl ?? AVAIL_NODE_DEFAULT_URL); } + async getLatestBlockHeight(): Promise { + const api = (await this.sdk).client.api; + const header = await api.rpc.chain.getHeader(); + const num = header.number; + return num.toNumber(); + } + async getBlockFromHash(hash: string): Promise { const block = await (await this.sdk).client.api.rpc.chain.getBlock(hash); return { diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts new file mode 100644 index 000000000..59a59e034 --- /dev/null +++ b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts @@ -0,0 +1,173 @@ +import { + ConfigPrimitivePayloadType, + ConfigPrimitiveType, + ConfigSyncProtocolType, + type PrimitiveEntry, + type SyncProtocolWithNetwork, +} from "@paima/config"; +import { BaseDataFetcher } from "../base/fetcher.ts"; +import type { DataFetched } from "../base/fetcher.ts"; +import type { + LastPage, + OutputAndCleanup, + RootConversion, +} from "../base/state.ts"; +import type { RootOutput, RootPage } from "../types.ts"; +import type { Input, Output, Page, PrimitiveType } from "./types.ts"; +import { AvailClient } from "./AvailClient.ts"; +import { all, call, type Operation } from "effection"; +import { bound } from "@paima/utils"; + +export class AvailFetcher extends BaseDataFetcher< + Input, + Output, + RootOutput, + Page, + RootPage +> { + readonly client: AvailClient; + + constructor( + readonly config: Extract< + SyncProtocolWithNetwork, + { syncProtocolType: ConfigSyncProtocolType.AVAIL_PARALLEL } + >, + ) { + super(config.syncProtocol.name); + this.client = new AvailClient( + config.syncProtocol.rpc, + config.syncProtocol.lightClient, + ); + } + + @bound + override *readData( + data: Input, + rootConversion: RootConversion, + lastPage: LastPage | undefined, + ): Operation> { + const outputs: OutputAndCleanup[] = []; + for (let height = data.from; height <= data.to; height++) { + let header; + try { + header = yield* call(() => + this.client.getBlockHeaderFromHeight(height) + ); + } catch (_e) { + // Likely reached the tip; stop here + break; + } + + const primitives = yield* this.readPrimitives( + height, + header, + this.config.primitives, + ); + + outputs.push({ + output: { + raw: header, + primitives, + }, + cleanup: () => {}, + }); + } + + if (outputs.length === 0) { + if (!lastPage) { + throw new Error( + `Could not fetch any blocks from ${data.from} to ${data.to} and no previous page was found.`, + ); + } + return { + output: [], + lastPage, + }; + } + + const lastOutput = outputs[outputs.length - 1].output; + return { + output: outputs, + lastPage: { + ownBlockNumber: lastOutput.raw.number, + own: { + height: lastOutput.raw.number, + hash: lastOutput.raw.hash, + }, + root: rootConversion.toRootPage(lastOutput), + }, + }; + } + + @bound + *readPrimitives( + height: number, + header: Output["raw"], + primitives: PrimitiveEntry[], + ): Operation { + const allOperations: Operation[] = []; + for (const primitive of primitives) { + allOperations.push( + this.fetchPaimaL2(height, primitive, header), + ); + } + return (yield* all(allOperations)).flat().filter( + Boolean, + ) as PrimitiveType[]; + } + + @bound + *fetchPaimaL2( + height: number, + primitive: PrimitiveEntry, + header: Output["raw"], + ): Operation { + // For now we only read blocks; if the appId appears in the block header + // we will invoke the data endpoint, but we will not emit a primitive yet. + const appId = primitive.primitive.appId; + if (typeof appId !== "number") return undefined; + + const isPresent = header.extension.app_lookup.index.some((e) => + e.appId === appId + ); + if (!isPresent) return undefined; + + // Read block data for the corresponding height to unblock future parsing. + // Intentionally ignore the result for now. + const blockData = yield* call(() => + this.client.getBlockDataFromHeight(height) + ); + // TODO: handle multiple data transactions + const dataTransaction = blockData.data_transactions.at(0); + if (!dataTransaction) return undefined; + // TODO: is always a JSON string? + const data = JSON.parse(atob(dataTransaction.data)); + return { + input: primitive.primitive, + primitiveType: ConfigPrimitiveType.AvailPaimaL2, + payloadType: ConfigPrimitivePayloadType.Event, + output: { + payloadType: ConfigPrimitivePayloadType.Event, + primitive: ConfigPrimitiveType.AvailPaimaL2, + payload: data, + syncProtocol: { + type: ConfigSyncProtocolType.AVAIL_PARALLEL, + name: this.config.syncProtocol.name, + payload: { + primitiveName: primitive.primitive.name, + caip2: this.config.network.caip2, + ownChain: { + blockNumber: height, + }, + extrinsicIndex: 0, + mainchain: { + blockNumber: null, + timestamp: null, + }, + }, + internal: {}, + }, + }, + }; + } +} diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts new file mode 100644 index 000000000..db6438a98 --- /dev/null +++ b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts @@ -0,0 +1,130 @@ +import { call, type Operation } from "effection"; +import { bound, type TimestampMs } from "@paima/utils"; +import type { PoolClient } from "pg"; +import { type LastPage, SyncState } from "../base/state.ts"; +import type { RootOutput, RootPage } from "../types.ts"; +import type { Input, Output, Page } from "./types.ts"; +import { pageRelation } from "./types.ts"; +import type { AvailFetcher } from "./fetcher.ts"; +import type { ConfigNetworkType, SyncProtocolWithNetwork } from "@paima/config"; +import { getPage } from "@paima/db"; +import { AvailClient } from "./AvailClient.ts"; + +export class AvailSyncState extends SyncState< + Input, + Output, + Page, + RootOutput, + RootPage, + AvailFetcher +> { + constructor( + lastPage: LastPage | undefined, + readonly config: Extract< + SyncProtocolWithNetwork, + { networkType: ConfigNetworkType.AVAIL } + >, + fetcher: AvailFetcher, + private readonly client: AvailClient, + dbConn: PoolClient, + ) { + super( + config.syncProtocol.name, + lastPage, + fetcher, + pageRelation, + dbConn, + ); + } + + @bound + override toPage(input: Input, data: Output[]): Page { + const lastBlock = data[data.length - 1]; + return { + height: lastBlock.raw.number, + hash: lastBlock.raw.hash, + }; + } + + @bound + override toRootPage(data: Output): RootPage { + // Avail headers include `received_at` (ms). Use it as the chain page. + return data.raw.received_at as unknown as TimestampMs; + } + + @bound + override toRootOutput(_data: Output): RootOutput { + throw new Error("Only main chains create root outputs"); + } + + @bound + override *stateToInput(): Operation { + const latestHeight = yield* call(() => this.client.getLatestBlockHeight()); + const startHeight = this.lastPage?.own.height ?? + this.config.syncProtocol.startBlockHeight - 1; + + if (startHeight >= latestHeight) { + return undefined; + } + + const from = startHeight + 1; + const to = Math.min( + from + this.config.syncProtocol.stepSize - 1, + latestHeight, + ); + + return { + from, + to, + isPresync: false, + }; + } + + @bound + override mergeDatum(ourOutput: Output, rootOutput: RootOutput): void { + const primitives = ourOutput.primitives.map((p) => ({ + ...p, + source: this.config.syncProtocol.name, + })); + const blockInfo = [{ + protocol_name: this.config.syncProtocol.name, + block_number: ourOutput.raw.number, + blockHash: ourOutput.raw.hash, + }]; + rootOutput.blockInfo.push(...blockInfo); + rootOutput.primitives.push(...primitives); + } + + @bound + override getNamespace(): string[] { + return [this.config.network.name, this.config.syncProtocol.name]; + } + + static *restoreState( + dbConn: PoolClient, + config: Extract< + SyncProtocolWithNetwork, + { networkType: ConfigNetworkType.AVAIL } + >, + fetcher: AvailFetcher, + ): Operation { + const [result] = yield* call(async () => + await getPage.run({ + protocol_name: config.syncProtocol.name, + }, dbConn) + ); + const page = result + ? result.page as unknown as LastPage + : undefined; + return new AvailSyncState( + page, + config, + fetcher, + new AvailClient( + config.syncProtocol.rpc, + config.syncProtocol.lightClient, + ), + dbConn, + ); + } +} diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/types.ts b/packages/node-sdk/sync/src/sync-protocols/avail/types.ts index 28792a207..8234301d7 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/types.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/types.ts @@ -1,3 +1,13 @@ +import type { + ConfigPrimitivePayloadType, + ConfigPrimitiveType, + ConfigSyncProtocolType, + FlattenSyncProtocolIOFor, +} from "@paima/config"; +import type { BlockNumber } from "@paima/utils"; +import type { PageSyncRange } from "../common/page-helpers.ts"; +import type { PageRelation } from "../base/page.ts"; + export type AvailBlockHeader = { hash: `0x${string}`; parent_hash: `0x${string}`; @@ -32,3 +42,31 @@ export type AvailBlock = { header: AvailBlockHeader; extrinsics: string[]; }; + +// ===================== +// Sync protocol typings +// ===================== + +export type Page = { + height: BlockNumber; + hash: `0x${string}`; +}; + +export type PrimitiveType = FlattenSyncProtocolIOFor< + ConfigSyncProtocolType.AVAIL_PARALLEL, + ConfigPrimitiveType.AvailPaimaL2, + ConfigPrimitivePayloadType.Event +>; + +export type Input = PageSyncRange; +export type Output = { + raw: AvailBlockHeader; + primitives: PrimitiveType[]; +}; + +export const pageRelation: PageRelation = { + compare: (p1, p2) => p1.height - p2.height, + equals: (p1, p2) => p1.height === p2.height, + min: (p1, p2) => (p1.height < p2.height ? p1 : p2), + max: (p1, p2) => (p1.height > p2.height ? p1 : p2), +}; diff --git a/packages/node-sdk/sync/src/sync-protocols/types.ts b/packages/node-sdk/sync/src/sync-protocols/types.ts index f944bd86e..27b40e353 100644 --- a/packages/node-sdk/sync/src/sync-protocols/types.ts +++ b/packages/node-sdk/sync/src/sync-protocols/types.ts @@ -6,6 +6,7 @@ import type { PaginatedFetcher } from "./base/fetcher.ts"; import type { UnionToIntersection } from "@paima/utils"; import type { MidnightSyncState } from "./midnight/state.ts"; import type { NtpSyncState } from "./ntp/state.ts"; +import type { AvailSyncState } from "./avail/state.ts"; // TODO: move folders export type RootOutput = ChainBlock; @@ -16,7 +17,8 @@ export type AllSyncProtocols = | NtpSyncState | EvmSyncState | UtxoRpcSyncState - | MidnightSyncState; + | MidnightSyncState + | AvailSyncState; export type ISyncProtocol = UnionToIntersection; type toPaginated = T extends { fetcher: PaginatedFetcher } ? T diff --git a/packages/node-sdk/sync/src/syncProtocolFactory.ts b/packages/node-sdk/sync/src/syncProtocolFactory.ts index fb7494a3a..56841bc5e 100644 --- a/packages/node-sdk/sync/src/syncProtocolFactory.ts +++ b/packages/node-sdk/sync/src/syncProtocolFactory.ts @@ -15,6 +15,8 @@ import { BufferedRpc } from "./sync-protocols/utxorpc/BufferedRpc.ts"; import { UtxoRpcFetcher } from "./sync-protocols/utxorpc/fetcher.ts"; import { UtxoRpcSyncState } from "./sync-protocols/utxorpc/state.ts"; import { MidnightFetcher, MidnightSyncState } from "@paima/sync"; +import { AvailFetcher } from "./sync-protocols/avail/fetcher.ts"; +import { AvailSyncState } from "./sync-protocols/avail/state.ts"; import { NtpFetcher } from "./sync-protocols/ntp/fetcher.ts"; import { NtpSyncState } from "./sync-protocols/ntp/state.ts"; @@ -83,6 +85,16 @@ export function* genSyncProtocols( fetcher, ); result.push(state); + } else if ( + entry.networkType === ConfigNetworkType.AVAIL + ) { + const fetcher = new AvailFetcher(entry); + const state = yield* AvailSyncState.restoreState( + dbConn, + entry, + fetcher, + ); + result.push(state); } else { throw new Error(`Unsupported network type: ${entry.network.type}`); } diff --git a/packages/paima-sdk/config/src/schema/network/substrate/avail.ts b/packages/paima-sdk/config/src/schema/network/substrate/avail.ts index 0576c374b..7e5b428d0 100644 --- a/packages/paima-sdk/config/src/schema/network/substrate/avail.ts +++ b/packages/paima-sdk/config/src/schema/network/substrate/avail.ts @@ -3,6 +3,7 @@ import type { Static } from "@sinclair/typebox"; import { ConfigSchema } from "../../utils.ts"; import { ConfigNetworkType } from "../types.ts"; import type { MergeIntersects } from "@paima/utils"; +import { TypeboxHelpers } from "@paima/utils"; // ===== // Utils @@ -19,6 +20,7 @@ export const ConfigNetworkSchemaAvail = new ConfigSchema({ name: Type.String(), type: Type.Literal(ConfigNetworkType.AVAIL), genesisSeed: Type.String(), + caip2: TypeboxHelpers.Caip2, nodeUrl: Type.String(), genesisHash: Type.String(), }), From 0acc3d717d05baecb8afff32377b5f297e505a87 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 17:35:48 -0300 Subject: [PATCH 09/17] added avail to stateMachine --- e2e/client/node/src/state-machine.ts | 9 +++++++++ e2e/shared/data-types/src/config.ts | 1 + e2e/shared/data-types/src/grammar.ts | 10 +++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/e2e/client/node/src/state-machine.ts b/e2e/client/node/src/state-machine.ts index 68757bfb3..34854d1e7 100644 --- a/e2e/client/node/src/state-machine.ts +++ b/e2e/client/node/src/state-machine.ts @@ -90,6 +90,15 @@ stm.addStateTransition( }, ); +stm.addStateTransition( + "avail-app-state", + function* (data) { + const { payload } = data.parsedInput; + console.log("📦 Avail App state has message:", payload.message); + return; + }, +); + stm.addStateTransition( "throw_error", function* (data) { diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index 2e5699eb9..1abc74176 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -308,6 +308,7 @@ export const localhostConfig = new ConfigBuilder() appId: readAvailApplication().appId, contractAddress: readAvailApplication().ApplicationKey, genesisHash: readAvailApplication().genesisHash, + scheduledPrefix: "avail-app-state", }), ) ) diff --git a/e2e/shared/data-types/src/grammar.ts b/e2e/shared/data-types/src/grammar.ts index 63ec72eae..0917d9064 100644 --- a/e2e/shared/data-types/src/grammar.ts +++ b/e2e/shared/data-types/src/grammar.ts @@ -57,10 +57,18 @@ export const grammar = { ), ], ], + "avail-app-state": [ + [ + "payload", + Type.Object({ + message: Type.String(), + }), + ], + ], // Auto-generate other primitives, but exclude midnight (we define it explicitly above) ...Object.fromEntries( Object.entries(mapPrimitivesToGrammar(localhostConfig.primitives)) - .filter(([key]) => key !== "midnightContractState"), + .filter(([key]) => key !== "midnightContractState" && key !== "avail-app-state"), ), } as const satisfies GrammarDefinition; From a52c6c71e63f02635c24768bea1e6bfa504393d3 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 17:45:02 -0300 Subject: [PATCH 10/17] fixed ts lint errors --- packages/node-sdk/sync/src/sync-protocols/avail/state.ts | 2 +- packages/node-sdk/sync/src/sync-protocols/midnight/state.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts index db6438a98..294f3bd2d 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts @@ -25,7 +25,7 @@ export class AvailSyncState extends SyncState< { networkType: ConfigNetworkType.AVAIL } >, fetcher: AvailFetcher, - private readonly client: AvailClient, + public readonly client: AvailClient, dbConn: PoolClient, ) { super( diff --git a/packages/node-sdk/sync/src/sync-protocols/midnight/state.ts b/packages/node-sdk/sync/src/sync-protocols/midnight/state.ts index 9ee683521..2bab8a429 100644 --- a/packages/node-sdk/sync/src/sync-protocols/midnight/state.ts +++ b/packages/node-sdk/sync/src/sync-protocols/midnight/state.ts @@ -33,7 +33,7 @@ export class MidnightSyncState extends SyncState< { networkType: ConfigNetworkType.MIDNIGHT } >, fetcher: MidnightFetcher, - private readonly client: MidnightClient, + public readonly client: MidnightClient, dbConn: PoolClient, ) { super( From b904d0da8bf281ff961b3765bef9b330a39872ea Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 18:52:44 -0300 Subject: [PATCH 11/17] getLatestBlockHeight uses light client status --- e2e/shared/data-types/src/config.ts | 6 +++--- .../sync/src/sync-protocols/avail/AvailClient.ts | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index 1abc74176..df8b0dbbd 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -191,9 +191,9 @@ export const localhostConfig = new ConfigBuilder() name: "parallelAvail", type: ConfigSyncProtocolType.AVAIL_PARALLEL, rpc: network.nodeUrl, - lightClient: network.nodeUrl, - startBlockHeight: 0, - pollingInterval: 10_000, + lightClient: 'http://127.0.0.1:7007', + startBlockHeight: 1, + pollingInterval: 20_000, }), ); diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts index d1fc1eb90..7e3befcbc 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts @@ -18,9 +18,19 @@ export class AvailClient { async getLatestBlockHeight(): Promise { const api = (await this.sdk).client.api; - const header = await api.rpc.chain.getHeader(); - const num = header.number; - return num.toNumber(); + // Block from avail node is slightly above the light client + // const header = await api.rpc.chain.getHeader(); + const statusResponse = await fetch(`${this.url}/v2/status`); + if (!statusResponse.ok) { + throw new Error( + `Failed to get status from light client, status: ${statusResponse.status}`, + ); + } + const status = await statusResponse.json(); + const num = status.blocks?.latest as number; + // const num = header.number; + // return num.toNumber(); + return num; } async getBlockFromHash(hash: string): Promise { From a180608e4000ee0933a4b00ede06bfe6c657796d Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 8 Sep 2025 23:28:18 -0300 Subject: [PATCH 12/17] primitives and processing --- .../sm/primitives/avail/contract-state.ts | 51 +++++++++++++++++++ packages/node-sdk/sm/primitives/processing.ts | 6 ++- .../sync/src/sync-protocols/avail/fetcher.ts | 18 +++++-- .../concise/src/v2/builtins/primitives.ts | 4 ++ .../src/schema/primitive/config/avail.ts | 1 + .../primitive/output/midnight/graphql.ts | 6 +-- .../config/src/schema/primitive/output/mod.ts | 1 + .../src/schema/sync-protocols/avail/rpc.ts | 4 +- 8 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 packages/node-sdk/sm/primitives/avail/contract-state.ts diff --git a/packages/node-sdk/sm/primitives/avail/contract-state.ts b/packages/node-sdk/sm/primitives/avail/contract-state.ts new file mode 100644 index 000000000..f71983cb8 --- /dev/null +++ b/packages/node-sdk/sm/primitives/avail/contract-state.ts @@ -0,0 +1,51 @@ +import { createScheduledData, insertPrimitiveAccounting } from "@paima/db"; +import { BuiltinTransitions, generateRawStmInput } from "@paima/concise"; +import { + type ConfigPrimitivePayloadType, + ConfigPrimitiveAccountingPayloadType, + ConfigPrimitiveType, + type ConfigSyncProtocolType, + type FlattenSyncProtocolIOFor, +} from "@paima/config"; +import { type StateUpdateStream, World } from "@paima/coroutine"; + +import type { PaimaBlockNumber } from "@paima/utils"; + +export default function* processAvailPaimaL2Datum( + paima_block_height: PaimaBlockNumber, + response: FlattenSyncProtocolIOFor< + ConfigSyncProtocolType.AVAIL_PARALLEL, + ConfigPrimitiveType.AvailPaimaL2, + ConfigPrimitivePayloadType.Event + >, +): StateUpdateStream { + const { scheduledPrefix } = response.input; + const { payload, syncProtocol } = response.output; + const scheduledInputData = generateRawStmInput( + BuiltinTransitions[ConfigPrimitiveType.AvailPaimaL2] + .scheduledPrefix, + scheduledPrefix, + { payload }, + ); + yield* World.resolve(insertPrimitiveAccounting, { + primitive_name: response.output.syncProtocol.payload.primitiveName, + paima_block_height: paima_block_height, + payload_type: ConfigPrimitiveAccountingPayloadType.Event, + payload: JSON.stringify(response.output.payload) as any, + }); + if (scheduledPrefix) { + yield* createScheduledData( + JSON.stringify(scheduledInputData), + { + blockHeight: syncProtocol.payload.ownChain.blockNumber, + }, + { + primitiveName: response.output.syncProtocol.payload.primitiveName, + txHash: response.output.syncProtocol.internal.transactionHash, + caip2: response.output.syncProtocol.payload.caip2, + fromAddress: response.input.contractAddress, + contractAddress: response.input.contractAddress, + } + ); + } +} \ No newline at end of file diff --git a/packages/node-sdk/sm/primitives/processing.ts b/packages/node-sdk/sm/primitives/processing.ts index 4f28f0c77..771b82754 100644 --- a/packages/node-sdk/sm/primitives/processing.ts +++ b/packages/node-sdk/sm/primitives/processing.ts @@ -22,6 +22,7 @@ import type { StateUpdateStream } from "@paima/coroutine"; import type { PaimaBlockNumber } from "@paima/utils"; import { clearBigInts } from "./utils.ts"; import processMidnightContractStateDatum from "./midnight/contract-state.ts"; +import processAvailPaimaL2Datum from "./avail/contract-state.ts"; export function* primitiveTransitionFunction( paima_block_height: PaimaBlockNumber, @@ -35,7 +36,10 @@ export function* primitiveTransitionFunction( case ConfigPrimitiveType.AvailPaimaL2: switch (primitive.payloadType) { case ConfigPrimitivePayloadType.Event: - return; // TODO + return yield* processAvailPaimaL2Datum( + paima_block_height, + primitive, + ); default: assertNever.default(clearBigInts(primitive)); } diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts index 59a59e034..e214d14a1 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts @@ -15,7 +15,7 @@ import type { import type { RootOutput, RootPage } from "../types.ts"; import type { Input, Output, Page, PrimitiveType } from "./types.ts"; import { AvailClient } from "./AvailClient.ts"; -import { all, call, type Operation } from "effection"; +import { all, call, sleep, type Operation } from "effection"; import { bound } from "@paima/utils"; export class AvailFetcher extends BaseDataFetcher< @@ -131,7 +131,9 @@ export class AvailFetcher extends BaseDataFetcher< e.appId === appId ); if (!isPresent) return undefined; - + // Sometimes the block data appears much later than the appId appears in the block header + // so we need to sleep for a bit to ensure the block data is available + yield* sleep(10_000); // Read block data for the corresponding height to unblock future parsing. // Intentionally ignore the result for now. const blockData = yield* call(() => @@ -141,7 +143,7 @@ export class AvailFetcher extends BaseDataFetcher< const dataTransaction = blockData.data_transactions.at(0); if (!dataTransaction) return undefined; // TODO: is always a JSON string? - const data = JSON.parse(atob(dataTransaction.data)); + const data: string = atob(dataTransaction.data); return { input: primitive.primitive, primitiveType: ConfigPrimitiveType.AvailPaimaL2, @@ -149,7 +151,11 @@ export class AvailFetcher extends BaseDataFetcher< output: { payloadType: ConfigPrimitivePayloadType.Event, primitive: ConfigPrimitiveType.AvailPaimaL2, - payload: data, + payload: { + inputData: height.toString(), + inputNonce: '0x', // TODO replace this with something meaningful + suppliedValue: data, + }, syncProtocol: { type: ConfigSyncProtocolType.AVAIL_PARALLEL, name: this.config.syncProtocol.name, @@ -165,7 +171,9 @@ export class AvailFetcher extends BaseDataFetcher< timestamp: null, }, }, - internal: {}, + internal: { + transactionHash: header.hash, // TODO replace this with real txHash + }, }, }, }; diff --git a/packages/paima-sdk/concise/src/v2/builtins/primitives.ts b/packages/paima-sdk/concise/src/v2/builtins/primitives.ts index 0a1301921..3b4a1cbad 100644 --- a/packages/paima-sdk/concise/src/v2/builtins/primitives.ts +++ b/packages/paima-sdk/concise/src/v2/builtins/primitives.ts @@ -9,6 +9,7 @@ import { ConfigPrimitivePayloadType, ConfigPrimitiveType, ConfigSyncProtocolType, + PrimitiveAvailPaimaL2Payload, PrimitiveCardanoCarpDelegationPayload, PrimitiveCardanoCarpMintBurnPayload, PrimitiveCardanoCarpProjectedNFTPayload, @@ -121,6 +122,9 @@ export const BuiltinTransitions = { [ConfigPrimitiveType.MidnightContractState]: { scheduledPrefix: [["payload", PrimitiveMidnightContractStatePayload]], }, + [ConfigPrimitiveType.AvailPaimaL2]: { + scheduledPrefix: [["payload", PrimitiveAvailPaimaL2Payload]], + }, } as const; /** diff --git a/packages/paima-sdk/config/src/schema/primitive/config/avail.ts b/packages/paima-sdk/config/src/schema/primitive/config/avail.ts index c334e243d..c4f9cd769 100644 --- a/packages/paima-sdk/config/src/schema/primitive/config/avail.ts +++ b/packages/paima-sdk/config/src/schema/primitive/config/avail.ts @@ -17,6 +17,7 @@ export const PrimitiveAvailPaimaL2Config = PrimitiveConfigBaseAvail.cloneMerge({ contractAddress: TypeboxHelpers.Avail.Address, appId: Type.Number(), genesisHash: Type.String(), + scheduledPrefix: Type.String(), }), optional: Type.Object({}), }); diff --git a/packages/paima-sdk/config/src/schema/primitive/output/midnight/graphql.ts b/packages/paima-sdk/config/src/schema/primitive/output/midnight/graphql.ts index e65588708..9b562ffef 100644 --- a/packages/paima-sdk/config/src/schema/primitive/output/midnight/graphql.ts +++ b/packages/paima-sdk/config/src/schema/primitive/output/midnight/graphql.ts @@ -1,6 +1,6 @@ -import { - type MidnightEncodedStateJson, - type Satisfies, +import type { + MidnightEncodedStateJson, + Satisfies, TypeboxHelpers, } from "@paima/utils"; import { diff --git a/packages/paima-sdk/config/src/schema/primitive/output/mod.ts b/packages/paima-sdk/config/src/schema/primitive/output/mod.ts index fb43a2c28..f435dcd67 100644 --- a/packages/paima-sdk/config/src/schema/primitive/output/mod.ts +++ b/packages/paima-sdk/config/src/schema/primitive/output/mod.ts @@ -1,6 +1,7 @@ export * from "./all.ts"; export * from "./types.ts"; export * from "./cardano/carp.ts"; +export * from "./avail/rpc.ts"; export * from "./common.ts"; export * from "./evm/rpc.ts"; export * from "./midnight/graphql.ts"; diff --git a/packages/paima-sdk/config/src/schema/sync-protocols/avail/rpc.ts b/packages/paima-sdk/config/src/schema/sync-protocols/avail/rpc.ts index 1f468f3ab..fe870851d 100644 --- a/packages/paima-sdk/config/src/schema/sync-protocols/avail/rpc.ts +++ b/packages/paima-sdk/config/src/schema/sync-protocols/avail/rpc.ts @@ -39,7 +39,9 @@ export const ConfigSyncProtocolSchemaAvailBase = NameField.cloneMerge( }); export const CommonResponseAvailRpcBase = { - internal: {}, + internal: { + transactionHash: Type.String(), + }, payload: { primitiveName: Type.String(), caip2: TypeboxHelpers.Caip2, From 7dcc7bd70158fc443ce9c275c0aff3ed447387a2 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Tue, 9 Sep 2025 11:23:29 -0300 Subject: [PATCH 13/17] Add delay configuration to AvailSyncState --- e2e/shared/data-types/src/config.ts | 1 + packages/node-sdk/sync/src/sync-protocols/avail/state.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index df8b0dbbd..97e725bd3 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -194,6 +194,7 @@ export const localhostConfig = new ConfigBuilder() lightClient: 'http://127.0.0.1:7007', startBlockHeight: 1, pollingInterval: 20_000, + delayMs: 40_000, }), ); diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts index 294f3bd2d..f0830d6b7 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts @@ -9,6 +9,7 @@ import type { AvailFetcher } from "./fetcher.ts"; import type { ConfigNetworkType, SyncProtocolWithNetwork } from "@paima/config"; import { getPage } from "@paima/db"; import { AvailClient } from "./AvailClient.ts"; +import { applyDelay } from "../common/utils.ts"; export class AvailSyncState extends SyncState< Input, @@ -49,7 +50,10 @@ export class AvailSyncState extends SyncState< @bound override toRootPage(data: Output): RootPage { // Avail headers include `received_at` (ms). Use it as the chain page. - return data.raw.received_at as unknown as TimestampMs; + return applyDelay( + data.raw.received_at, + this.config.syncProtocol.delayMs, + ); } @bound From 4c08a9cc9ff571fa0ac2bbb11c46eaf0c6111e7c Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Thu, 11 Sep 2025 17:57:30 -0300 Subject: [PATCH 14/17] added block log and removed sleep in the fetcher --- .../sync/src/sync-protocols/avail/fetcher.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts index e214d14a1..f1b809603 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts @@ -15,7 +15,7 @@ import type { import type { RootOutput, RootPage } from "../types.ts"; import type { Input, Output, Page, PrimitiveType } from "./types.ts"; import { AvailClient } from "./AvailClient.ts"; -import { all, call, sleep, type Operation } from "effection"; +import { all, call, type Operation } from "effection"; import { bound } from "@paima/utils"; export class AvailFetcher extends BaseDataFetcher< @@ -47,6 +47,11 @@ export class AvailFetcher extends BaseDataFetcher< lastPage: LastPage | undefined, ): Operation> { const outputs: OutputAndCleanup[] = []; + console.log( + `[Avail] Fetching blocks from ${data.from} to ${data.to}. ${ + data.isPresync ? "[presync]" : "" + }`, + ); for (let height = data.from; height <= data.to; height++) { let header; try { @@ -131,9 +136,6 @@ export class AvailFetcher extends BaseDataFetcher< e.appId === appId ); if (!isPresent) return undefined; - // Sometimes the block data appears much later than the appId appears in the block header - // so we need to sleep for a bit to ensure the block data is available - yield* sleep(10_000); // Read block data for the corresponding height to unblock future parsing. // Intentionally ignore the result for now. const blockData = yield* call(() => @@ -153,7 +155,7 @@ export class AvailFetcher extends BaseDataFetcher< primitive: ConfigPrimitiveType.AvailPaimaL2, payload: { inputData: height.toString(), - inputNonce: '0x', // TODO replace this with something meaningful + inputNonce: "0x", // TODO replace this with something meaningful suppliedValue: data, }, syncProtocol: { From 4ab0e1f0d5606af556e56d7cb3a2df4281a337e5 Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Fri, 12 Sep 2025 19:55:38 -0300 Subject: [PATCH 15/17] final fixes --- deno.lock | 482 ++++++++++++++++++ e2e/client/node/src/state-machine.ts | 6 +- e2e/shared/data-types/src/config.ts | 4 +- e2e/shared/data-types/src/grammar.ts | 6 +- .../sm/primitives/avail/contract-state.ts | 16 +- .../src/sync-protocols/avail/AvailClient.ts | 7 +- .../sync/src/sync-protocols/avail/fetcher.ts | 2 +- .../sync/src/sync-protocols/avail/state.ts | 4 +- templates/evm-midnight/deno.lock | 457 ++++++++++++++++- 9 files changed, 965 insertions(+), 19 deletions(-) diff --git a/deno.lock b/deno.lock index 60fb490c2..463d143e2 100644 --- a/deno.lock +++ b/deno.lock @@ -119,6 +119,10 @@ "npm:@openzeppelin/contracts-upgradeable@^5.1.0": "5.1.0_@openzeppelin+contracts@5.1.0", "npm:@openzeppelin/contracts@5.1.0": "5.1.0", "npm:@paima/pgtyped-cli@^2.4.5": "2.4.5_typescript@5.6.3_fp-ts@2.16.11_io-ts@2.2.22__fp-ts@2.16.11_chokidar@4.0.1", + "npm:@paimaexample/npm-avail-light-client@*": "0.3.30", + "npm:@paimaexample/npm-avail-light-client@0.3.30": "0.3.30", + "npm:@paimaexample/npm-avail-node@*": "0.3.30", + "npm:@paimaexample/npm-avail-node@0.3.30": "0.3.30", "npm:@pgtyped/parser@2.4.2": "2.4.2", "npm:@pgtyped/runtime@2.4.2": "2.4.2", "npm:@pgtyped/runtime@^2.4.2": "2.4.2", @@ -135,6 +139,7 @@ "npm:abitype@^1.0.8": "1.0.9_typescript@5.6.3_zod@3.25.76", "npm:assert-never@^1.4.0": "1.4.0", "npm:autoprefixer@^10.4.16": "10.4.21_postcss@8.5.6", + "npm:avail-js-sdk@~0.4.2": "0.4.2", "npm:axios-proxy-builder@~0.1.2": "0.1.2", "npm:axios@^1.10.0": "1.11.0", "npm:axios@^1.6.8": "1.11.0", @@ -4345,6 +4350,22 @@ ], "bin": true }, + "@paimaexample/npm-avail-light-client@0.3.30": { + "integrity": "sha512-UimIoG4raHuFC6sLRdD2re1FWFTNNOTIhjoJ+ZfO0EZNh1PJkMDvqHquXjzuLhoW0uyXHIlK+JJCttcY8XiThw==", + "dependencies": [ + "extract-zip", + "tar@6.2.1" + ], + "bin": true + }, + "@paimaexample/npm-avail-node@0.3.30": { + "integrity": "sha512-Zy7KT6jSR6XhlB8Ju6LrmQQaqrCDOgVHTxTksuMO/ElbDFZ5E9X1C1Boqnm0NdkcMHYUVHjAbUju9Iw8+aNNnQ==", + "dependencies": [ + "linus", + "tar@6.2.1" + ], + "bin": true + }, "@pgtyped/parser@2.4.2": { "integrity": "sha512-LbK90cz+CAjG+jsiKS5FNVkb97Ys5xZa1xmSIq7N2zYz1vX04hr6xNhDUSjbC8C/YnFm1S+d2D6BbHMgzsBilw==", "dependencies": [ @@ -4399,6 +4420,388 @@ "@polka/url@1.0.0-next.29": { "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==" }, + "@polkadot-api/json-rpc-provider-proxy@0.1.0": { + "integrity": "sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==" + }, + "@polkadot-api/json-rpc-provider@0.0.1": { + "integrity": "sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==" + }, + "@polkadot-api/metadata-builders@0.3.2": { + "integrity": "sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==", + "dependencies": [ + "@polkadot-api/substrate-bindings", + "@polkadot-api/utils" + ] + }, + "@polkadot-api/observable-client@0.3.2_@polkadot-api+substrate-client@0.1.4_rxjs@7.8.2": { + "integrity": "sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==", + "dependencies": [ + "@polkadot-api/metadata-builders", + "@polkadot-api/substrate-bindings", + "@polkadot-api/substrate-client", + "@polkadot-api/utils", + "rxjs@7.8.2" + ] + }, + "@polkadot-api/substrate-bindings@0.6.0": { + "integrity": "sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==", + "dependencies": [ + "@noble/hashes@1.8.0", + "@polkadot-api/utils", + "@scure/base@1.2.6", + "scale-ts" + ] + }, + "@polkadot-api/substrate-client@0.1.4": { + "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", + "dependencies": [ + "@polkadot-api/json-rpc-provider", + "@polkadot-api/utils" + ] + }, + "@polkadot-api/utils@0.1.0": { + "integrity": "sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==" + }, + "@polkadot/api-augment@15.10.2": { + "integrity": "sha512-CCli5ltPiJEyQF/8DmTRpTfYKHY4W0B+xQDmzKgFmd+Q64Qot0fGpsaZXZftef1Tuoh0Uqak9qM+6B4APXIPkQ==", + "dependencies": [ + "@polkadot/api-base", + "@polkadot/rpc-augment", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-augment@15.10.2", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/api-base@15.10.2": { + "integrity": "sha512-7DJw++5IbPrsLPGcTlIZbMOretfvQJG80CW8+A+t2BLxbbv+I2neWNQ9QV9O28XsbOHzNgKHXuRyirdaG/dvrg==", + "dependencies": [ + "@polkadot/rpc-core", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/util", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/api-derive@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-tF9DZvdm7hkRIJ1HtJzu73vdqQWBr8935YSN/RNsRb4FhJK5cHaC2uB4NLdRMnyUjmH0JRSnvWFq+HHcVxFJZw==", + "dependencies": [ + "@polkadot/api", + "@polkadot/api-augment", + "@polkadot/api-base", + "@polkadot/rpc-core", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/api@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-UM/510TwdugPjMpfyhhMNOZJ3M2ftRk0Ftxe+WSWev3o1u0dxqGuIN6fN0c224CHXIr58uWXUoMRHi6Cnfaxhw==", + "dependencies": [ + "@polkadot/api-augment", + "@polkadot/api-base", + "@polkadot/api-derive", + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/rpc-augment", + "@polkadot/rpc-core", + "@polkadot/rpc-provider", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-augment@15.10.2", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/types-known", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "eventemitter3@5.0.1", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/keyring@13.5.6": { + "integrity": "sha512-Ybe6Mflrh96FKR5tfEaf/93RxJD7x9UigseNOJW6Yd8LF+GesdxrqmZD7zh+53Hb7smGQWf/0FCfwhoWZVgPUQ==" + }, + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-Ybe6Mflrh96FKR5tfEaf/93RxJD7x9UigseNOJW6Yd8LF+GesdxrqmZD7zh+53Hb7smGQWf/0FCfwhoWZVgPUQ==", + "dependencies": [ + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "tslib@2.8.1" + ] + }, + "@polkadot/networks@13.5.6": { + "integrity": "sha512-9HqUIBOHnz9x/ssPb0aOD/7XcU8vGokEYpLoNgexFNIJzqDgrDHXR197iFpkbMqA/+98zagrvYUyPYj1yYs9Jw==", + "dependencies": [ + "@polkadot/util", + "@substrate/ss58-registry", + "tslib@2.8.1" + ] + }, + "@polkadot/rpc-augment@15.10.2": { + "integrity": "sha512-9QQ8utyAEdEl7iScteIN59EBu8eNZjZa8AfKBitbdq1Hezd+WPil5LdoYi+wmJOMhZHeDT1s7/j2+kY1Z2Vymg==", + "dependencies": [ + "@polkadot/rpc-core", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/rpc-core@15.10.2": { + "integrity": "sha512-vqDvr1WcHH3WPzDV4WTlf2S5cDmIoFPciynJ8eNcKqR3mG7Cqd0iL+MG6s0KFXdSY2Qvtl+0C6yZN0xr4Ha6BQ==", + "dependencies": [ + "@polkadot/rpc-augment", + "@polkadot/rpc-provider", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/util", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/rpc-provider@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-kqpPW8U0stVW+uOZP8g5d87Xb8rbXJR5PUub6xgGG6AOMbbvvuCU3GSohu/iozo4p9uD7TGH90jvbxj1rjJVMA==", + "dependencies": [ + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-support", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "@polkadot/x-fetch", + "@polkadot/x-global", + "@polkadot/x-ws", + "eventemitter3@5.0.1", + "mock-socket", + "nock", + "tslib@2.8.1" + ], + "optionalDependencies": [ + "@substrate/connect" + ] + }, + "@polkadot/types-augment@15.10.2": { + "integrity": "sha512-X/xh+Dzud6OIyr7q8xttAwn+Fb5hKImIWEO1oG8WcInqv+P0vRyu7Tds+2ut9t64sJi3ydJ7I+T+WxZYheCU7g==", + "dependencies": [ + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-augment@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-X/xh+Dzud6OIyr7q8xttAwn+Fb5hKImIWEO1oG8WcInqv+P0vRyu7Tds+2ut9t64sJi3ydJ7I+T+WxZYheCU7g==", + "dependencies": [ + "@polkadot/types@15.10.2", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-codec@15.10.2": { + "integrity": "sha512-dhwbaukUZiYDW3QAAnLAFThYE5hQGdwBMWOVTt9+aBWxEKovLK93j0V30tEzMUtrZy8xaRWdhdDeQ3DSmxEP6w==", + "dependencies": [ + "@polkadot/util", + "@polkadot/x-bigint", + "tslib@2.8.1" + ] + }, + "@polkadot/types-create@15.10.2": { + "integrity": "sha512-vqXwPUSgx/By31qSkhOR5GN6zMbF1MkiX3F1g5KKHaRE8p/DdTry4LhufxhtK1mr9eBWvVGXxCOZdwjQco2M1A==", + "dependencies": [ + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-known@15.10.2": { + "integrity": "sha512-vs02WiIlLualrrh/EuA5qzK6QzatVPqBBNqa66dUtmyhJy48OEelBK+QLfOIQvZKU0ModEunoVrnxuY+O1DCmA==", + "dependencies": [ + "@polkadot/networks", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-support@15.10.2": { + "integrity": "sha512-sHamH6MehJa7aGZ/DHTB6vJAhSN5VrJx5lpDpb3xgBFTr0cVc5IsociqgJ/mgvyEIdLF3laraPxREqxCmuxTaQ==", + "dependencies": [ + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types@15.10.2": { + "integrity": "sha512-/wDwKdDijxSXyNk5YezhVitdFxoQaTSSG9KXa7dEWujtmS/51UHmt9+P3W8b8D8kKaCvumahf/ww3GJI6s0Eqw==", + "dependencies": [ + "@polkadot/keyring@13.5.6", + "@polkadot/types-augment@15.10.2", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-/wDwKdDijxSXyNk5YezhVitdFxoQaTSSG9KXa7dEWujtmS/51UHmt9+P3W8b8D8kKaCvumahf/ww3GJI6s0Eqw==", + "dependencies": [ + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-augment@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/util-crypto@13.5.6": { + "integrity": "sha512-1l+t5lVc9UWxvbJe7/3V+QK8CwrDPuQjDK6FKtDZgZCU0JRrjySOxV0J4PeDIv8TgXZtbIcQFVUhIsJTyKZZJQ==", + "dependencies": [ + "@noble/curves@1.9.6", + "@noble/hashes@1.8.0", + "@polkadot/networks" + ] + }, + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-1l+t5lVc9UWxvbJe7/3V+QK8CwrDPuQjDK6FKtDZgZCU0JRrjySOxV0J4PeDIv8TgXZtbIcQFVUhIsJTyKZZJQ==", + "dependencies": [ + "@noble/curves@1.9.6", + "@noble/hashes@1.8.0", + "@polkadot/networks", + "@polkadot/util", + "@polkadot/wasm-crypto", + "@polkadot/wasm-util", + "@polkadot/x-bigint", + "@polkadot/x-randomvalues", + "@scure/base@1.2.6", + "tslib@2.8.1" + ] + }, + "@polkadot/util@13.5.6": { + "integrity": "sha512-V+CkW2VdhcMWvl7eXdmlCLGqLxrKvXZtXE76KBbPP5n0Z+8DqQ58IHNOE9xe2LOgqDwIzdLlOUwkyF9Zj19y+Q==", + "dependencies": [ + "@polkadot/x-bigint", + "@polkadot/x-global", + "@polkadot/x-textdecoder", + "@polkadot/x-textencoder", + "@types/bn.js", + "bn.js@5.2.2", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-bridge@7.5.1_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-E+N3CSnX3YaXpAmfIQ+4bTyiAqJQKvVcMaXjkuL8Tp2zYffClWLG5e+RY15Uh+EWfUl9If4y6cLZi3D5NcpAGQ==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-util", + "@polkadot/x-randomvalues", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto-asmjs@7.5.1_@polkadot+util@13.5.6": { + "integrity": "sha512-jAg7Uusk+xeHQ+QHEH4c/N3b1kEGBqZb51cWe+yM61kKpQwVGZhNdlWetW6U23t/BMyZArIWMsZqmK/Ij0PHog==", + "dependencies": [ + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto-init@7.5.1_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-Obu4ZEo5jYO6sN31eqCNOXo88rPVkP9TrUOyynuFCnXnXr8V/HlmY/YkAd9F87chZnkTJRlzak17kIWr+i7w3A==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-bridge", + "@polkadot/wasm-crypto-asmjs", + "@polkadot/wasm-crypto-wasm", + "@polkadot/wasm-util", + "@polkadot/x-randomvalues", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto-wasm@7.5.1_@polkadot+util@13.5.6": { + "integrity": "sha512-S2yQSGbOGTcaV6UdipFVyEGanJvG6uD6Tg7XubxpiGbNAblsyYKeFcxyH1qCosk/4qf+GIUwlOL4ydhosZflqg==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-util", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto@7.5.1_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-acjt4VJ3w19v7b/SIPsV/5k9s6JsragHKPnwoZ0KTfBvAFXwzz80jUzVGxA06SKHacfCUe7vBRlz7M5oRby1Pw==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-bridge", + "@polkadot/wasm-crypto-asmjs", + "@polkadot/wasm-crypto-init", + "@polkadot/wasm-crypto-wasm", + "@polkadot/wasm-util", + "@polkadot/x-randomvalues", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-util@7.5.1_@polkadot+util@13.5.6": { + "integrity": "sha512-sbvu71isFhPXpvMVX+EkRnUg/+54Tx7Sf9BEMqxxoPj7cG1I/MKeDEwbQz6MaU4gm7xJqvEWCAemLFcXfHQ/2A==", + "dependencies": [ + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/x-bigint@13.5.6": { + "integrity": "sha512-HpqZJ9ud94iK/+0Ofacw7QdtvzFp6SucBBml4XwWZTWoLaLOGDsO7FoWE7yCuwPbX8nLgIM6YmQBeUoZmBtVqQ==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-fetch@13.5.6": { + "integrity": "sha512-gqx8c6lhnD7Qht+56J+4oeTA8YZ9bAPqzOt2cRJf9MTplMy44W6671T2p6hA3QMvzy4aBTxMie3uKc4tGpLu4A==", + "dependencies": [ + "@polkadot/x-global", + "node-fetch@3.3.2", + "tslib@2.8.1" + ] + }, + "@polkadot/x-global@13.5.6": { + "integrity": "sha512-iw97n0Bnl2284WgAK732LYR4DW6w5+COfBfHzkhiHqs5xwPEwWMgWGrf2hM8WAQqNIz6Ni8w/jagucPyQBur3Q==", + "dependencies": [ + "tslib@2.8.1" + ] + }, + "@polkadot/x-randomvalues@13.5.6_@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-w1F9G7FxrJ7+hGC8bh9/VpPH4KN8xmyzgiQdR7+rVB2V8KsKQBQidG69pj5Kwsh3oODOz0yQYsTG6Rm6TAJbGA==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-util", + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-textdecoder@13.5.6": { + "integrity": "sha512-jTGeYCxFh89KRrP7bNj1CPqKO36Onsi0iA6A+5YtRS5wjdQU+/OFM/EHLTP2nvkvZo/tOkOewMR9sausisUvVQ==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-textencoder@13.5.6": { + "integrity": "sha512-iVwz9+OrYCEF9QbNfr9M206mmWvY/AhDmGPfAIeTR4fRgKGVYqcP8RIF8iu/x0MVQWqiVO3vlhlUk7MfrmAnoQ==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-ws@13.5.6": { + "integrity": "sha512-247ktVp/iE57NTXjFpHaoPoDcvoEPb8+16r2Eq0IBQ2umOV7P6KmxvdNx5eFUvRsgXvBpNwUXE1WVnXjK/eDtA==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1", + "ws@8.18.3" + ] + }, "@protobufjs/aspromise@1.1.2": { "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, @@ -4716,6 +5119,38 @@ "blake2b" ] }, + "@substrate/connect-extension-protocol@2.2.2": { + "integrity": "sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA==" + }, + "@substrate/connect-known-chains@1.10.3": { + "integrity": "sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w==" + }, + "@substrate/connect@0.8.11_smoldot@2.0.26": { + "integrity": "sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==", + "dependencies": [ + "@substrate/connect-extension-protocol", + "@substrate/connect-known-chains", + "@substrate/light-client-extension-helpers", + "smoldot" + ], + "deprecated": true + }, + "@substrate/light-client-extension-helpers@1.0.0_smoldot@2.0.26_@polkadot-api+substrate-client@0.1.4_rxjs@7.8.2": { + "integrity": "sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==", + "dependencies": [ + "@polkadot-api/json-rpc-provider", + "@polkadot-api/json-rpc-provider-proxy", + "@polkadot-api/observable-client", + "@polkadot-api/substrate-client", + "@substrate/connect-extension-protocol", + "@substrate/connect-known-chains", + "rxjs@7.8.2", + "smoldot" + ] + }, + "@substrate/ss58-registry@1.51.0": { + "integrity": "sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==" + }, "@svgr/babel-plugin-add-jsx-attribute@8.0.0_@babel+core@7.28.3": { "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", "dependencies": [ @@ -4887,6 +5322,12 @@ "@babel/types" ] }, + "@types/bn.js@5.2.0": { + "integrity": "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==", + "dependencies": [ + "@types/node@22.15.15" + ] + }, "@types/body-parser@1.19.6": { "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dependencies": [ @@ -5864,6 +6305,13 @@ ], "bin": true }, + "avail-js-sdk@0.4.2": { + "integrity": "sha512-5lW1l9pxYm+OGKSmJsETx3L/9bu784x7h3CuMcHB1x+mZNWBCRe14jRvTFCbGo3WIMvjSjDtScjI+ve6IBFL8w==", + "dependencies": [ + "@polkadot/api", + "neverthrow" + ] + }, "available-typed-arrays@1.0.7": { "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dependencies": [ @@ -10462,6 +10910,9 @@ "ufo" ] }, + "mock-socket@9.3.1": { + "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==" + }, "module-details-from-path@1.0.4": { "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==" }, @@ -10532,6 +10983,12 @@ "neo-async@2.6.2": { "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "neverthrow@8.2.0": { + "integrity": "sha512-kOCT/1MCPAxY5iUV3wytNFUMUolzuwd/VF/1KCx7kf6CutrOsTie+84zTGTpgQycjvfLdBBdvBvFLqFD2c0wkQ==", + "optionalDependencies": [ + "@rollup/rollup-linux-x64-gnu" + ] + }, "no-case@3.0.4": { "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dependencies": [ @@ -10543,6 +11000,14 @@ "integrity": "sha512-WmS3EUGw+vXHlTgiUPi3NzbZNwH6+uGX0QLGgqG+aFSJ5rkX/Ee0nuwHBJfZTfQwwR8lGO819NEIwQ7CGhkdEQ==", "deprecated": true }, + "nock@13.5.6": { + "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "dependencies": [ + "debug@4.4.1", + "json-stringify-safe", + "propagate" + ] + }, "node-domexception@1.0.0": { "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "deprecated": true @@ -11872,6 +12337,9 @@ "react-is" ] }, + "propagate@2.0.1": { + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==" + }, "property-information@6.5.0": { "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==" }, @@ -12846,6 +13314,12 @@ "is-fullwidth-code-point@5.0.0" ] }, + "smoldot@2.0.26": { + "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", + "dependencies": [ + "ws@8.18.3" + ] + }, "snake-case@3.0.4": { "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", "dependencies": [ @@ -14343,6 +14817,13 @@ "npm:viem@^2.21.3" ] }, + "e2e/shared/contracts/avail": { + "dependencies": [ + "npm:@paimaexample/npm-avail-light-client@0.3.30", + "npm:@paimaexample/npm-avail-node@0.3.30", + "npm:avail-js-sdk@~0.4.2" + ] + }, "e2e/shared/contracts/cardano": { "dependencies": [ "jsr:@std/toml@*", @@ -14581,6 +15062,7 @@ "npm:@sinclair/typebox@~0.34.30", "npm:@utxorpc/sdk@~0.6.8", "npm:@utxorpc/spec@0.16", + "npm:avail-js-sdk@~0.4.2", "npm:denque@^2.1.0", "npm:effection@3.5.0", "npm:graphql-ws@^6.0.6", diff --git a/e2e/client/node/src/state-machine.ts b/e2e/client/node/src/state-machine.ts index 34854d1e7..08cc16c58 100644 --- a/e2e/client/node/src/state-machine.ts +++ b/e2e/client/node/src/state-machine.ts @@ -94,7 +94,11 @@ stm.addStateTransition( "avail-app-state", function* (data) { const { payload } = data.parsedInput; - console.log("📦 Avail App state has message:", payload.message); + const parsedPayload = JSON.parse(payload.suppliedValue); + console.log( + "📦 Avail App state has message:", + parsedPayload.message || parsedPayload, + ); return; }, ); diff --git a/e2e/shared/data-types/src/config.ts b/e2e/shared/data-types/src/config.ts index 97e725bd3..573bc4a1d 100644 --- a/e2e/shared/data-types/src/config.ts +++ b/e2e/shared/data-types/src/config.ts @@ -191,10 +191,10 @@ export const localhostConfig = new ConfigBuilder() name: "parallelAvail", type: ConfigSyncProtocolType.AVAIL_PARALLEL, rpc: network.nodeUrl, - lightClient: 'http://127.0.0.1:7007', + lightClient: "http://127.0.0.1:7007", startBlockHeight: 1, pollingInterval: 20_000, - delayMs: 40_000, + delayMs: 0, }), ); diff --git a/e2e/shared/data-types/src/grammar.ts b/e2e/shared/data-types/src/grammar.ts index 0917d9064..994e675ab 100644 --- a/e2e/shared/data-types/src/grammar.ts +++ b/e2e/shared/data-types/src/grammar.ts @@ -61,14 +61,16 @@ export const grammar = { [ "payload", Type.Object({ - message: Type.String(), + suppliedValue: Type.String(), }), ], ], // Auto-generate other primitives, but exclude midnight (we define it explicitly above) ...Object.fromEntries( Object.entries(mapPrimitivesToGrammar(localhostConfig.primitives)) - .filter(([key]) => key !== "midnightContractState" && key !== "avail-app-state"), + .filter(([key]) => + key !== "midnightContractState" && key !== "avail-app-state" + ), ), } as const satisfies GrammarDefinition; diff --git a/packages/node-sdk/sm/primitives/avail/contract-state.ts b/packages/node-sdk/sm/primitives/avail/contract-state.ts index f71983cb8..9a63be936 100644 --- a/packages/node-sdk/sm/primitives/avail/contract-state.ts +++ b/packages/node-sdk/sm/primitives/avail/contract-state.ts @@ -1,8 +1,8 @@ import { createScheduledData, insertPrimitiveAccounting } from "@paima/db"; import { BuiltinTransitions, generateRawStmInput } from "@paima/concise"; import { - type ConfigPrimitivePayloadType, ConfigPrimitiveAccountingPayloadType, + type ConfigPrimitivePayloadType, ConfigPrimitiveType, type ConfigSyncProtocolType, type FlattenSyncProtocolIOFor, @@ -14,16 +14,16 @@ import type { PaimaBlockNumber } from "@paima/utils"; export default function* processAvailPaimaL2Datum( paima_block_height: PaimaBlockNumber, response: FlattenSyncProtocolIOFor< - ConfigSyncProtocolType.AVAIL_PARALLEL, - ConfigPrimitiveType.AvailPaimaL2, - ConfigPrimitivePayloadType.Event + ConfigSyncProtocolType.AVAIL_PARALLEL, + ConfigPrimitiveType.AvailPaimaL2, + ConfigPrimitivePayloadType.Event >, ): StateUpdateStream { const { scheduledPrefix } = response.input; const { payload, syncProtocol } = response.output; const scheduledInputData = generateRawStmInput( BuiltinTransitions[ConfigPrimitiveType.AvailPaimaL2] - .scheduledPrefix, + .scheduledPrefix, scheduledPrefix, { payload }, ); @@ -37,7 +37,7 @@ export default function* processAvailPaimaL2Datum( yield* createScheduledData( JSON.stringify(scheduledInputData), { - blockHeight: syncProtocol.payload.ownChain.blockNumber, + blockHeight: paima_block_height, }, { primitiveName: response.output.syncProtocol.payload.primitiveName, @@ -45,7 +45,7 @@ export default function* processAvailPaimaL2Datum( caip2: response.output.syncProtocol.payload.caip2, fromAddress: response.input.contractAddress, contractAddress: response.input.contractAddress, - } + }, ); } -} \ No newline at end of file +} diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts index 7e3befcbc..337eeeb60 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/AvailClient.ts @@ -30,7 +30,7 @@ export class AvailClient { const num = status.blocks?.latest as number; // const num = header.number; // return num.toNumber(); - return num; + return Math.max(num - 1, 1); } async getBlockFromHash(hash: string): Promise { @@ -58,7 +58,10 @@ export class AvailClient { } async getBlockDataFromHeight(height: number): Promise { - const response = await fetch(`${this.url}/v2/blocks/${height}/data`); + let response = await fetch(`${this.url}/v2/blocks/${height}/data`); + if (response.status === 400) { + response = await fetch(`${this.url}/v2/blocks/${height + 1}/data`); + } if (!response.ok) { throw new Error( `Failed to get block data from height ${height}, status: ${response.status}`, diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts index f1b809603..200f1a1dc 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/fetcher.ts @@ -15,7 +15,7 @@ import type { import type { RootOutput, RootPage } from "../types.ts"; import type { Input, Output, Page, PrimitiveType } from "./types.ts"; import { AvailClient } from "./AvailClient.ts"; -import { all, call, type Operation } from "effection"; +import { all, call, type Operation, sleep } from "effection"; import { bound } from "@paima/utils"; export class AvailFetcher extends BaseDataFetcher< diff --git a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts index f0830d6b7..3329c62aa 100644 --- a/packages/node-sdk/sync/src/sync-protocols/avail/state.ts +++ b/packages/node-sdk/sync/src/sync-protocols/avail/state.ts @@ -49,9 +49,9 @@ export class AvailSyncState extends SyncState< @bound override toRootPage(data: Output): RootPage { - // Avail headers include `received_at` (ms). Use it as the chain page. + // Avail headers include `received_at` (sec). Use it as the chain page. return applyDelay( - data.raw.received_at, + data.raw.received_at * 1000, this.config.syncProtocol.delayMs, ); } diff --git a/templates/evm-midnight/deno.lock b/templates/evm-midnight/deno.lock index 61b67bf46..e16d849af 100644 --- a/templates/evm-midnight/deno.lock +++ b/templates/evm-midnight/deno.lock @@ -139,6 +139,7 @@ "npm:@wagmi/cli@2.3.1": "2.3.1_zod@3.25.76_esbuild@0.25.9_picomatch@3.0.1", "npm:abitype@^1.0.8": "1.0.8_zod@3.25.76", "npm:assert-never@^1.4.0": "1.4.0", + "npm:avail-js-sdk@~0.4.2": "0.4.2", "npm:bech32@2": "2.0.0", "npm:bs58@6": "6.0.0", "npm:bs58check@4": "4.0.0", @@ -2503,6 +2504,388 @@ "@pkgjs/parseargs@0.11.0": { "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==" }, + "@polkadot-api/json-rpc-provider-proxy@0.1.0": { + "integrity": "sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==" + }, + "@polkadot-api/json-rpc-provider@0.0.1": { + "integrity": "sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==" + }, + "@polkadot-api/metadata-builders@0.3.2": { + "integrity": "sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==", + "dependencies": [ + "@polkadot-api/substrate-bindings", + "@polkadot-api/utils" + ] + }, + "@polkadot-api/observable-client@0.3.2_@polkadot-api+substrate-client@0.1.4_rxjs@7.8.2": { + "integrity": "sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==", + "dependencies": [ + "@polkadot-api/metadata-builders", + "@polkadot-api/substrate-bindings", + "@polkadot-api/substrate-client", + "@polkadot-api/utils", + "rxjs@7.8.2" + ] + }, + "@polkadot-api/substrate-bindings@0.6.0": { + "integrity": "sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==", + "dependencies": [ + "@noble/hashes@1.8.0", + "@polkadot-api/utils", + "@scure/base@1.2.6", + "scale-ts" + ] + }, + "@polkadot-api/substrate-client@0.1.4": { + "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", + "dependencies": [ + "@polkadot-api/json-rpc-provider", + "@polkadot-api/utils" + ] + }, + "@polkadot-api/utils@0.1.0": { + "integrity": "sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==" + }, + "@polkadot/api-augment@15.10.2": { + "integrity": "sha512-CCli5ltPiJEyQF/8DmTRpTfYKHY4W0B+xQDmzKgFmd+Q64Qot0fGpsaZXZftef1Tuoh0Uqak9qM+6B4APXIPkQ==", + "dependencies": [ + "@polkadot/api-base", + "@polkadot/rpc-augment", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-augment@15.10.2", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/api-base@15.10.2": { + "integrity": "sha512-7DJw++5IbPrsLPGcTlIZbMOretfvQJG80CW8+A+t2BLxbbv+I2neWNQ9QV9O28XsbOHzNgKHXuRyirdaG/dvrg==", + "dependencies": [ + "@polkadot/rpc-core", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/util", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/api-derive@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-tF9DZvdm7hkRIJ1HtJzu73vdqQWBr8935YSN/RNsRb4FhJK5cHaC2uB4NLdRMnyUjmH0JRSnvWFq+HHcVxFJZw==", + "dependencies": [ + "@polkadot/api", + "@polkadot/api-augment", + "@polkadot/api-base", + "@polkadot/rpc-core", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/api@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-UM/510TwdugPjMpfyhhMNOZJ3M2ftRk0Ftxe+WSWev3o1u0dxqGuIN6fN0c224CHXIr58uWXUoMRHi6Cnfaxhw==", + "dependencies": [ + "@polkadot/api-augment", + "@polkadot/api-base", + "@polkadot/api-derive", + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/rpc-augment", + "@polkadot/rpc-core", + "@polkadot/rpc-provider", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-augment@15.10.2", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/types-known", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "eventemitter3@5.0.1", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/keyring@13.5.6": { + "integrity": "sha512-Ybe6Mflrh96FKR5tfEaf/93RxJD7x9UigseNOJW6Yd8LF+GesdxrqmZD7zh+53Hb7smGQWf/0FCfwhoWZVgPUQ==" + }, + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-Ybe6Mflrh96FKR5tfEaf/93RxJD7x9UigseNOJW6Yd8LF+GesdxrqmZD7zh+53Hb7smGQWf/0FCfwhoWZVgPUQ==", + "dependencies": [ + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "tslib@2.8.1" + ] + }, + "@polkadot/networks@13.5.6": { + "integrity": "sha512-9HqUIBOHnz9x/ssPb0aOD/7XcU8vGokEYpLoNgexFNIJzqDgrDHXR197iFpkbMqA/+98zagrvYUyPYj1yYs9Jw==", + "dependencies": [ + "@polkadot/util", + "@substrate/ss58-registry", + "tslib@2.8.1" + ] + }, + "@polkadot/rpc-augment@15.10.2": { + "integrity": "sha512-9QQ8utyAEdEl7iScteIN59EBu8eNZjZa8AfKBitbdq1Hezd+WPil5LdoYi+wmJOMhZHeDT1s7/j2+kY1Z2Vymg==", + "dependencies": [ + "@polkadot/rpc-core", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/rpc-core@15.10.2": { + "integrity": "sha512-vqDvr1WcHH3WPzDV4WTlf2S5cDmIoFPciynJ8eNcKqR3mG7Cqd0iL+MG6s0KFXdSY2Qvtl+0C6yZN0xr4Ha6BQ==", + "dependencies": [ + "@polkadot/rpc-augment", + "@polkadot/rpc-provider", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/util", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/rpc-provider@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-kqpPW8U0stVW+uOZP8g5d87Xb8rbXJR5PUub6xgGG6AOMbbvvuCU3GSohu/iozo4p9uD7TGH90jvbxj1rjJVMA==", + "dependencies": [ + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-support", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "@polkadot/x-fetch", + "@polkadot/x-global", + "@polkadot/x-ws", + "eventemitter3@5.0.1", + "mock-socket", + "nock", + "tslib@2.8.1" + ], + "optionalDependencies": [ + "@substrate/connect" + ] + }, + "@polkadot/types-augment@15.10.2": { + "integrity": "sha512-X/xh+Dzud6OIyr7q8xttAwn+Fb5hKImIWEO1oG8WcInqv+P0vRyu7Tds+2ut9t64sJi3ydJ7I+T+WxZYheCU7g==", + "dependencies": [ + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-augment@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-X/xh+Dzud6OIyr7q8xttAwn+Fb5hKImIWEO1oG8WcInqv+P0vRyu7Tds+2ut9t64sJi3ydJ7I+T+WxZYheCU7g==", + "dependencies": [ + "@polkadot/types@15.10.2", + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-codec@15.10.2": { + "integrity": "sha512-dhwbaukUZiYDW3QAAnLAFThYE5hQGdwBMWOVTt9+aBWxEKovLK93j0V30tEzMUtrZy8xaRWdhdDeQ3DSmxEP6w==", + "dependencies": [ + "@polkadot/util", + "@polkadot/x-bigint", + "tslib@2.8.1" + ] + }, + "@polkadot/types-create@15.10.2": { + "integrity": "sha512-vqXwPUSgx/By31qSkhOR5GN6zMbF1MkiX3F1g5KKHaRE8p/DdTry4LhufxhtK1mr9eBWvVGXxCOZdwjQco2M1A==", + "dependencies": [ + "@polkadot/types-codec", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-known@15.10.2": { + "integrity": "sha512-vs02WiIlLualrrh/EuA5qzK6QzatVPqBBNqa66dUtmyhJy48OEelBK+QLfOIQvZKU0ModEunoVrnxuY+O1DCmA==", + "dependencies": [ + "@polkadot/networks", + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types-support@15.10.2": { + "integrity": "sha512-sHamH6MehJa7aGZ/DHTB6vJAhSN5VrJx5lpDpb3xgBFTr0cVc5IsociqgJ/mgvyEIdLF3laraPxREqxCmuxTaQ==", + "dependencies": [ + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/types@15.10.2": { + "integrity": "sha512-/wDwKdDijxSXyNk5YezhVitdFxoQaTSSG9KXa7dEWujtmS/51UHmt9+P3W8b8D8kKaCvumahf/ww3GJI6s0Eqw==", + "dependencies": [ + "@polkadot/keyring@13.5.6", + "@polkadot/types-augment@15.10.2", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/types@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6": { + "integrity": "sha512-/wDwKdDijxSXyNk5YezhVitdFxoQaTSSG9KXa7dEWujtmS/51UHmt9+P3W8b8D8kKaCvumahf/ww3GJI6s0Eqw==", + "dependencies": [ + "@polkadot/keyring@13.5.6_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-augment@15.10.2_@polkadot+util@13.5.6_@polkadot+util-crypto@13.5.6__@polkadot+util@13.5.6__@polkadot+x-randomvalues@13.5.6___@polkadot+util@13.5.6___@polkadot+wasm-util@7.5.1____@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6", + "@polkadot/types-codec", + "@polkadot/types-create", + "@polkadot/util", + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6", + "rxjs@7.8.2", + "tslib@2.8.1" + ] + }, + "@polkadot/util-crypto@13.5.6": { + "integrity": "sha512-1l+t5lVc9UWxvbJe7/3V+QK8CwrDPuQjDK6FKtDZgZCU0JRrjySOxV0J4PeDIv8TgXZtbIcQFVUhIsJTyKZZJQ==", + "dependencies": [ + "@noble/curves@1.9.6", + "@noble/hashes@1.8.0", + "@polkadot/networks" + ] + }, + "@polkadot/util-crypto@13.5.6_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-1l+t5lVc9UWxvbJe7/3V+QK8CwrDPuQjDK6FKtDZgZCU0JRrjySOxV0J4PeDIv8TgXZtbIcQFVUhIsJTyKZZJQ==", + "dependencies": [ + "@noble/curves@1.9.6", + "@noble/hashes@1.8.0", + "@polkadot/networks", + "@polkadot/util", + "@polkadot/wasm-crypto", + "@polkadot/wasm-util", + "@polkadot/x-bigint", + "@polkadot/x-randomvalues", + "@scure/base@1.2.6", + "tslib@2.8.1" + ] + }, + "@polkadot/util@13.5.6": { + "integrity": "sha512-V+CkW2VdhcMWvl7eXdmlCLGqLxrKvXZtXE76KBbPP5n0Z+8DqQ58IHNOE9xe2LOgqDwIzdLlOUwkyF9Zj19y+Q==", + "dependencies": [ + "@polkadot/x-bigint", + "@polkadot/x-global", + "@polkadot/x-textdecoder", + "@polkadot/x-textencoder", + "@types/bn.js", + "bn.js@5.2.2", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-bridge@7.5.1_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-E+N3CSnX3YaXpAmfIQ+4bTyiAqJQKvVcMaXjkuL8Tp2zYffClWLG5e+RY15Uh+EWfUl9If4y6cLZi3D5NcpAGQ==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-util", + "@polkadot/x-randomvalues", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto-asmjs@7.5.1_@polkadot+util@13.5.6": { + "integrity": "sha512-jAg7Uusk+xeHQ+QHEH4c/N3b1kEGBqZb51cWe+yM61kKpQwVGZhNdlWetW6U23t/BMyZArIWMsZqmK/Ij0PHog==", + "dependencies": [ + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto-init@7.5.1_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-Obu4ZEo5jYO6sN31eqCNOXo88rPVkP9TrUOyynuFCnXnXr8V/HlmY/YkAd9F87chZnkTJRlzak17kIWr+i7w3A==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-bridge", + "@polkadot/wasm-crypto-asmjs", + "@polkadot/wasm-crypto-wasm", + "@polkadot/wasm-util", + "@polkadot/x-randomvalues", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto-wasm@7.5.1_@polkadot+util@13.5.6": { + "integrity": "sha512-S2yQSGbOGTcaV6UdipFVyEGanJvG6uD6Tg7XubxpiGbNAblsyYKeFcxyH1qCosk/4qf+GIUwlOL4ydhosZflqg==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-util", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-crypto@7.5.1_@polkadot+util@13.5.6_@polkadot+x-randomvalues@13.5.6__@polkadot+util@13.5.6__@polkadot+wasm-util@7.5.1___@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-acjt4VJ3w19v7b/SIPsV/5k9s6JsragHKPnwoZ0KTfBvAFXwzz80jUzVGxA06SKHacfCUe7vBRlz7M5oRby1Pw==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-bridge", + "@polkadot/wasm-crypto-asmjs", + "@polkadot/wasm-crypto-init", + "@polkadot/wasm-crypto-wasm", + "@polkadot/wasm-util", + "@polkadot/x-randomvalues", + "tslib@2.8.1" + ] + }, + "@polkadot/wasm-util@7.5.1_@polkadot+util@13.5.6": { + "integrity": "sha512-sbvu71isFhPXpvMVX+EkRnUg/+54Tx7Sf9BEMqxxoPj7cG1I/MKeDEwbQz6MaU4gm7xJqvEWCAemLFcXfHQ/2A==", + "dependencies": [ + "@polkadot/util", + "tslib@2.8.1" + ] + }, + "@polkadot/x-bigint@13.5.6": { + "integrity": "sha512-HpqZJ9ud94iK/+0Ofacw7QdtvzFp6SucBBml4XwWZTWoLaLOGDsO7FoWE7yCuwPbX8nLgIM6YmQBeUoZmBtVqQ==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-fetch@13.5.6": { + "integrity": "sha512-gqx8c6lhnD7Qht+56J+4oeTA8YZ9bAPqzOt2cRJf9MTplMy44W6671T2p6hA3QMvzy4aBTxMie3uKc4tGpLu4A==", + "dependencies": [ + "@polkadot/x-global", + "node-fetch@3.3.2", + "tslib@2.8.1" + ] + }, + "@polkadot/x-global@13.5.6": { + "integrity": "sha512-iw97n0Bnl2284WgAK732LYR4DW6w5+COfBfHzkhiHqs5xwPEwWMgWGrf2hM8WAQqNIz6Ni8w/jagucPyQBur3Q==", + "dependencies": [ + "tslib@2.8.1" + ] + }, + "@polkadot/x-randomvalues@13.5.6_@polkadot+util@13.5.6_@polkadot+wasm-util@7.5.1__@polkadot+util@13.5.6": { + "integrity": "sha512-w1F9G7FxrJ7+hGC8bh9/VpPH4KN8xmyzgiQdR7+rVB2V8KsKQBQidG69pj5Kwsh3oODOz0yQYsTG6Rm6TAJbGA==", + "dependencies": [ + "@polkadot/util", + "@polkadot/wasm-util", + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-textdecoder@13.5.6": { + "integrity": "sha512-jTGeYCxFh89KRrP7bNj1CPqKO36Onsi0iA6A+5YtRS5wjdQU+/OFM/EHLTP2nvkvZo/tOkOewMR9sausisUvVQ==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-textencoder@13.5.6": { + "integrity": "sha512-iVwz9+OrYCEF9QbNfr9M206mmWvY/AhDmGPfAIeTR4fRgKGVYqcP8RIF8iu/x0MVQWqiVO3vlhlUk7MfrmAnoQ==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1" + ] + }, + "@polkadot/x-ws@13.5.6": { + "integrity": "sha512-247ktVp/iE57NTXjFpHaoPoDcvoEPb8+16r2Eq0IBQ2umOV7P6KmxvdNx5eFUvRsgXvBpNwUXE1WVnXjK/eDtA==", + "dependencies": [ + "@polkadot/x-global", + "tslib@2.8.1", + "ws@8.18.3" + ] + }, "@protobufjs/aspromise@1.1.2": { "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, @@ -2794,6 +3177,38 @@ "blake2b" ] }, + "@substrate/connect-extension-protocol@2.2.2": { + "integrity": "sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA==" + }, + "@substrate/connect-known-chains@1.10.3": { + "integrity": "sha512-OJEZO1Pagtb6bNE3wCikc2wrmvEU5x7GxFFLqqbz1AJYYxSlrPCGu4N2og5YTExo4IcloNMQYFRkBGue0BKZ4w==" + }, + "@substrate/connect@0.8.11_smoldot@2.0.26": { + "integrity": "sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==", + "dependencies": [ + "@substrate/connect-extension-protocol", + "@substrate/connect-known-chains", + "@substrate/light-client-extension-helpers", + "smoldot" + ], + "deprecated": true + }, + "@substrate/light-client-extension-helpers@1.0.0_smoldot@2.0.26_@polkadot-api+substrate-client@0.1.4_rxjs@7.8.2": { + "integrity": "sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==", + "dependencies": [ + "@polkadot-api/json-rpc-provider", + "@polkadot-api/json-rpc-provider-proxy", + "@polkadot-api/observable-client", + "@polkadot-api/substrate-client", + "@substrate/connect-extension-protocol", + "@substrate/connect-known-chains", + "rxjs@7.8.2", + "smoldot" + ] + }, + "@substrate/ss58-registry@1.51.0": { + "integrity": "sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==" + }, "@swc/core-darwin-arm64@1.13.5": { "integrity": "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==", "os": ["darwin"], @@ -2921,6 +3336,12 @@ "@babel/types" ] }, + "@types/bn.js@5.2.0": { + "integrity": "sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q==", + "dependencies": [ + "@types/node@22.15.15" + ] + }, "@types/bunyan@1.8.9": { "integrity": "sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==", "dependencies": [ @@ -3310,6 +3731,13 @@ "atomic-sleep@1.0.0": { "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" }, + "avail-js-sdk@0.4.2": { + "integrity": "sha512-5lW1l9pxYm+OGKSmJsETx3L/9bu784x7h3CuMcHB1x+mZNWBCRe14jRvTFCbGo3WIMvjSjDtScjI+ve6IBFL8w==", + "dependencies": [ + "@polkadot/api", + "neverthrow" + ] + }, "available-typed-arrays@1.0.7": { "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dependencies": [ @@ -5008,6 +5436,9 @@ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "bin": true }, + "mock-socket@9.3.1": { + "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==" + }, "module-details-from-path@1.0.4": { "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==" }, @@ -5047,10 +5478,24 @@ ], "bin": true }, + "neverthrow@8.2.0": { + "integrity": "sha512-kOCT/1MCPAxY5iUV3wytNFUMUolzuwd/VF/1KCx7kf6CutrOsTie+84zTGTpgQycjvfLdBBdvBvFLqFD2c0wkQ==", + "optionalDependencies": [ + "@rollup/rollup-linux-x64-gnu" + ] + }, "no-case@4.0.0": { "integrity": "sha512-WmS3EUGw+vXHlTgiUPi3NzbZNwH6+uGX0QLGgqG+aFSJ5rkX/Ee0nuwHBJfZTfQwwR8lGO819NEIwQ7CGhkdEQ==", "deprecated": true }, + "nock@13.5.6": { + "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "dependencies": [ + "debug", + "json-stringify-safe", + "propagate" + ] + }, "node-domexception@1.0.0": { "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "deprecated": true @@ -5484,6 +5929,9 @@ "react-is" ] }, + "propagate@2.0.1": { + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==" + }, "protobufjs@7.5.4": { "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", "dependencies": [ @@ -5869,6 +6317,12 @@ "sisteransi@1.0.5": { "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, + "smoldot@2.0.26": { + "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", + "dependencies": [ + "ws@8.18.3" + ] + }, "sonic-boom@4.2.0": { "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", "dependencies": [ @@ -6767,7 +7221,8 @@ "packages/shared/contracts/avail": { "dependencies": [ "npm:@paimaexample/npm-avail-light-client@0.3.30", - "npm:@paimaexample/npm-avail-node@0.3.30" + "npm:@paimaexample/npm-avail-node@0.3.30", + "npm:avail-js-sdk@~0.4.2" ] }, "packages/shared/contracts/cardano": { From 677685a966360184d26f1b64cc67c97234c925cf Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Fri, 12 Sep 2025 20:57:03 -0300 Subject: [PATCH 16/17] clean --- .../sm/primitives/avail/contract-state.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/node-sdk/sm/primitives/avail/contract-state.ts b/packages/node-sdk/sm/primitives/avail/contract-state.ts index 9a63be936..d89d331a0 100644 --- a/packages/node-sdk/sm/primitives/avail/contract-state.ts +++ b/packages/node-sdk/sm/primitives/avail/contract-state.ts @@ -19,7 +19,7 @@ export default function* processAvailPaimaL2Datum( ConfigPrimitivePayloadType.Event >, ): StateUpdateStream { - const { scheduledPrefix } = response.input; + const { scheduledPrefix, contractAddress } = response.input; const { payload, syncProtocol } = response.output; const scheduledInputData = generateRawStmInput( BuiltinTransitions[ConfigPrimitiveType.AvailPaimaL2] @@ -28,10 +28,10 @@ export default function* processAvailPaimaL2Datum( { payload }, ); yield* World.resolve(insertPrimitiveAccounting, { - primitive_name: response.output.syncProtocol.payload.primitiveName, + primitive_name: syncProtocol.payload.primitiveName, paima_block_height: paima_block_height, payload_type: ConfigPrimitiveAccountingPayloadType.Event, - payload: JSON.stringify(response.output.payload) as any, + payload: JSON.stringify(payload) as any, }); if (scheduledPrefix) { yield* createScheduledData( @@ -40,11 +40,11 @@ export default function* processAvailPaimaL2Datum( blockHeight: paima_block_height, }, { - primitiveName: response.output.syncProtocol.payload.primitiveName, - txHash: response.output.syncProtocol.internal.transactionHash, - caip2: response.output.syncProtocol.payload.caip2, - fromAddress: response.input.contractAddress, - contractAddress: response.input.contractAddress, + primitiveName: syncProtocol.payload.primitiveName, + txHash: syncProtocol.internal.transactionHash, + caip2: syncProtocol.payload.caip2, + fromAddress: contractAddress, + contractAddress: contractAddress, }, ); } From bda3358936306cb7a4ffbabe722d9c97edde8acc Mon Sep 17 00:00:00 2001 From: Eduardo Soto Date: Mon, 15 Sep 2025 12:55:18 -0300 Subject: [PATCH 17/17] added avail_enabled flag in start.ts --- e2e/client/node/scripts/start.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/e2e/client/node/scripts/start.ts b/e2e/client/node/scripts/start.ts index 6674b75ca..094bc2032 100644 --- a/e2e/client/node/scripts/start.ts +++ b/e2e/client/node/scripts/start.ts @@ -20,6 +20,10 @@ const midnight_enabled = Deno ? (Deno.env.get("DISABLE_MIDNIGHT") === "true" ? false : true) : true; +const avail_enabled = Deno + ? (Deno.env.get("DISABLE_AVAIL") === "true" ? false : true) + : true; + const config = Value.Parse(OrchestratorConfig, { processes: { // Launch Dev DB & Collector @@ -33,7 +37,7 @@ const config = Value.Parse(OrchestratorConfig, { processesToLaunch: [ launchEvm("@e2e/evm-contracts"), yaci_enabled ? launchCardano("@e2e/cardano-contracts") : {}, - launchAvail("@e2e/avail-contracts"), + avail_enabled ? launchAvail("@e2e/avail-contracts") : {}, midnight_enabled ? launchMidnight("@e2e/midnight-contracts") : {}, { stopProcessAtPort: [10590],