From 4c87ad7159ce99f9dfa053342a02f5102480c704 Mon Sep 17 00:00:00 2001 From: Denis Carriere Date: Fri, 15 Mar 2024 12:40:54 +0100 Subject: [PATCH] add danchorsmart example --- examples/eos-danchorsmart.mjs | 108 ++++++++++++++++++++++++++++++++++ examples/ethereum-blobs.mjs | 68 +++++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 examples/eos-danchorsmart.mjs create mode 100644 examples/ethereum-blobs.mjs diff --git a/examples/eos-danchorsmart.mjs b/examples/eos-danchorsmart.mjs new file mode 100644 index 0000000..5230dbe --- /dev/null +++ b/examples/eos-danchorsmart.mjs @@ -0,0 +1,108 @@ +import { createRegistry, createRequest, applyParams } from "@substreams/core"; +import { readPackage } from "@substreams/manifest"; +import { BlockEmitter } from "@substreams/node"; +import { createNodeTransport } from "@substreams/node/createNodeTransport"; +import { APIClient, Serializer } from "@wharfkit/antelope"; + +// auth API token +// https://app.streamingfast.io/ +// https://app.pinax.network/ +if (!process.env.SUBSTREAMS_API_KEY) { + throw new Error("SUBSTREAMS_API_KEY is require"); +} +const token = process.env.SUBSTREAMS_API_KEY; + +// RPC API Client +const contract = "danchorsmart"; +const rpc = new APIClient({ url: "https://eos.api.eosnation.io" }); +const abi = (await rpc.v1.chain.get_abi(contract)).abi; +if ( !abi ) throw new Error("ABI not found"); + +// User parameters +const baseUrl = "https://eos.substreams.pinax.network:443"; +const manifest = "https://github.com/pinax-network/substreams/releases/download/common-v0.7.0/common-v0.7.0.spkg"; +const outputModule = "map_db_ops"; +const params = `map_db_ops=contract=${contract}` +const startBlockNum = 344396356; +const stopBlockNum = `+${60 * 86400 * 2}`; // +60 days (2 blocks per second) + +// Read Substream +const substreamPackage = await readPackage(manifest); +if (!substreamPackage.modules) { + throw new Error("No modules found in substream package"); +} +applyParams([params], substreamPackage.modules.modules); + +// Connect Transport +const registry = createRegistry(substreamPackage); +const transport = createNodeTransport(baseUrl, token, registry); +const request = createRequest({ + substreamPackage, + outputModule, + startBlockNum, + stopBlockNum, +}); + +// NodeJS Events +const emitter = new BlockEmitter(transport, request, registry); + +// Session Trace ID +emitter.on("session", (session) => { + console.dir(session); +}); + +function decode_table(dbOp, abi) { + let type = null; + for ( const struct of abi.tables ) { + if ( struct.name === dbOp.tableName ) { + type = struct.type; + } + } + if ( !type ) return null; + return { + ...dbOp, + oldData: decode_data(dbOp.oldData, abi, type), + newData: decode_data(dbOp.newData, abi, type), + }; +} + +function decode_data(arrayBuffer, abi, type) { + if ( !arrayBuffer) return null; + const data = Buffer.from(arrayBuffer, "base64").toString("hex"); + const decoded = Serializer.decode({data, abi, type}); + const values = {}; + for ( const [key, value] of Object.entries(decoded) ) { + values[key] = JSON.parse(JSON.stringify(value)); + } + return values; +} + +// Stream Blocks +emitter.on("anyMessage", (message, cursor, clock) => { + const block_num = Number(clock.number); + const timestamp = clock.timestamp.toDate(); + const seconds = Number(clock.timestamp.seconds); + for ( const dbOp of message.dbOps ?? [] ) { + if ( !dbOp.newData ) continue; + const data = decode_table(dbOp, abi); + if ( !data) continue; + console.log({...data, block_num, timestamp, seconds }); + } +}); + +// End of Stream +emitter.on("close", (error) => { + if (error) { + console.error(error); + } + console.timeEnd("🆗 close"); +}); + +// Fatal Error +emitter.on("fatalError", (error) => { + console.error(error); +}); + +console.log("✅ start"); +console.time("🆗 close"); +emitter.start(); diff --git a/examples/ethereum-blobs.mjs b/examples/ethereum-blobs.mjs new file mode 100644 index 0000000..57418ef --- /dev/null +++ b/examples/ethereum-blobs.mjs @@ -0,0 +1,68 @@ +import { createRegistry, createRequest } from "@substreams/core"; +import { readPackage } from "@substreams/manifest"; +import { BlockEmitter } from "@substreams/node"; +import { createNodeTransport } from "@substreams/node/createNodeTransport"; + +// auth API token +// https://app.streamingfast.io/ +// https://app.pinax.network/ +if (!process.env.SUBSTREAMS_API_KEY) { + throw new Error("SUBSTREAMS_API_KEY is require"); +} + +const token = process.env.SUBSTREAMS_API_KEY; +const baseUrl = "https://goerli.substreams.pinax.network:443"; + +// User parameters +const manifest = "https://github.com/pinax-network/substreams/releases/download/blobs-v0.2.0/eth-blobs-v0.2.0.spkg"; +const outputModule = "map_blobs"; +const startBlockNum = 7671800; +const stopBlockNum = "+10"; + +// Read Substream +const substreamPackage = await readPackage(manifest); +if (!substreamPackage.modules) { + throw new Error("No modules found in substream package"); +} + +// Connect Transport +const registry = createRegistry(substreamPackage); +const transport = createNodeTransport(baseUrl, token, registry); +const request = createRequest({ + substreamPackage, + outputModule, + startBlockNum, + stopBlockNum, +}); + +// NodeJS Events +const emitter = new BlockEmitter(transport, request, registry); + +// Session Trace ID +emitter.on("session", (session) => { + console.dir(session); +}); + +// Stream Blocks +emitter.on("anyMessage", (message, cursor, clock) => { + console.dir(message); + console.dir(cursor); + console.dir(clock); +}); + +// End of Stream +emitter.on("close", (error) => { + if (error) { + console.error(error); + } + console.timeEnd("🆗 close"); +}); + +// Fatal Error +emitter.on("fatalError", (error) => { + console.error(error); +}); + +console.log("✅ start"); +console.time("🆗 close"); +emitter.start(); \ No newline at end of file