├── .cargo
└── config.toml
├── .github
└── workflows
│ └── publish_to_npm.yaml
├── .gitignore
├── .npmignore
├── .yarn
└── releases
│ └── yarn-3.8.1.cjs
├── .yarnrc.yml
├── Cargo.toml
├── LICENSE
├── README.md
├── __test__
└── decoder.test.mjs
├── build.rs
├── docs
├── .nojekyll
├── assets
│ ├── highlight.css
│ ├── icons.js
│ ├── icons.svg
│ ├── main.js
│ ├── navigation.js
│ ├── search.js
│ └── style.css
├── classes
│ ├── CallDecoder.html
│ ├── Decoder.html
│ ├── EventStream.html
│ ├── HypersyncClient.html
│ └── QueryResponseStream.html
├── enums
│ ├── BlockField.html
│ ├── DataType.html
│ ├── HexOutput.html
│ ├── JoinMode.html
│ ├── LogField.html
│ ├── TraceField.html
│ └── TransactionField.html
├── functions
│ ├── presetQueryBlocksAndTransactionHashes.html
│ ├── presetQueryBlocksAndTransactions.html
│ ├── presetQueryLogs.html
│ └── presetQueryLogsOfEvent.html
├── index.html
├── interfaces
│ ├── AccessList.html
│ ├── Authorization.html
│ ├── AuthorizationSelection.html
│ ├── Block.html
│ ├── BlockSelection.html
│ ├── ClientConfig.html
│ ├── ColumnMapping.html
│ ├── DecodedEvent.html
│ ├── DecodedSolValue.html
│ ├── Event.html
│ ├── EventResponse.html
│ ├── Events.html
│ ├── FieldSelection.html
│ ├── Log.html
│ ├── LogSelection.html
│ ├── Query.html
│ ├── QueryResponse.html
│ ├── QueryResponseData.html
│ ├── RollbackGuard.html
│ ├── StreamConfig.html
│ ├── Trace.html
│ ├── TraceSelection.html
│ ├── Transaction.html
│ ├── TransactionSelection.html
│ └── Withdrawal.html
└── modules.html
├── examples
├── all-erc20
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── call_watch
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── parquet-out
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── reverse_wallet
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── simple-blocks-and-transaction-hashes
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── simple-blocks-and-transactions
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── simple-logs-of-event
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── simple-logs
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
├── wallet
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ │ └── app.ts
│ └── tsconfig.json
└── watch
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── src
│ └── app.ts
│ └── tsconfig.json
├── index.d.ts
├── index.js
├── npm
├── darwin-arm64
│ ├── README.md
│ └── package.json
├── darwin-x64
│ ├── README.md
│ └── package.json
├── linux-arm64-gnu
│ ├── README.md
│ └── package.json
├── linux-x64-gnu
│ ├── README.md
│ └── package.json
├── linux-x64-musl
│ ├── README.md
│ └── package.json
└── win32-x64-msvc
│ ├── README.md
│ └── package.json
├── package.json
├── src
├── config.rs
├── decode.rs
├── decode_call.rs
├── lib.rs
├── preset_query.rs
├── query.rs
└── types.rs
└── yarn.lock
/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [target.aarch64-unknown-linux-musl]
2 | linker = "aarch64-linux-musl-gcc"
3 | rustflags = ["-C", "target-feature=-crt-static"]
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/node
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=node
3 |
4 | ### Node ###
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # Diagnostic reports (https://nodejs.org/api/report.html)
14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
15 |
16 | # Runtime data
17 | pids
18 | *.pid
19 | *.seed
20 | *.pid.lock
21 |
22 | # Directory for instrumented libs generated by jscoverage/JSCover
23 | lib-cov
24 |
25 | # Coverage directory used by tools like istanbul
26 | coverage
27 | *.lcov
28 |
29 | # nyc test coverage
30 | .nyc_output
31 |
32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
33 | .grunt
34 |
35 | # Bower dependency directory (https://bower.io/)
36 | bower_components
37 |
38 | # node-waf configuration
39 | .lock-wscript
40 |
41 | # Compiled binary addons (https://nodejs.org/api/addons.html)
42 | build/Release
43 |
44 | # Dependency directories
45 | node_modules/
46 | jspm_packages/
47 |
48 | # TypeScript v1 declaration files
49 | typings/
50 |
51 | # TypeScript cache
52 | *.tsbuildinfo
53 |
54 | # Optional npm cache directory
55 | .npm
56 |
57 | # Optional eslint cache
58 | .eslintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variables file
76 | .env
77 | .env.test
78 |
79 | # parcel-bundler cache (https://parceljs.org/)
80 | .cache
81 |
82 | # Next.js build output
83 | .next
84 |
85 | # Nuxt.js build / generate output
86 | .nuxt
87 | dist
88 |
89 | # Gatsby files
90 | .cache/
91 | # Comment in the public line in if your project uses Gatsby and not Next.js
92 | # https://nextjs.org/blog/next-9-1#public-directory-support
93 | # public
94 |
95 | # vuepress build output
96 | .vuepress/dist
97 |
98 | # Serverless directories
99 | .serverless/
100 |
101 | # FuseBox cache
102 | .fusebox/
103 |
104 | # DynamoDB Local files
105 | .dynamodb/
106 |
107 | # TernJS port file
108 | .tern-port
109 |
110 | # Stores VSCode versions used for testing VSCode extensions
111 | .vscode-test
112 |
113 | # End of https://www.toptal.com/developers/gitignore/api/node
114 |
115 | # Created by https://www.toptal.com/developers/gitignore/api/macos
116 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos
117 |
118 | ### macOS ###
119 | # General
120 | .DS_Store
121 | .AppleDouble
122 | .LSOverride
123 |
124 | # Icon must end with two
125 | Icon
126 |
127 |
128 | # Thumbnails
129 | ._*
130 |
131 | # Files that might appear in the root of a volume
132 | .DocumentRevisions-V100
133 | .fseventsd
134 | .Spotlight-V100
135 | .TemporaryItems
136 | .Trashes
137 | .VolumeIcon.icns
138 | .com.apple.timemachine.donotpresent
139 |
140 | # Directories potentially created on remote AFP share
141 | .AppleDB
142 | .AppleDesktop
143 | Network Trash Folder
144 | Temporary Items
145 | .apdisk
146 |
147 | ### macOS Patch ###
148 | # iCloud generated files
149 | *.icloud
150 |
151 | # End of https://www.toptal.com/developers/gitignore/api/macos
152 |
153 | # Created by https://www.toptal.com/developers/gitignore/api/windows
154 | # Edit at https://www.toptal.com/developers/gitignore?templates=windows
155 |
156 | ### Windows ###
157 | # Windows thumbnail cache files
158 | Thumbs.db
159 | Thumbs.db:encryptable
160 | ehthumbs.db
161 | ehthumbs_vista.db
162 |
163 | # Dump file
164 | *.stackdump
165 |
166 | # Folder config file
167 | [Dd]esktop.ini
168 |
169 | # Recycle Bin used on file shares
170 | $RECYCLE.BIN/
171 |
172 | # Windows Installer files
173 | *.cab
174 | *.msi
175 | *.msix
176 | *.msm
177 | *.msp
178 |
179 | # Windows shortcuts
180 | *.lnk
181 |
182 | # End of https://www.toptal.com/developers/gitignore/api/windows
183 |
184 | #Added by cargo
185 |
186 | /target
187 | Cargo.lock
188 |
189 | .pnp.*
190 | .yarn/*
191 | !.yarn/patches
192 | !.yarn/plugins
193 | !.yarn/releases
194 | !.yarn/sdks
195 | !.yarn/versions
196 |
197 | *.node
198 |
199 | data/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | target
2 | Cargo.lock
3 | .cargo
4 | .github
5 | npm
6 | .eslintrc
7 | .prettierignore
8 | rustfmt.toml
9 | yarn.lock
10 | *.node
11 | .yarn
12 | __test__
13 | renovate.json
14 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nodeLinker: node-modules
2 |
3 | yarnPath: .yarn/releases/yarn-3.8.1.cjs
4 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | edition = "2021"
3 | name = "envio_hypersync-client"
4 | version = "0.0.0"
5 |
6 | [lib]
7 | crate-type = ["cdylib"]
8 |
9 | [dependencies]
10 | # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
11 | napi = { version = "2", default-features = false, features = [
12 | "napi9",
13 | "async",
14 | "serde-json",
15 | ] }
16 | napi-derive = "2"
17 | serde = { version = "1", features = ["derive"] }
18 | alloy-dyn-abi = "1.1"
19 | tokio = { version = "1", features = ["rt-multi-thread"] }
20 | env_logger = "0.11"
21 | faster-hex = "0.9.0"
22 | anyhow = "1"
23 | serde_json = "1"
24 | ruint = "1"
25 | alloy-primitives = "1.1"
26 |
27 | hypersync-client = "0.19.0"
28 |
29 | [build-dependencies]
30 | napi-build = "2.0.1"
31 |
32 | [profile.release]
33 | lto = true
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Node.js HyperSync Client
2 |
3 | HyperSync Client by [Envio](https://envio.dev).
4 |
5 | Read full documentation [here](https://docs.hypersync.xyz/docs/nodejs-client/introduction).
6 |
7 | ## Getting Started
8 |
9 | ```bash
10 | npm i @envio-dev/hypersync-client
11 | ```
12 |
13 | See [examples](examples) for usage.
14 |
--------------------------------------------------------------------------------
/__test__/decoder.test.mjs:
--------------------------------------------------------------------------------
1 | import test from "ava";
2 | import { Decoder, HypersyncClient } from "../index.js";
3 |
4 | test("Decodes event from etherscan", async (t) => {
5 | const decoder = Decoder.fromSignatures([
6 | "event Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)",
7 | ]);
8 |
9 | const log = {
10 | topics: [
11 | "0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde",
12 | "0x000000000000000000000000827922686190790b37229fd06084350e74485b72",
13 | "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
14 | "0x0000000000000000000000000000000000000000000000000000000000000001",
15 | ],
16 | data: "0x000000000000000000000000827922686190790b37229fd06084350e74485b72000000000000000000000000000000000000000000000000000000000bebae76000000000000000000000000000000000000000000000000000000000000270f000000000000000000000000000000000000000000000000000000000000270f",
17 | };
18 | const decoded = await decoder.decodeLogs([log]);
19 | t.is(decoded[0].indexed[1].val, -1n);
20 | });
21 |
22 | //skig the async test against hypersync endpoint
23 | test.skip("Fetches event from base", async (t) => {
24 | const decoder = Decoder.fromSignatures([
25 | "event Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)",
26 | ]);
27 | const client = HypersyncClient.new({ url: "https://base.hypersync.xyz" });
28 | const res = await client.getEvents({
29 | fromBlock: 13899663,
30 | toBlock: 13899664,
31 | logs: [
32 | {
33 | address: ["0x98c7A2338336d2d354663246F64676009c7bDa97"],
34 | topics: [
35 | [
36 | "0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde",
37 | ],
38 | ],
39 | },
40 | ],
41 | fieldSelection: {
42 | log: [
43 | "topic0",
44 | "topic1",
45 | "topic2",
46 | "topic3",
47 | "data",
48 | "log_index",
49 | "transaction_hash",
50 | ],
51 | },
52 | });
53 |
54 | const decoded = await decoder.decodeEvents(res.data);
55 | t.is(decoded[0].indexed[1].val, -1n);
56 | // console.log(decoded[0].indexed[1].val);
57 | // const decoder = Decoder.fromSignatures([
58 | // "event Mint(address sender, address indexed owner, int24 indexed tickLower, int24 indexed tickUpper, uint128 amount, uint256 amount0, uint256 amount1)",
59 | // ]);
60 | //
61 | // const log = {
62 | // topics: [
63 | // "0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde",
64 | // "0x000000000000000000000000827922686190790b37229fd06084350e74485b72",
65 | // "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
66 | // "0x0000000000000000000000000000000000000000000000000000000000000001",
67 | // ],
68 | // data: "0x000000000000000000000000827922686190790b37229fd06084350e74485b72000000000000000000000000000000000000000000000000000000000bebae76000000000000000000000000000000000000000000000000000000000000270f000000000000000000000000000000000000000000000000000000000000270f",
69 | // };
70 | // const decoded = await decoder.decodeLogs([log]);
71 | // t.is(decoded[0].indexed[1].val, -1n);
72 | });
73 |
--------------------------------------------------------------------------------
/build.rs:
--------------------------------------------------------------------------------
1 | extern crate napi_build;
2 |
3 | fn main() {
4 | napi_build::setup();
5 | }
6 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
--------------------------------------------------------------------------------
/docs/assets/highlight.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --light-code-background: #FFFFFF;
3 | --dark-code-background: #1E1E1E;
4 | }
5 |
6 | @media (prefers-color-scheme: light) { :root {
7 | --code-background: var(--light-code-background);
8 | } }
9 |
10 | @media (prefers-color-scheme: dark) { :root {
11 | --code-background: var(--dark-code-background);
12 | } }
13 |
14 | :root[data-theme='light'] {
15 | --code-background: var(--light-code-background);
16 | }
17 |
18 | :root[data-theme='dark'] {
19 | --code-background: var(--dark-code-background);
20 | }
21 |
22 | pre, code { background: var(--code-background); }
23 |
--------------------------------------------------------------------------------
/docs/assets/navigation.js:
--------------------------------------------------------------------------------
1 | window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA52VT28TMRDFv4vPEREVVCi3kkIjtFVFU8EBcTDeSdaKY6/8BxoQ3x3FYbN21h5bvfq995tZjT377Q+x8GzJgrwXiu0+chAtmZGe2o4sCEi3N/NRedXZvSAzsuOyJYt3f2fn9C219OnQw2V2OM8nV/D84Gzv7GX0LOSznxSX96qdVB3O88lGbZPfOpznk0+aMkhmRwVNS0OZ5UrmGJGeJy2pELfAVAt6hDBBjQEzD8SY8PoqmlouX5H98BOkXVsNdD/NByLGWB160OYg2VJwkHbKuTBgrM8O9OERTK+kgVxfCRPGvGEMjGm4CVrj0oLeUAZmPsox5OrtdQhxtlOa/6bHoaY5oaMatQYBrI55tmJw/8yTLK8Uo3g/sQWDnUa9VHLDt0lUaEBBSri9vKd9z2WGFDow1Ok9tP5aJ0mhoQK0VuILFQ4w1uDBcPmGip14w/AU8ojBUUSZPMNgYb/m8LsTWzBYo9KDbhQ63kZt8Q5CAwby+yVJ8Eoxis4jclSjjn/gMu7owpCPSogflO3uHNVtEhc5MNRp7SLvOzRgIP+/TRK8UoziI48tBdjwz86RBr0SU+xsYsTAX7ntWk1/UZHEjTIG6TUYsP7O+FVubmQbNLKipoNgBWyc9OdmXhWMK1+/qS/8kpqV5Rq1LdGPlnrYw+ZiX2eZ/50T9Pd/I5OmsrALAAA="
--------------------------------------------------------------------------------
/docs/classes/EventStream.html:
--------------------------------------------------------------------------------
1 |
EventStream | @envio-dev/hypersync-client Methods close close ( ) : Promise < void > Returns Promise < void >
--------------------------------------------------------------------------------
/docs/classes/QueryResponseStream.html:
--------------------------------------------------------------------------------
1 | QueryResponseStream | @envio-dev/hypersync-client Class QueryResponseStream Methods close close ( ) : Promise < void > Returns Promise < void >
--------------------------------------------------------------------------------
/docs/enums/HexOutput.html:
--------------------------------------------------------------------------------
1 | HexOutput | @envio-dev/hypersync-client Enumeration Members No Encode No Encode : "NoEncode"
Non Prefixed Non Prefixed : "NonPrefixed"
Prefixed Prefixed : "Prefixed"
--------------------------------------------------------------------------------
/docs/enums/JoinMode.html:
--------------------------------------------------------------------------------
1 | JoinMode | @envio-dev/hypersync-client Enumeration Members Join Nothing Join Nothing : 2
--------------------------------------------------------------------------------
/docs/functions/presetQueryBlocksAndTransactionHashes.html:
--------------------------------------------------------------------------------
1 | presetQueryBlocksAndTransactionHashes | @envio-dev/hypersync-client Function presetQueryBlocksAndTransactionHashes preset Query Blocks And Transaction Hashes ( fromBlock , toBlock ? ) : Query Parameters fromBlock : number Optional
toBlock : number
--------------------------------------------------------------------------------
/docs/functions/presetQueryBlocksAndTransactions.html:
--------------------------------------------------------------------------------
1 | presetQueryBlocksAndTransactions | @envio-dev/hypersync-client Function presetQueryBlocksAndTransactions preset Query Blocks And Transactions ( fromBlock , toBlock ? ) : Query Parameters fromBlock : number Optional
toBlock : number
--------------------------------------------------------------------------------
/docs/functions/presetQueryLogs.html:
--------------------------------------------------------------------------------
1 | presetQueryLogs | @envio-dev/hypersync-client preset Query Logs ( contractAddress , fromBlock , toBlock ? ) : Query Parameters contractAddress : string fromBlock : number Optional
toBlock : number
--------------------------------------------------------------------------------
/docs/functions/presetQueryLogsOfEvent.html:
--------------------------------------------------------------------------------
1 | presetQueryLogsOfEvent | @envio-dev/hypersync-client Function presetQueryLogsOfEvent preset Query Logs Of Event ( contractAddress , topic0 , fromBlock , toBlock ? ) : Query Parameters contractAddress : string topic0 : string fromBlock : number Optional
toBlock : number
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 | @envio-dev/hypersync-client
@envio-dev/hypersync-client
--------------------------------------------------------------------------------
/docs/interfaces/AccessList.html:
--------------------------------------------------------------------------------
1 | AccessList | @envio-dev/hypersync-client Properties Optional
address address ?: string
Optional
storage Keys storage Keys ?: string []
--------------------------------------------------------------------------------
/docs/interfaces/AuthorizationSelection.html:
--------------------------------------------------------------------------------
1 | AuthorizationSelection | @envio-dev/hypersync-client Interface AuthorizationSelection interface AuthorizationSelection { address ?: string [] ; chainId ?: number [] ; } Properties Optional
address address ?: string []
Optional
chain Id chain Id ?: number []
--------------------------------------------------------------------------------
/docs/interfaces/BlockSelection.html:
--------------------------------------------------------------------------------
1 | BlockSelection | @envio-dev/hypersync-client interface BlockSelection { hash ?: string [] ; miner ?: string [] ; } Properties Optional
hash hash ?: string []
Optional
miner miner ?: string []
--------------------------------------------------------------------------------
/docs/interfaces/DecodedEvent.html:
--------------------------------------------------------------------------------
1 | DecodedEvent | @envio-dev/hypersync-client
--------------------------------------------------------------------------------
/docs/interfaces/DecodedSolValue.html:
--------------------------------------------------------------------------------
1 | DecodedSolValue | @envio-dev/hypersync-client Interface DecodedSolValue
--------------------------------------------------------------------------------
/docs/interfaces/Event.html:
--------------------------------------------------------------------------------
1 | Event | @envio-dev/hypersync-client
--------------------------------------------------------------------------------
/docs/interfaces/LogSelection.html:
--------------------------------------------------------------------------------
1 | LogSelection | @envio-dev/hypersync-client interface LogSelection { address ?: string [] ; topics ?: string [] [] ; } Properties Optional
address address ?: string []
Optional
topics topics ?: string [] []
--------------------------------------------------------------------------------
/examples/all-erc20/README.md:
--------------------------------------------------------------------------------
1 | # Index all erc20 on the whole of Ethereum
2 |
3 | Example of using hypersync-client to get data for all erc20 transfers.
4 |
5 | The example uses the 'Transfer' event and counts all the amounts in the first batch of events that it recieves. The script doesn't scan the entire Ethereum chain, but rather goes through as many events as it can in the initial returned range.
6 |
7 | ## Prerequisites
8 |
9 | - Node.js (version 18.0.0 or above - rather stick to even/lts releases)
10 | - npm/yarn/pnpm
11 |
12 | ## Run
13 |
14 | ```bash
15 | git clone https://github.com/enviodev/hypersync-client-node.github
16 | cd hypersync-client-node/examples/all-erc20
17 | npm install
18 | npm build
19 | npm start
20 | ```
21 |
22 | ## Comments
23 |
24 | The code is well commented, so best you go through that directly. Things to note, this is just an example of the API, and not an accurate example. So it doesn't take into account different decimals of ERC20 tokens, it only runs the query once - so it only does the first ~1.3 million blocks, it also includes volume of intra-contract-interaction transfers which might not be considered volume.
25 |
26 | So areas that could be explored further in pursuit of learning how to use Hypersync:
27 |
28 | - Scan the full chain by repeating queries from the end block rage all the way until the head.
29 | - Scan only erc20 contracts you care about by including the contract addresses in the query.
30 | - Get the decimals of the erc20 tokens and convert the amounts to a standard unit (might not be completely feasible if unless you are doing a subset of erc20 tokens).
31 | - Analyze only the resultant change in erc20 balance in a transaction, and exclude for example if multiple intra-contract transfers happen. This could be a fun one to work out.
32 |
--------------------------------------------------------------------------------
/examples/all-erc20/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "all-erc20",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "tsc",
8 | "start": "node dist/app.js"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "@types/node": "^20.10.3",
15 | "typescript": "^5.3.2"
16 | },
17 | "dependencies": {
18 | "@envio-dev/hypersync-client": "../.."
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/all-erc20/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/all-erc20/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, Decoder, BlockField, LogField, TransactionField } from "@envio-dev/hypersync-client";
2 | import fs from "node:fs";
3 |
4 | async function main() {
5 | // Create hypersync client using the mainnet hypersync endpoint
6 | // Passing null config makes it use default
7 | const client = HypersyncClient.new(null);
8 |
9 | // The query to run
10 | const query = {
11 | // Start from block 0 and go to the end of the chain (we don't specify a toBlock).
12 | // you can add a "toBlock" to limit the query to a certain range.
13 | "fromBlock": 0,
14 | // The logs we want. We will also automatically get transactions and blocks relating to these logs (the query implicitly joins them).
15 | "logs": [
16 | {
17 | // We want All ERC20 transfers so no address filter and only a filter for the first topic
18 | "topics": [
19 | ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
20 | ]
21 | }
22 | ],
23 | // Select the fields we are interested in, notice topics are selected as topic0,1,2,3
24 | // Most of the fields below are there for demonstration purposes.
25 | // The only field we use in this example is the 'log.data' + 'log.address' + 'log.topic0' so you could create a faster query by removing others.
26 | "fieldSelection": {
27 | "block": [
28 | BlockField.Number,
29 | BlockField.Timestamp,
30 | BlockField.Hash,
31 | ],
32 | "log": [
33 | LogField.BlockNumber,
34 | LogField.LogIndex,
35 | LogField.TransactionIndex,
36 | LogField.TransactionHash,
37 | LogField.Data,
38 | LogField.Address,
39 | LogField.Topic0,
40 | LogField.Topic1,
41 | LogField.Topic2,
42 | LogField.Topic3,
43 | ],
44 | "transaction": [
45 | TransactionField.BlockNumber,
46 | TransactionField.TransactionIndex,
47 | TransactionField.Hash,
48 | TransactionField.From,
49 | TransactionField.To,
50 | TransactionField.Value,
51 | TransactionField.Input,
52 | ]
53 | },
54 | };
55 |
56 | console.log("Running the query...");
57 |
58 | // Run the query once, the query is automatically paginated so it will return when it reaches some limit (time, response size etc.)
59 | // there is a nextBlock field on the response object so we can set the fromBlock of our query to this value and continue our query until
60 | // res.nextBlock is equal to res.archiveHeight or query.toBlock in case we specified an end block.
61 | const res = await client.get(query);
62 |
63 | console.log(`Ran the query once. Next block to query is ${res.nextBlock}`);
64 |
65 | // Create a decoder with our mapping
66 | const decoder = Decoder.fromSignatures([
67 | "Transfer(address indexed from, address indexed to, uint amount)"
68 | ]);
69 |
70 | // Decode the log on a background thread so we don't block the event loop.
71 | // Can also use decoder.decodeLogsSync rather than using this promise api if it is more convenient.
72 | const decodedLogs = await decoder.decodeLogs(res.data.logs);
73 |
74 | // Let's count total volume, it is meaningless because of currency differences but good as an example.
75 | let total_volume = BigInt(0);
76 |
77 | for (const log of decodedLogs) {
78 | // skip invalid logs
79 | if (log === null) {
80 | continue;
81 | }
82 | // We know it is a bigint because of the signature
83 | total_volume += log.body[0].val as bigint;
84 | }
85 |
86 | const totalBlocks = res.nextBlock - query.fromBlock;
87 |
88 | console.log(`Total volume was ${total_volume} in ${totalBlocks} blocks in ${res.data.logs.length} transfers.`);
89 | }
90 |
91 | main();
92 |
--------------------------------------------------------------------------------
/examples/all-erc20/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/call_watch/README.md:
--------------------------------------------------------------------------------
1 | # Watch example
2 |
3 | Example of using hypersync-client to watch for new events of a contract.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/call_watch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "watch-example",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/call_watch/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.16.1
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.5.4
19 |
20 | packages:
21 |
22 | /@types/node@20.16.1:
23 | resolution: {integrity: sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==}
24 | dependencies:
25 | undici-types: 6.19.8
26 | dev: true
27 |
28 | /typescript@5.5.4:
29 | resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@6.19.8:
35 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/call_watch/src/app.ts:
--------------------------------------------------------------------------------
1 | import {HypersyncClient, Decoder, LogField} from "@envio-dev/hypersync-client";
2 | import fs from "node:fs";
3 | import {CallDecoder, TransactionField} from "../../../index";
4 |
5 | const DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
6 |
7 | async function main() {
8 | // Create hypersync client using the mainnet hypersync endpoint
9 | const client = HypersyncClient.new({
10 | url: "https://eth.hypersync.xyz"
11 | });
12 |
13 | // The query to run
14 | const query = {
15 | // start from tip of the chain
16 | "fromBlock": 20500000,
17 | "transactions": [
18 | {
19 | "from": [DAI_ADDRESS]
20 | },
21 | {
22 | "to": [DAI_ADDRESS]
23 | }
24 | ],
25 | // Select the fields we are interested in, notice topics are selected as topic0,1,2,3
26 | "fieldSelection": {
27 | "transaction": [
28 | TransactionField.Hash,
29 | TransactionField.Input,
30 | ]
31 | },
32 | };
33 |
34 | const decoder = CallDecoder.fromSignatures([
35 | "transfer(address dst, uint256 wad)",
36 | ]);
37 |
38 |
39 | while (true) {
40 | const res = await client.get(query);
41 | if (res.data.transactions.length !== 0) {
42 | // Decode the log on a background thread so we don't block the event loop.
43 | // Can also use decoder.decodeLogsSync if it is more convenient.
44 | const decodedInputs = await decoder.decodeTransactionsInput(res.data.transactions);
45 | for (const input of decodedInputs) {
46 | if (input === null) {
47 | continue;
48 | }
49 | console.log(`Transaction decoded. Addr ${input[0].val}, Wad ${input[1].val}`);
50 | }
51 | } else {
52 | console.log(`no tx`);
53 | }
54 | let height = res.archiveHeight;
55 | while (height < res.nextBlock) {
56 | // wait if we are at the head
57 | console.log(`waiting for chain to advance. Height is ${height}`);
58 | height = await client.getHeight();
59 | await new Promise(resolve => setTimeout(resolve, 1000));
60 | }
61 |
62 | // Continue query from nextBlock
63 | query.fromBlock = res.nextBlock;
64 | }
65 | }
66 |
67 | main();
68 |
--------------------------------------------------------------------------------
/examples/call_watch/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/parquet-out/README.md:
--------------------------------------------------------------------------------
1 | # Parquet output example
2 |
3 | Example of using hypersync-client to get bulk data into parquet files.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/parquet-out/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parquet-out",
3 | "version": "0.1.4",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/parquet-out/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/parquet-out/src/app.ts:
--------------------------------------------------------------------------------
1 | import { DataType, HexOutput, HypersyncClient, LogField } from "@envio-dev/hypersync-client";
2 |
3 | async function main() {
4 | // Create hypersync client using the mainnet hypersync endpoint
5 | const client = HypersyncClient.new({
6 | url: "https://eth.hypersync.xyz",
7 | });
8 |
9 | // The query to run
10 | const query = {
11 | "fromBlock": 18500123,
12 | "toBlock": 18501123,
13 | "logs": [{
14 | "address": ["0xdAC17F958D2ee523a2206206994597C13D831ec7"],
15 | "topics": [["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]],
16 | }],
17 | // Select the fields we are interested in, notice topics are selected as topic0,1,2,3
18 | "fieldSelection": {
19 | "log": [
20 | LogField.BlockNumber,
21 | LogField.LogIndex,
22 | LogField.TransactionIndex,
23 | LogField.TransactionHash,
24 | LogField.Data,
25 | LogField.Address,
26 | LogField.Topic0,
27 | LogField.Topic1,
28 | LogField.Topic2,
29 | LogField.Topic3,
30 | ],
31 | },
32 | };
33 |
34 | console.log("Downloading data into parquet... This might take some time depending on connection speed");
35 |
36 | await client.collectParquet("data", query, {
37 | /// Convert binary columns to prefixed hex format like '0x1ab..'
38 | hexOutput: HexOutput.Prefixed,
39 | columnMapping: {
40 | decodedLog: {
41 | "value": DataType.Float64,
42 | },
43 | },
44 | eventSignature: "Transfer(address indexed from, address indexed to, uint256 value)",
45 | });
46 |
47 | console.log("finished writing parquet");
48 | }
49 |
50 | main();
51 |
--------------------------------------------------------------------------------
/examples/parquet-out/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/reverse_wallet/README.md:
--------------------------------------------------------------------------------
1 | # Reverse wallet example
2 |
3 | Example of using hypersync-client to get all transactions data for specific of an address in reverse order.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/reverse_wallet/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reverse_wallet",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/reverse_wallet/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/reverse_wallet/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, Decoder, TransactionField } from "@envio-dev/hypersync-client";
2 |
3 | async function main() {
4 | // Create hypersync client using the mainnet hypersync endpoint
5 | const client = HypersyncClient.new({
6 | url: "https://eth.hypersync.xyz"
7 | });
8 |
9 | // The query to run
10 | const query = {
11 | "fromBlock": 0,
12 | "transactions": [
13 | // get all transactions coming from and going to our address.
14 | {
15 | from: ["0x5a830d7a5149b2f1a2e72d15cd51b84379ee81e5"]
16 | },
17 | {
18 | to: ["0x5a830d7a5149b2f1a2e72d15cd51b84379ee81e5"]
19 | }
20 | ],
21 | "fieldSelection": {
22 | "transaction": [
23 | TransactionField.BlockNumber,
24 | TransactionField.Hash,
25 | TransactionField.From,
26 | TransactionField.To,
27 | TransactionField.Value,
28 | ]
29 | }
30 | };
31 |
32 | // Stream data in reverse order
33 | //
34 | // This will parallelize internal requests so we don't have to worry about pipelining/parallelizing make request -> handle response -> handle data loop
35 | const receiver = await client.stream(query, { reverse: true });
36 |
37 | while (true) {
38 | let res = await receiver.recv();
39 | if (res === null) {
40 | break;
41 | }
42 | for (const tx of res.data.transactions) {
43 | console.log(tx);
44 | }
45 | }
46 | }
47 |
48 | main();
49 |
--------------------------------------------------------------------------------
/examples/reverse_wallet/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transaction-hashes/README.md:
--------------------------------------------------------------------------------
1 | # Wallet example
2 |
3 | Example of using hypersync-client to get all blocks and transaction hashes (not whole transaction objects) within a block range.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transaction-hashes/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wallet",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transaction-hashes/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transaction-hashes/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, presetQueryBlocksAndTransactionHashes } from "@envio-dev/hypersync-client";
2 |
3 | async function main() {
4 | // Create hypersync client using the mainnet hypersync endpoint
5 | const client = HypersyncClient.new({
6 | url: "https://eth.hypersync.xyz"
7 | });
8 |
9 | // query is inclusive of from_block, exclusive of to_block so this will return 49 blocks
10 | let query = presetQueryBlocksAndTransactionHashes(17_000_000, 17_000_050);
11 |
12 | console.log("Running the query...");
13 |
14 | // Run the query once, the query is automatically paginated so it will return when it reaches some limit (time, response size etc.)
15 | // there is a nextBlock field on the response object so we can set the fromBlock of our query to this value and continue our query until
16 | // res.nextBlock is equal to res.archiveHeight or query.toBlock in case we specified an end block.
17 | const res = await client.get(query);
18 |
19 | console.log(`Query returned ${res.data.blocks.length} blocks and ${res.data.transactions.length} transaction hashes`)
20 | }
21 |
22 | main();
23 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transaction-hashes/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transactions/README.md:
--------------------------------------------------------------------------------
1 | # Wallet example
2 |
3 | Example of using hypersync-client to get all blocks and transactions within a block range.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transactions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wallet",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transactions/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transactions/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, presetQueryBlocksAndTransactions } from "@envio-dev/hypersync-client";
2 |
3 | async function main() {
4 | // Create hypersync client using the mainnet hypersync endpoint
5 | const client = HypersyncClient.new({
6 | url: "https://eth.hypersync.xyz"
7 | });
8 |
9 | // query is inclusive of from_block, exclusive of to_block so this will return 49 blocks
10 | let query = presetQueryBlocksAndTransactions(17_000_000, 17_000_050);
11 |
12 | console.log("Running the query...");
13 |
14 | // Run the query once, the query is automatically paginated so it will return when it reaches some limit (time, response size etc.)
15 | // there is a nextBlock field on the response object so we can set the fromBlock of our query to this value and continue our query until
16 | // res.nextBlock is equal to res.archiveHeight or query.toBlock in case we specified an end block.
17 | const res = await client.get(query);
18 |
19 | console.log(`Query returned ${res.data.blocks.length} blocks and ${res.data.transactions.length} transactions`)
20 | }
21 |
22 | main();
23 |
--------------------------------------------------------------------------------
/examples/simple-blocks-and-transactions/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/simple-logs-of-event/README.md:
--------------------------------------------------------------------------------
1 | # Wallet example
2 |
3 | Example of using hypersync-client to get all logs from a contract's event in a block range.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/simple-logs-of-event/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wallet",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/simple-logs-of-event/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/simple-logs-of-event/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, presetQueryLogsOfEvent } from "@envio-dev/hypersync-client";
2 |
3 | async function main() {
4 | // Create hypersync client using the mainnet hypersync endpoint
5 | const client = HypersyncClient.new({
6 | url: "https://eth.hypersync.xyz"
7 | });
8 |
9 | // address to get logs from
10 | const usdt_contract = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
11 |
12 | // topic0 of transaction event signature (hash of event signature)
13 | // query will return logs of this event
14 | const event_topic_0 = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
15 |
16 | // query is inclusive of from_block, exclusive of to_block so this will return 49 blocks
17 | let query = presetQueryLogsOfEvent(usdt_contract, event_topic_0, 17_000_000, 17_000_050);
18 |
19 | console.log("Running the query...");
20 |
21 | // Run the query once, the query is automatically paginated so it will return when it reaches some limit (time, response size etc.)
22 | // there is a nextBlock field on the response object so we can set the fromBlock of our query to this value and continue our query until
23 | // res.nextBlock is equal to res.archiveHeight or query.toBlock in case we specified an end block.
24 | const res = await client.get(query);
25 |
26 | console.log(`Query returned ${res.data.logs.length} logs of transfer events from contract ${usdt_contract}`)
27 |
28 | }
29 |
30 | main();
31 |
--------------------------------------------------------------------------------
/examples/simple-logs-of-event/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/simple-logs/README.md:
--------------------------------------------------------------------------------
1 | # Wallet example
2 |
3 | Example of using hypersync-client to get all logs from a contract in a block range.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/simple-logs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wallet",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/simple-logs/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/simple-logs/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, presetQueryLogs } from "@envio-dev/hypersync-client";
2 |
3 | async function main() {
4 | // Create hypersync client using the mainnet hypersync endpoint
5 | const client = HypersyncClient.new({
6 | url: "https://eth.hypersync.xyz"
7 | });
8 |
9 | // address to get logs from
10 | const usdt_contract = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
11 |
12 | // query is inclusive of from_block, exclusive of to_block so this will return 49 blocks
13 | let query = presetQueryLogs(usdt_contract, 17_000_000, 17_000_050);
14 |
15 | console.log("Running the query...");
16 |
17 | // Run the query once, the query is automatically paginated so it will return when it reaches some limit (time, response size etc.)
18 | // there is a nextBlock field on the response object so we can set the fromBlock of our query to this value and continue our query until
19 | // res.nextBlock is equal to res.archiveHeight or query.toBlock in case we specified an end block.
20 | const res = await client.get(query);
21 |
22 | console.log(`Query returned ${res.data.logs.length} logs from contract ${usdt_contract}`)
23 | }
24 |
25 | main();
26 |
--------------------------------------------------------------------------------
/examples/simple-logs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/wallet/README.md:
--------------------------------------------------------------------------------
1 | # Wallet example
2 |
3 | Example of using hypersync-client to get all transfer (Ether and erc20) data for specific set of addresses.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/wallet/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wallet",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/wallet/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/wallet/src/app.ts:
--------------------------------------------------------------------------------
1 | import { HypersyncClient, Decoder, BlockField, LogField, TransactionField } from "@envio-dev/hypersync-client";
2 | import fs from "node:fs";
3 |
4 | // The addresses we want to get data for
5 | const addresses = [
6 | "0xD1a923D70510814EaE7695A76326201cA06d080F".toLowerCase(),
7 | "0xc0A101c4E9Bb4463BD2F5d6833c2276C36914Fb6".toLowerCase(),
8 | "0xa0FBaEdC4C110f5A0c5E96c3eeAC9B5635b74CE7".toLowerCase(),
9 | "0x32448eb389aBe39b20d5782f04a8d71a2b2e7189".toLowerCase(),
10 | ];
11 |
12 | // Convert address to topic for filtering. Padds the address with zeroes.
13 | function addressToTopic(address: string): string {
14 | return "0x000000000000000000000000" + address.slice(2, address.length);
15 | }
16 |
17 | async function main() {
18 | // Create hypersync client using the mainnet hypersync endpoint
19 | const client = HypersyncClient.new({
20 | url: "https://eth.hypersync.xyz"
21 | });
22 |
23 | const addressTopicFilter = addresses.map(addressToTopic);
24 |
25 | // The query to run
26 | const query = {
27 | // start from block 0 and go to the end of the chain (we don't specify a toBlock).
28 | "fromBlock": 0,
29 | // The logs we want. We will also automatically get transactions and blocks relating to these logs (the query implicitly joins them).
30 | "logs": [
31 | {
32 | // We want All ERC20 transfers coming to any of our addresses
33 | "topics": [
34 | ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
35 | [],
36 | addressTopicFilter,
37 | [],
38 | ]
39 | },
40 | {
41 | // We want All ERC20 transfers going from any of our addresses
42 | "topics": [
43 | ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
44 | addressTopicFilter,
45 | [],
46 | [],
47 | ]
48 | }
49 | ],
50 | "transactions": [
51 | // get all transactions coming from and going to any of our addresses.
52 | {
53 | from: addresses
54 | },
55 | {
56 | to: addresses
57 | }
58 | ],
59 | // Select the fields we are interested in, notice topics are selected as topic0,1,2,3
60 | "fieldSelection": {
61 | "block": [
62 | BlockField.Number,
63 | BlockField.Timestamp,
64 | BlockField.Hash,
65 | ],
66 | "log": [
67 | LogField.BlockNumber,
68 | LogField.LogIndex,
69 | LogField.TransactionIndex,
70 | LogField.TransactionHash,
71 | LogField.Data,
72 | LogField.Address,
73 | LogField.Topic0,
74 | LogField.Topic1,
75 | LogField.Topic2,
76 | LogField.Topic3,
77 | ],
78 | "transaction": [
79 | TransactionField.BlockNumber,
80 | TransactionField.TransactionIndex,
81 | TransactionField.Hash,
82 | TransactionField.From,
83 | TransactionField.To,
84 | TransactionField.Value,
85 | TransactionField.Input,
86 | ]
87 | },
88 | };
89 |
90 | console.log("Running the query...");
91 |
92 | // Run the query once, the query is automatically paginated so it will return when it reaches some limit (time, response size etc.)
93 | // there is a nextBlock field on the response object so we can set the fromBlock of our query to this value and continue our query until
94 | // res.nextBlock is equal to res.archiveHeight or query.toBlock in case we specified an end block.
95 | const res = await client.get(query);
96 |
97 | console.log(`Ran the query once. Next block to query is ${res.nextBlock}`);
98 |
99 | const decoder = Decoder.fromSignatures([
100 | "Transfer(address indexed from, address indexed to, uint amount)"
101 | ]);
102 |
103 | // Decode the log on a background thread so we don't block the event loop.
104 | // Can also use decoder.decodeLogsSync if it is more convenient.
105 | const decodedLogs = await decoder.decodeLogs(res.data.logs);
106 |
107 | // Let's count total volume for each address, it is meaningless because of currency differences but good as an example.
108 | let total_erc20_volume = {};
109 |
110 | for (const log of decodedLogs) {
111 | // skip invalid logs
112 | if (log === null) {
113 | continue;
114 | }
115 |
116 | if (!total_erc20_volume[log.indexed[0].val as string]) {
117 | total_erc20_volume[log.indexed[0].val as string] = BigInt(0);
118 | }
119 | if (!total_erc20_volume[log.indexed[1].val as string]) {
120 | total_erc20_volume[log.indexed[1].val as string] = BigInt(0);
121 | }
122 | // We count for both sides but we will filter by our addresses later so we will ignore unnecessary addresses.
123 | total_erc20_volume[log.indexed[0].val as string] += log.body[0].val as bigint;
124 | total_erc20_volume[log.indexed[1].val as string] += log.body[0].val as bigint;
125 | }
126 |
127 | for (const addr of addresses) {
128 | console.log(`Total erc20 transfer volume for address ${addr} is ${total_erc20_volume[addr]}`);
129 | }
130 |
131 | let total_wei_volume = {};
132 |
133 | for (const tx of res.data.transactions) {
134 | if (!total_wei_volume[tx.from]) {
135 | total_wei_volume[tx.from] = BigInt(0);
136 | }
137 | if (!total_wei_volume[tx.to]) {
138 | total_wei_volume[tx.to] = BigInt(0);
139 | }
140 |
141 | total_wei_volume[tx.from] += BigInt(tx.value);
142 | total_wei_volume[tx.to] += BigInt(tx.value);
143 | }
144 |
145 | for (const addr of addresses) {
146 | console.log(`Total wei transfer wolume for address ${addr} is ${total_wei_volume[addr]}`);
147 | }
148 | }
149 |
150 | main();
151 |
--------------------------------------------------------------------------------
/examples/wallet/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/examples/watch/README.md:
--------------------------------------------------------------------------------
1 | # Watch example
2 |
3 | Example of using hypersync-client to watch for new events of a contract.
4 |
5 | Can run `npx tsc && node dist/app.js` to run it.
6 |
--------------------------------------------------------------------------------
/examples/watch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "watch-example",
3 | "version": "0.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/node": "^20.10.3",
14 | "typescript": "^5.3.2"
15 | },
16 | "dependencies": {
17 | "@envio-dev/hypersync-client": "../.."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/watch/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@envio-dev/hypersync-client':
9 | specifier: ../..
10 | version: link:../..
11 |
12 | devDependencies:
13 | '@types/node':
14 | specifier: ^20.10.3
15 | version: 20.10.4
16 | typescript:
17 | specifier: ^5.3.2
18 | version: 5.3.3
19 |
20 | packages:
21 |
22 | /@types/node@20.10.4:
23 | resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==}
24 | dependencies:
25 | undici-types: 5.26.5
26 | dev: true
27 |
28 | /typescript@5.3.3:
29 | resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
30 | engines: {node: '>=14.17'}
31 | hasBin: true
32 | dev: true
33 |
34 | /undici-types@5.26.5:
35 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
36 | dev: true
37 |
--------------------------------------------------------------------------------
/examples/watch/src/app.ts:
--------------------------------------------------------------------------------
1 | import {HypersyncClient, Decoder, LogField} from "@envio-dev/hypersync-client";
2 | import fs from "node:fs";
3 |
4 | const DAI_ADDRESS = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
5 |
6 | async function main() {
7 | // Create hypersync client using the mainnet hypersync endpoint
8 | const client = HypersyncClient.new({
9 | url: "https://eth.hypersync.xyz"
10 | });
11 |
12 | const height = await client.getHeight();
13 |
14 | // The query to run
15 | const query = {
16 | // start from tip of the chain
17 | "fromBlock": height,
18 | "logs": [
19 | {
20 | "address": [DAI_ADDRESS],
21 | // We want the transfers
22 | "topics": [
23 | ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
24 | [],
25 | [],
26 | [],
27 | ]
28 | }
29 | ],
30 | // Select the fields we are interested in, notice topics are selected as topic0,1,2,3
31 | "fieldSelection": {
32 | "log": [
33 | LogField.Data,
34 | LogField.Address,
35 | LogField.Topic0,
36 | LogField.Topic1,
37 | LogField.Topic2,
38 | LogField.Topic3,
39 | ]
40 | },
41 | };
42 |
43 | const decoder = Decoder.fromSignatures([
44 | "Transfer(address indexed from, address indexed to, uint amount)"
45 | ]);
46 |
47 | let total_dai_volume = BigInt(0);
48 |
49 | while(true) {
50 | const res = await client.get(query);
51 |
52 | if(res.data.logs.length !== 0) {
53 | // Decode the log on a background thread so we don't block the event loop.
54 | // Can also use decoder.decodeLogsSync if it is more convenient.
55 | const decodedLogs = await decoder.decodeLogs(res.data.logs);
56 |
57 | for (const log of decodedLogs) {
58 | if (log === null) {
59 | continue;
60 | }
61 | total_dai_volume += log.body[0].val as bigint;
62 | }
63 | }
64 |
65 | console.log(`scanned up to ${res.nextBlock} and total DAI transfer volume is ${total_dai_volume / BigInt(1e18)} USD`);
66 |
67 | let height = res.archiveHeight;
68 | while (height < res.nextBlock) {
69 | // wait if we are at the head
70 | console.log(`waiting for chain to advance. Height is ${height}`);
71 | height = await client.getHeight();
72 | await new Promise(resolve => setTimeout(resolve, 1000));
73 | }
74 |
75 | // Continue query from nextBlock
76 | query.fromBlock = res.nextBlock;
77 | }
78 | }
79 |
80 | main();
81 |
--------------------------------------------------------------------------------
/examples/watch/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "esModuleInterop": true,
5 | "target": "es2020",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "outDir": "dist"
9 | },
10 | "lib": ["es2015"]
11 | }
12 |
--------------------------------------------------------------------------------
/npm/darwin-arm64/README.md:
--------------------------------------------------------------------------------
1 | # `@envio-dev/hypersync-client-darwin-arm64`
2 |
3 | This is the **aarch64-apple-darwin** binary for `@envio-dev/hypersync-client`
4 |
--------------------------------------------------------------------------------
/npm/darwin-arm64/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client-darwin-arm64",
3 | "version": "0.6.5",
4 | "os": [
5 | "darwin"
6 | ],
7 | "cpu": [
8 | "arm64"
9 | ],
10 | "main": "hypersync-client.darwin-arm64.node",
11 | "files": [
12 | "hypersync-client.darwin-arm64.node"
13 | ],
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">= 10"
17 | }
18 | }
--------------------------------------------------------------------------------
/npm/darwin-x64/README.md:
--------------------------------------------------------------------------------
1 | # `@envio-dev/hypersync-client-darwin-x64`
2 |
3 | This is the **x86_64-apple-darwin** binary for `@envio-dev/hypersync-client`
4 |
--------------------------------------------------------------------------------
/npm/darwin-x64/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client-darwin-x64",
3 | "version": "0.6.5",
4 | "os": [
5 | "darwin"
6 | ],
7 | "cpu": [
8 | "x64"
9 | ],
10 | "main": "hypersync-client.darwin-x64.node",
11 | "files": [
12 | "hypersync-client.darwin-x64.node"
13 | ],
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">= 10"
17 | }
18 | }
--------------------------------------------------------------------------------
/npm/linux-arm64-gnu/README.md:
--------------------------------------------------------------------------------
1 | # `@envio-dev/hypersync-client-linux-arm64-gnu`
2 |
3 | This is the **aarch64-unknown-linux-gnu** binary for `@envio-dev/hypersync-client`
4 |
--------------------------------------------------------------------------------
/npm/linux-arm64-gnu/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client-linux-arm64-gnu",
3 | "version": "0.6.5",
4 | "os": [
5 | "linux"
6 | ],
7 | "cpu": [
8 | "arm64"
9 | ],
10 | "main": "hypersync-client.linux-arm64-gnu.node",
11 | "files": [
12 | "hypersync-client.linux-arm64-gnu.node"
13 | ],
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">= 10"
17 | },
18 | "libc": [
19 | "glibc"
20 | ]
21 | }
--------------------------------------------------------------------------------
/npm/linux-x64-gnu/README.md:
--------------------------------------------------------------------------------
1 | # `@envio-dev/hypersync-client-linux-x64-gnu`
2 |
3 | This is the **x86_64-unknown-linux-gnu** binary for `@envio-dev/hypersync-client`
4 |
--------------------------------------------------------------------------------
/npm/linux-x64-gnu/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client-linux-x64-gnu",
3 | "version": "0.6.5",
4 | "os": [
5 | "linux"
6 | ],
7 | "cpu": [
8 | "x64"
9 | ],
10 | "main": "hypersync-client.linux-x64-gnu.node",
11 | "files": [
12 | "hypersync-client.linux-x64-gnu.node"
13 | ],
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">= 10"
17 | },
18 | "libc": [
19 | "glibc"
20 | ]
21 | }
--------------------------------------------------------------------------------
/npm/linux-x64-musl/README.md:
--------------------------------------------------------------------------------
1 | # `@envio-dev/hypersync-client-linux-x64-musl`
2 |
3 | This is the **x86_64-unknown-linux-musl** binary for `@envio-dev/hypersync-client`
4 |
--------------------------------------------------------------------------------
/npm/linux-x64-musl/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client-linux-x64-musl",
3 | "version": "0.6.5",
4 | "os": [
5 | "linux"
6 | ],
7 | "cpu": [
8 | "x64"
9 | ],
10 | "main": "hypersync-client.linux-x64-musl.node",
11 | "files": [
12 | "hypersync-client.linux-x64-musl.node"
13 | ],
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">= 10"
17 | },
18 | "libc": [
19 | "musl"
20 | ]
21 | }
--------------------------------------------------------------------------------
/npm/win32-x64-msvc/README.md:
--------------------------------------------------------------------------------
1 | # `@envio-dev/hypersync-client-win32-x64-msvc`
2 |
3 | This is the **x86_64-pc-windows-msvc** binary for `@envio-dev/hypersync-client`
4 |
--------------------------------------------------------------------------------
/npm/win32-x64-msvc/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client-win32-x64-msvc",
3 | "version": "0.6.5",
4 | "os": [
5 | "win32"
6 | ],
7 | "cpu": [
8 | "x64"
9 | ],
10 | "main": "hypersync-client.win32-x64-msvc.node",
11 | "files": [
12 | "hypersync-client.win32-x64-msvc.node"
13 | ],
14 | "license": "MIT",
15 | "engines": {
16 | "node": ">= 10"
17 | }
18 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@envio-dev/hypersync-client",
3 | "description": "HyperSync Client by Envio",
4 | "version": "0.6.6",
5 | "main": "index.js",
6 | "types": "index.d.ts",
7 | "napi": {
8 | "name": "hypersync-client",
9 | "triples": {
10 | "additional": [
11 | "aarch64-apple-darwin",
12 | "aarch64-unknown-linux-gnu",
13 | "x86_64-unknown-linux-musl"
14 | ]
15 | }
16 | },
17 | "license": "MIT",
18 | "devDependencies": {
19 | "@napi-rs/cli": "^2.16.3",
20 | "ava": "^5.1.1",
21 | "typedoc": "^0.25.4",
22 | "typedoc-plugin-markdown": "^3.17.1",
23 | "typescript": "^5.3.2"
24 | },
25 | "ava": {
26 | "timeout": "3m"
27 | },
28 | "engines": {
29 | "node": ">= 10"
30 | },
31 | "scripts": {
32 | "artifacts": "napi artifacts",
33 | "build": "napi build --platform --release --no-const-enum",
34 | "build:debug": "napi build --platform --no-const-enum",
35 | "prepublishOnly": "napi prepublish -t npm",
36 | "test": "ava",
37 | "universal": "napi universal",
38 | "version": "napi version",
39 | "docs": "yarn build && npx typedoc index.d.ts",
40 | "docs:md": "yarn build && npx typedoc --plugin typedoc-plugin-markdown index.d.ts"
41 | },
42 | "packageManager": "yarn@3.8.1"
43 | }
44 |
--------------------------------------------------------------------------------
/src/config.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use anyhow::{Context, Result};
4 | use serde::Serialize;
5 |
6 | #[napi(object)]
7 | #[derive(Default, Clone, Serialize)]
8 | pub struct StreamConfig {
9 | #[serde(skip_serializing_if = "Option::is_none")]
10 | pub column_mapping: Option,
11 | #[serde(skip_serializing_if = "Option::is_none")]
12 | pub event_signature: Option,
13 | #[serde(skip_serializing_if = "Option::is_none")]
14 | pub hex_output: Option,
15 | #[serde(skip_serializing_if = "Option::is_none")]
16 | pub batch_size: Option,
17 | #[serde(skip_serializing_if = "Option::is_none")]
18 | pub max_batch_size: Option,
19 | #[serde(skip_serializing_if = "Option::is_none")]
20 | pub min_batch_size: Option,
21 | #[serde(skip_serializing_if = "Option::is_none")]
22 | pub concurrency: Option,
23 | #[serde(skip_serializing_if = "Option::is_none")]
24 | pub max_num_blocks: Option,
25 | #[serde(skip_serializing_if = "Option::is_none")]
26 | pub max_num_transactions: Option,
27 | #[serde(skip_serializing_if = "Option::is_none")]
28 | pub max_num_logs: Option,
29 | #[serde(skip_serializing_if = "Option::is_none")]
30 | pub max_num_traces: Option,
31 | #[serde(skip_serializing_if = "Option::is_none")]
32 | pub response_bytes_ceiling: Option,
33 | #[serde(skip_serializing_if = "Option::is_none")]
34 | pub response_bytes_floor: Option,
35 | #[serde(skip_serializing_if = "Option::is_none")]
36 | pub reverse: Option,
37 | }
38 |
39 | #[napi(string_enum)]
40 | #[derive(Debug, Serialize)]
41 | pub enum HexOutput {
42 | NoEncode,
43 | Prefixed,
44 | NonPrefixed,
45 | }
46 |
47 | #[napi(string_enum)]
48 | #[derive(Debug, Serialize)]
49 | #[serde(rename_all = "lowercase")]
50 | pub enum DataType {
51 | Float64,
52 | Float32,
53 | UInt64,
54 | UInt32,
55 | Int64,
56 | Int32,
57 | }
58 |
59 | impl Default for HexOutput {
60 | fn default() -> Self {
61 | Self::NoEncode
62 | }
63 | }
64 |
65 | #[napi(object)]
66 | #[derive(Default, Clone, Serialize)]
67 | pub struct ColumnMapping {
68 | #[serde(skip_serializing_if = "Option::is_none")]
69 | pub block: Option>,
70 | #[serde(skip_serializing_if = "Option::is_none")]
71 | pub transaction: Option>,
72 | #[serde(skip_serializing_if = "Option::is_none")]
73 | pub log: Option>,
74 | #[serde(skip_serializing_if = "Option::is_none")]
75 | pub trace: Option>,
76 | #[serde(skip_serializing_if = "Option::is_none")]
77 | pub decoded_log: Option>,
78 | }
79 |
80 | impl StreamConfig {
81 | pub fn try_convert(&self) -> Result {
82 | let json = serde_json::to_vec(self).context("serialize to json")?;
83 | serde_json::from_slice(&json).context("parse json")
84 | }
85 | }
86 |
87 | #[napi(object)]
88 | #[derive(Default, Clone, Serialize)]
89 | pub struct ClientConfig {
90 | #[serde(skip_serializing_if = "Option::is_none")]
91 | pub url: Option,
92 | #[serde(skip_serializing_if = "Option::is_none")]
93 | pub bearer_token: Option,
94 | #[serde(skip_serializing_if = "Option::is_none")]
95 | pub http_req_timeout_millis: Option,
96 | #[serde(skip_serializing_if = "Option::is_none")]
97 | pub max_num_retries: Option,
98 | #[serde(skip_serializing_if = "Option::is_none")]
99 | pub retry_backoff_ms: Option,
100 | #[serde(skip_serializing_if = "Option::is_none")]
101 | pub retry_base_ms: Option,
102 | #[serde(skip_serializing_if = "Option::is_none")]
103 | pub retry_ceiling_ms: Option,
104 | #[serde(skip)]
105 | pub enable_checksum_addresses: Option,
106 | }
107 |
108 | impl ClientConfig {
109 | pub fn try_convert(&self) -> Result {
110 | let json = serde_json::to_vec(self).context("serialize to json")?;
111 | serde_json::from_slice(&json).context("parse json")
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/decode.rs:
--------------------------------------------------------------------------------
1 | use std::sync::Arc;
2 |
3 | use anyhow::{Context, Result};
4 | use hypersync_client::format::{Data, Hex, LogArgument};
5 |
6 | use crate::{
7 | map_err,
8 | types::{DecodedEvent, DecodedSolValue, Event, Log},
9 | };
10 |
11 | #[napi]
12 | #[derive(Clone)]
13 | pub struct Decoder {
14 | inner: Arc,
15 | checksummed_addresses: bool,
16 | }
17 |
18 | #[napi]
19 | impl Decoder {
20 | #[napi]
21 | pub fn from_signatures(signatures: Vec) -> napi::Result {
22 | let inner = hypersync_client::Decoder::from_signatures(&signatures)
23 | .context("create inner decoder")
24 | .map_err(map_err)?;
25 | Ok(Self {
26 | inner: Arc::new(inner),
27 | checksummed_addresses: false,
28 | })
29 | }
30 |
31 | #[napi]
32 | pub fn from_signatures_with_checksum(
33 | signatures: Vec,
34 | checksum: bool,
35 | ) -> napi::Result {
36 | let inner = hypersync_client::Decoder::from_signatures(&signatures)
37 | .context("create inner decoder")
38 | .map_err(map_err)?;
39 | Ok(Self {
40 | inner: Arc::new(inner),
41 | checksummed_addresses: checksum,
42 | })
43 | }
44 |
45 | #[napi]
46 | pub fn enable_checksummed_addresses(&mut self) {
47 | self.checksummed_addresses = true;
48 | }
49 |
50 | #[napi]
51 | pub fn disable_checksummed_addresses(&mut self) {
52 | self.checksummed_addresses = false;
53 | }
54 |
55 | #[napi]
56 | pub async fn decode_logs(&self, logs: Vec) -> Vec> {
57 | let decoder = self.clone();
58 | tokio::task::spawn_blocking(move || decoder.decode_logs_sync(logs))
59 | .await
60 | .unwrap()
61 | }
62 |
63 | #[napi]
64 | pub fn decode_logs_sync(&self, logs: Vec) -> Vec> {
65 | logs.iter()
66 | .map(|log| self.decode_impl(log).ok().flatten())
67 | .collect::>()
68 | }
69 |
70 | #[napi]
71 | pub async fn decode_events(&self, events: Vec) -> Vec> {
72 | let decoder = self.clone();
73 | tokio::task::spawn_blocking(move || decoder.decode_events_sync(events))
74 | .await
75 | .unwrap()
76 | }
77 |
78 | #[napi]
79 | pub fn decode_events_sync(&self, events: Vec) -> Vec> {
80 | events
81 | .iter()
82 | .map(|event| self.decode_impl(&event.log).ok().flatten())
83 | .collect::>()
84 | }
85 |
86 | fn decode_impl(&self, log: &Log) -> Result> {
87 | let topics = log
88 | .topics
89 | .iter()
90 | .map(|v| {
91 | v.as_ref()
92 | .map(|v| LogArgument::decode_hex(v).context("decode topic"))
93 | .transpose()
94 | })
95 | .collect::>>()
96 | .context("decode topics")?;
97 |
98 | let topic0 = topics
99 | .first()
100 | .context("get topic0")?
101 | .as_ref()
102 | .context("topic0 is null")?;
103 |
104 | let data = log.data.as_ref().context("get log.data")?;
105 | let data = Data::decode_hex(data).context("decode data")?;
106 |
107 | let decoded = match self
108 | .inner
109 | .decode(topic0.as_slice(), &topics, &data)
110 | .context("decode log")?
111 | {
112 | Some(v) => v,
113 | None => return Ok(None),
114 | };
115 |
116 | Ok(Some(DecodedEvent {
117 | indexed: decoded
118 | .indexed
119 | .into_iter()
120 | .map(|v| DecodedSolValue::new(v, self.checksummed_addresses))
121 | .collect(),
122 | body: decoded
123 | .body
124 | .into_iter()
125 | .map(|v| DecodedSolValue::new(v, self.checksummed_addresses))
126 | .collect(),
127 | }))
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/decode_call.rs:
--------------------------------------------------------------------------------
1 | use crate::map_err;
2 | use crate::types::{DecodedSolValue, Trace, Transaction};
3 | use anyhow::Context;
4 | use hypersync_client::format::{Data, Hex};
5 | use std::sync::Arc;
6 |
7 | #[napi]
8 | #[derive(Clone)]
9 | pub struct CallDecoder {
10 | inner: Arc,
11 | checksummed_addresses: bool,
12 | }
13 |
14 | #[napi]
15 | impl CallDecoder {
16 | #[napi]
17 | pub fn from_signatures(signatures: Vec) -> napi::Result {
18 | let inner = hypersync_client::CallDecoder::from_signatures(&signatures)
19 | .context("build inner decoder")
20 | .map_err(map_err)?;
21 |
22 | Ok(Self {
23 | inner: Arc::new(inner),
24 | checksummed_addresses: false,
25 | })
26 | }
27 |
28 | #[napi]
29 | pub fn from_signatures_with_checksum(
30 | signatures: Vec,
31 | checksum: bool,
32 | ) -> napi::Result {
33 | let inner = hypersync_client::CallDecoder::from_signatures(&signatures)
34 | .context("build inner decoder")
35 | .map_err(map_err)?;
36 |
37 | Ok(Self {
38 | inner: Arc::new(inner),
39 | checksummed_addresses: checksum,
40 | })
41 | }
42 |
43 | pub fn enable_checksummed_addresses(&mut self) {
44 | self.checksummed_addresses = true;
45 | }
46 |
47 | pub fn disable_checksummed_addresses(&mut self) {
48 | self.checksummed_addresses = false;
49 | }
50 |
51 | #[napi]
52 | pub async fn decode_inputs(&self, inputs: Vec) -> Vec>> {
53 | let decoder = self.clone();
54 |
55 | tokio::task::spawn_blocking(move || decoder.decode_inputs_sync(inputs))
56 | .await
57 | .unwrap()
58 | }
59 |
60 | #[napi]
61 |
62 | pub async fn decode_transactions_input(
63 | &self,
64 | txs: Vec,
65 | ) -> Vec>> {
66 | let decoder = self.clone();
67 |
68 | tokio::task::spawn_blocking(move || decoder.decode_transactions_input_sync(txs))
69 | .await
70 | .unwrap()
71 | }
72 |
73 | #[napi]
74 | pub async fn decode_traces_input(
75 | &self,
76 | traces: Vec,
77 | ) -> Vec>> {
78 | let decoder = self.clone();
79 |
80 | tokio::task::spawn_blocking(move || decoder.decode_traces_input_sync(traces))
81 | .await
82 | .unwrap()
83 | }
84 |
85 | #[napi]
86 | pub fn decode_inputs_sync(&self, inputs: Vec) -> Vec>> {
87 | inputs
88 | .into_iter()
89 | .map(|input| self.decode_impl(input))
90 | .collect()
91 | }
92 |
93 | #[napi]
94 | pub fn decode_transactions_input_sync(
95 | &self,
96 | txs: Vec,
97 | ) -> Vec>> {
98 | txs.into_iter()
99 | .map(|tx| self.decode_impl(tx.input?))
100 | .collect()
101 | }
102 |
103 | #[napi]
104 | pub fn decode_traces_input_sync(
105 | &self,
106 | traces: Vec,
107 | ) -> Vec>> {
108 | traces
109 | .into_iter()
110 | .map(|trace| self.decode_impl(trace.input?))
111 | .collect()
112 | }
113 |
114 | #[napi]
115 | pub fn decode_impl(&self, input: String) -> Option> {
116 | let input = Data::decode_hex(input.as_str())
117 | .context("decode input")
118 | .unwrap();
119 | let decoded_input = self
120 | .inner
121 | .decode_input(&input)
122 | .context("decode log")
123 | .unwrap();
124 | decoded_input.map(|decoded_input| {
125 | decoded_input
126 | .into_iter()
127 | .map(|value| DecodedSolValue::new(value, self.checksummed_addresses))
128 | .collect()
129 | })
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/preset_query.rs:
--------------------------------------------------------------------------------
1 | use anyhow::Context;
2 | use hypersync_client::{
3 | format::{Address, Hex, LogArgument},
4 | preset_query,
5 | };
6 |
7 | use crate::{map_err, query::Query};
8 |
9 | /// Returns a query for all Blocks and Transactions within the block range (from_block, to_block]
10 | /// If to_block is None then query runs to the head of the chain.
11 | #[napi]
12 | pub fn preset_query_blocks_and_transactions(
13 | from_block: i64,
14 | to_block: Option,
15 | ) -> napi::Result {
16 | let from_block = from_block
17 | .try_into()
18 | .context("convert from_block")
19 | .map_err(map_err)?;
20 | let to_block = to_block
21 | .map(|t| t.try_into().context("convert to_block"))
22 | .transpose()
23 | .map_err(map_err)?;
24 |
25 | let query: Query = preset_query::blocks_and_transactions(from_block, to_block)
26 | .try_into()
27 | .map_err(map_err)?;
28 |
29 | Ok(query)
30 | }
31 |
32 | /// Returns a query object for all Blocks and hashes of the Transactions within the block range
33 | /// (from_block, to_block]. Also returns the block_hash and block_number fields on each Transaction
34 | /// so it can be mapped to a block. If to_block is None then query runs to the head of the chain.
35 | #[napi]
36 | pub fn preset_query_blocks_and_transaction_hashes(
37 | from_block: i64,
38 | to_block: Option,
39 | ) -> napi::Result {
40 | let from_block = from_block
41 | .try_into()
42 | .context("convert from_block")
43 | .map_err(map_err)?;
44 | let to_block = to_block
45 | .map(|t| t.try_into().context("convert to_block"))
46 | .transpose()
47 | .map_err(map_err)?;
48 |
49 | let query: Query = preset_query::blocks_and_transaction_hashes(from_block, to_block)
50 | .try_into()
51 | .map_err(map_err)?;
52 |
53 | Ok(query)
54 | }
55 |
56 | /// Returns a query object for all Logs within the block range from the given address.
57 | /// If to_block is None then query runs to the head of the chain.
58 | #[napi]
59 | pub fn preset_query_logs(
60 | contract_address: String,
61 | from_block: i64,
62 | to_block: Option,
63 | ) -> napi::Result {
64 | let address = Address::decode_hex(&contract_address)
65 | .context("parse address")
66 | .map_err(map_err)?;
67 |
68 | let from_block = from_block
69 | .try_into()
70 | .context("convert from_block")
71 | .map_err(map_err)?;
72 | let to_block = to_block
73 | .map(|t| t.try_into().context("convert to_block"))
74 | .transpose()
75 | .map_err(map_err)?;
76 |
77 | preset_query::logs(from_block, to_block, address)
78 | .try_into()
79 | .map_err(map_err)
80 | }
81 |
82 | /// Returns a query for all Logs within the block range from the given address with a
83 | /// matching topic0 event signature. Topic0 is the keccak256 hash of the event signature.
84 | /// If to_block is None then query runs to the head of the chain.
85 | #[napi]
86 | pub fn preset_query_logs_of_event(
87 | contract_address: String,
88 | topic0: String,
89 | from_block: i64,
90 | to_block: Option,
91 | ) -> napi::Result {
92 | let address = Address::decode_hex(&contract_address)
93 | .context("parse address")
94 | .map_err(map_err)?;
95 | let topic0 = LogArgument::decode_hex(&topic0)
96 | .context("parse topic0")
97 | .map_err(map_err)?;
98 |
99 | let from_block = from_block
100 | .try_into()
101 | .context("convert from_block")
102 | .map_err(map_err)?;
103 | let to_block = to_block
104 | .map(|t| t.try_into().context("convert to_block"))
105 | .transpose()
106 | .map_err(map_err)?;
107 |
108 | let query = preset_query::logs_of_event(from_block, to_block, topic0, address)
109 | .try_into()
110 | .map_err(map_err)?;
111 | Ok(query)
112 | }
113 |
--------------------------------------------------------------------------------
Returns a query object for all Blocks and hashes of the Transactions within the block range 2 | (from_block, to_block]. Also returns the block_hash and block_number fields on each Transaction 3 | so it can be mapped to a block. If to_block is None then query runs to the head of the chain.
4 |