@chainfoundry/chaincodec 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -0
- package/chaincodec.darwin-arm64.node +0 -0
- package/chaincodec.darwin-x64.node +0 -0
- package/chaincodec.linux-arm64-gnu.node +0 -0
- package/chaincodec.linux-x64-gnu.node +0 -0
- package/chaincodec.linux-x64-musl.node +0 -0
- package/chaincodec.win32-x64-msvc.node +0 -0
- package/package.json +14 -3
package/README.md
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# @chainfoundry/chaincodec
|
|
2
|
+
|
|
3
|
+
Universal blockchain ABI decoder for Node.js — production-grade EVM event & function call decoding.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@chainfoundry/chaincodec)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
Native Node.js bindings (via [napi-rs](https://napi.rs)) for the [chaincodec](https://crates.io/crates/chaincodec-evm) Rust library. Decode `eth_getLogs` entries, function calldata, and compute topic0 fingerprints — all at Rust speed with a TypeScript-first API.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @chainfoundry/chaincodec
|
|
16
|
+
# or
|
|
17
|
+
yarn add @chainfoundry/chaincodec
|
|
18
|
+
# or
|
|
19
|
+
pnpm add @chainfoundry/chaincodec
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
No build step required — pre-built native binaries are bundled for all major platforms.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Platform support
|
|
27
|
+
|
|
28
|
+
| Platform | Architecture | Supported |
|
|
29
|
+
|----------|-------------|-----------|
|
|
30
|
+
| Linux (glibc) | x64 | ✅ |
|
|
31
|
+
| Linux (glibc) | arm64 | ✅ |
|
|
32
|
+
| Linux (musl / Alpine) | x64 | ✅ |
|
|
33
|
+
| macOS | x64 (Intel) | ✅ |
|
|
34
|
+
| macOS | arm64 (Apple Silicon) | ✅ |
|
|
35
|
+
| Windows | x64 | ✅ |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { EvmDecoder, MemoryRegistry } from '@chainfoundry/chaincodec';
|
|
43
|
+
|
|
44
|
+
// 1. Load schemas
|
|
45
|
+
const registry = new MemoryRegistry();
|
|
46
|
+
registry.loadDirectory('./node_modules/@chainfoundry/chaincodec/schemas');
|
|
47
|
+
|
|
48
|
+
// 2. Decode a raw log from eth_getLogs
|
|
49
|
+
const decoder = new EvmDecoder();
|
|
50
|
+
|
|
51
|
+
const rawLog = {
|
|
52
|
+
chain: 'ethereum',
|
|
53
|
+
txHash: '0xabc123...',
|
|
54
|
+
blockNumber: 19500000n,
|
|
55
|
+
blockTimestamp: 1710000000n,
|
|
56
|
+
logIndex: 0,
|
|
57
|
+
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
|
|
58
|
+
topics: [
|
|
59
|
+
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // Transfer
|
|
60
|
+
'0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045', // from
|
|
61
|
+
'0x000000000000000000000000ab5801a7d398351b8be11c439e05c5b3259aec9b', // to
|
|
62
|
+
],
|
|
63
|
+
data: '0x00000000000000000000000000000000000000000000000000000000000f4240',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const fp = decoder.fingerprint(rawLog);
|
|
67
|
+
const schema = registry.getByFingerprint(fp);
|
|
68
|
+
|
|
69
|
+
if (schema) {
|
|
70
|
+
const event = decoder.decodeEvent(rawLog, schema);
|
|
71
|
+
console.log(event.schemaName); // "ERC20Transfer"
|
|
72
|
+
console.log(event.fields.from); // "0xd8da6bf2..."
|
|
73
|
+
console.log(event.fields.to); // "0xab5801a7..."
|
|
74
|
+
console.log(event.fields.value); // "1000000" (1 USDC)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Decode function calldata
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { EvmCallDecoder } from '@chainfoundry/chaincodec';
|
|
84
|
+
import { readFileSync } from 'fs';
|
|
85
|
+
|
|
86
|
+
// Load ABI JSON (from Etherscan, Hardhat artifacts, Foundry out/, etc.)
|
|
87
|
+
const abiJson = readFileSync('./abi/uniswap_v3_router.json', 'utf-8');
|
|
88
|
+
const decoder = EvmCallDecoder.fromAbiJson(abiJson);
|
|
89
|
+
|
|
90
|
+
// Decode raw calldata from a transaction's `input` field
|
|
91
|
+
const calldata = '0x414bf389...';
|
|
92
|
+
const call = decoder.decodeCall(calldata);
|
|
93
|
+
|
|
94
|
+
console.log(call.functionName); // "exactInputSingle"
|
|
95
|
+
for (const [name, value] of Object.entries(call.inputs)) {
|
|
96
|
+
console.log(` ${name}: ${value}`);
|
|
97
|
+
}
|
|
98
|
+
// tokenIn: 0xC02aaA39b... (WETH)
|
|
99
|
+
// tokenOut: 0xA0b8699... (USDC)
|
|
100
|
+
// amountIn: 1000000000000000000
|
|
101
|
+
// amountOutMin: 1800000000
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Batch decode
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { BatchEngine, BatchRequest, ErrorMode } from '@chainfoundry/chaincodec';
|
|
110
|
+
|
|
111
|
+
const engine = new BatchEngine(registry);
|
|
112
|
+
engine.addDecoder('ethereum', new EvmDecoder());
|
|
113
|
+
|
|
114
|
+
const logs = await fetchLogsFromRpc(fromBlock, toBlock); // RawLog[]
|
|
115
|
+
|
|
116
|
+
const result = engine.decode({
|
|
117
|
+
chain: 'ethereum',
|
|
118
|
+
logs,
|
|
119
|
+
chunkSize: 10_000,
|
|
120
|
+
errorMode: ErrorMode.Collect,
|
|
121
|
+
onProgress: (decoded, total) => {
|
|
122
|
+
process.stdout.write(`\r${decoded}/${total}`);
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
console.log(`decoded: ${result.events.length}`);
|
|
127
|
+
console.log(`errors: ${result.errors.length}`);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Compute topic0 fingerprint
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { computeFingerprint } from '@chainfoundry/chaincodec';
|
|
136
|
+
|
|
137
|
+
const fp = computeFingerprint('Transfer(address,address,uint256)');
|
|
138
|
+
// "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
|
|
139
|
+
|
|
140
|
+
const fp2 = computeFingerprint('Swap(address,uint256,uint256,uint256,uint256,address)');
|
|
141
|
+
// Uniswap V2 Swap topic0
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## API reference
|
|
147
|
+
|
|
148
|
+
### `EvmDecoder`
|
|
149
|
+
|
|
150
|
+
| Method | Description |
|
|
151
|
+
|--------|-------------|
|
|
152
|
+
| `fingerprint(log)` | Compute topic0 fingerprint from a raw log |
|
|
153
|
+
| `decodeEvent(log, schema)` | Decode an EVM log into named fields |
|
|
154
|
+
|
|
155
|
+
### `EvmCallDecoder`
|
|
156
|
+
|
|
157
|
+
| Method | Description |
|
|
158
|
+
|--------|-------------|
|
|
159
|
+
| `EvmCallDecoder.fromAbiJson(json)` | Create decoder from ABI JSON string |
|
|
160
|
+
| `decodeCall(calldata, blockNumber?)` | Decode function calldata |
|
|
161
|
+
| `encodeCall(functionName, args)` | ABI-encode a function call |
|
|
162
|
+
|
|
163
|
+
### `MemoryRegistry`
|
|
164
|
+
|
|
165
|
+
| Method | Description |
|
|
166
|
+
|--------|-------------|
|
|
167
|
+
| `loadFile(path)` | Load a CSDL schema file |
|
|
168
|
+
| `loadDirectory(path)` | Load all `.csdl` files in a directory |
|
|
169
|
+
| `getByFingerprint(fp)` | Look up schema by topic0 hash |
|
|
170
|
+
| `getByName(name)` | Look up schema by name |
|
|
171
|
+
| `allSchemas()` | Return all registered schemas |
|
|
172
|
+
|
|
173
|
+
### `BatchEngine`
|
|
174
|
+
|
|
175
|
+
| Method | Description |
|
|
176
|
+
|--------|-------------|
|
|
177
|
+
| `addDecoder(chainSlug, decoder)` | Register a decoder for a chain |
|
|
178
|
+
| `decode(request)` | Batch decode a list of raw logs |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## TypeScript types
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface RawLog {
|
|
186
|
+
chain: string;
|
|
187
|
+
txHash: string;
|
|
188
|
+
blockNumber: bigint;
|
|
189
|
+
blockTimestamp: bigint;
|
|
190
|
+
logIndex: number;
|
|
191
|
+
address: string;
|
|
192
|
+
topics: string[];
|
|
193
|
+
data: string;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface DecodedEvent {
|
|
197
|
+
schemaName: string;
|
|
198
|
+
chain: string;
|
|
199
|
+
blockNumber: bigint;
|
|
200
|
+
txHash: string;
|
|
201
|
+
logIndex: number;
|
|
202
|
+
fields: Record<string, string>; // NormalizedValue as string
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
interface DecodedCall {
|
|
206
|
+
functionName: string;
|
|
207
|
+
inputs: Record<string, string>;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Using CommonJS
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
const { EvmDecoder, MemoryRegistry } = require('@chainfoundry/chaincodec');
|
|
217
|
+
|
|
218
|
+
const registry = new MemoryRegistry();
|
|
219
|
+
registry.loadDirectory('./schemas');
|
|
220
|
+
|
|
221
|
+
const decoder = new EvmDecoder();
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Bundled schemas
|
|
227
|
+
|
|
228
|
+
The package ships with 50+ CSDL schemas covering ERC-20/721/1155, Uniswap, Aave, Compound, ChainLink, and more. Schemas are in the `schemas/` subdirectory of the installed package.
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { join } from 'path';
|
|
232
|
+
import { createRequire } from 'module';
|
|
233
|
+
|
|
234
|
+
const require = createRequire(import.meta.url);
|
|
235
|
+
const schemasDir = join(
|
|
236
|
+
require.resolve('@chainfoundry/chaincodec/package.json'),
|
|
237
|
+
'../schemas'
|
|
238
|
+
);
|
|
239
|
+
registry.loadDirectory(schemasDir);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
MIT — see [LICENSE](https://github.com/DarshanKumar89/chainkit/blob/main/LICENSE)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainfoundry/chaincodec",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Universal blockchain ABI decoder — production-grade event & call decoding for Ethereum and EVM chains",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ethereum",
|
|
@@ -12,7 +12,17 @@
|
|
|
12
12
|
"chaincodec",
|
|
13
13
|
"arbitrum",
|
|
14
14
|
"base",
|
|
15
|
-
"polygon"
|
|
15
|
+
"polygon",
|
|
16
|
+
"optimism",
|
|
17
|
+
"solidity",
|
|
18
|
+
"defi",
|
|
19
|
+
"uniswap",
|
|
20
|
+
"napi",
|
|
21
|
+
"rust-napi",
|
|
22
|
+
"native-addon",
|
|
23
|
+
"eth-logs",
|
|
24
|
+
"event-decoder",
|
|
25
|
+
"call-decoder"
|
|
16
26
|
],
|
|
17
27
|
"license": "MIT",
|
|
18
28
|
"repository": {
|
|
@@ -36,7 +46,8 @@
|
|
|
36
46
|
"files": [
|
|
37
47
|
"index.d.ts",
|
|
38
48
|
"index.js",
|
|
39
|
-
"chaincodec.*.node"
|
|
49
|
+
"chaincodec.*.node",
|
|
50
|
+
"README.md"
|
|
40
51
|
],
|
|
41
52
|
"scripts": {
|
|
42
53
|
"build": "napi build --platform --release",
|