@wonjm/tx-decoder-rc 0.12.0-rc.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 +569 -0
- package/dist/index.cjs +6420 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2476 -0
- package/dist/index.d.ts +2476 -0
- package/dist/index.js +6386 -0
- package/dist/index.js.map +1 -0
- package/package.json +92 -0
package/README.md
ADDED
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
# Transaction Decoder
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40initia%2Ftx-decoder)
|
|
4
|
+
[](https://bundlephobia.com/package/@initia/tx-decoder)
|
|
5
|
+
[](https://www.npmjs.com/package/@initia/tx-decoder)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://github.com/initia-labs/tx-decoder/actions)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
A TypeScript library for decoding Cosmos SDK transactions, providing human-readable message decoding and balance change tracking.
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Features](#-features)
|
|
15
|
+
- [Installation](#-installation)
|
|
16
|
+
- [Quick Start](#-quick-start)
|
|
17
|
+
- [API Reference](#-api-reference)
|
|
18
|
+
- [Supported Message Types](#-supported-message-types)
|
|
19
|
+
- [Development](#-development)
|
|
20
|
+
- [License](#-license)
|
|
21
|
+
|
|
22
|
+
## ✨ [Features](#-features)
|
|
23
|
+
|
|
24
|
+
- **Human-Readable Output**: Decodes Cosmos SDK transaction messages into a clear, human-readable JSON format.
|
|
25
|
+
- **Multi-VM Support**: Full support for Move VM, EVM, and WASM virtual machines with VM-specific balance tracking.
|
|
26
|
+
- **Balance Tracking**: Tracks fungible token deltas and correlates Move objects or EVM NFTs with specific tokenId tracking based on the originating VM.
|
|
27
|
+
- **Type-Safe**: Built with TypeScript and validated with Zod for robust, type-safe operations.
|
|
28
|
+
- **Extensible**: Features a flexible handler system that can be easily extended to support new message types.
|
|
29
|
+
- **Immutable State**: Uses Immer for safe and predictable state management.
|
|
30
|
+
- **ABI-driven EVM Support**: Uses `viem` to decode EVM event logs (ERC-20 and ERC-721 `Transfer` events) without relying on Cosmos `coin_spent` events.
|
|
31
|
+
|
|
32
|
+
## 📦 [Installation](#-installation)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# npm
|
|
36
|
+
npm install @initia/tx-decoder
|
|
37
|
+
|
|
38
|
+
# yarn
|
|
39
|
+
yarn add @initia/tx-decoder
|
|
40
|
+
|
|
41
|
+
# pnpm
|
|
42
|
+
pnpm add @initia/tx-decoder
|
|
43
|
+
|
|
44
|
+
# bun
|
|
45
|
+
bun add @initia/tx-decoder
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 🚀 [Quick Start](#-quick-start)
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { TxDecoder } from "@initia/tx-decoder";
|
|
52
|
+
|
|
53
|
+
const decoder = new TxDecoder({
|
|
54
|
+
registryUrl: "https://registry.initia.xyz/",
|
|
55
|
+
restUrl: "https://rest.initia.xyz"
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Decode a Cosmos transaction for L1 and Move L2
|
|
59
|
+
const decodedTx = await decoder.decodeCosmosTransaction(txResponse);
|
|
60
|
+
console.log(decodedTx);
|
|
61
|
+
|
|
62
|
+
// Decode a Cosmos transaction for EVM L2
|
|
63
|
+
const decodedEvmTx = await decoder.decodeCosmosEvmTransaction(txResponse);
|
|
64
|
+
console.log(decodedEvmTx);
|
|
65
|
+
|
|
66
|
+
// Decode a Cosmos transaction for WASM L2
|
|
67
|
+
const decodedWasmTx = await decoder.decodeCosmosWasmTransaction(txResponse);
|
|
68
|
+
console.log(decodedWasmTx);
|
|
69
|
+
|
|
70
|
+
// Decode a native Ethereum RPC transaction
|
|
71
|
+
const ethereumTx = await decoder.decodeEthereumTransaction({
|
|
72
|
+
tx: ethereumTransaction,
|
|
73
|
+
txReceipt: ethereumTransactionReceipt
|
|
74
|
+
});
|
|
75
|
+
console.log(ethereumTx);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Each decoded message includes a `balanceChanges` object tagged with `vm: "move"`, `vm: "evm"`, or `vm: "wasm"`. EVM balance deltas are sourced from decoded log events via `viem` rather than Cosmos bank events.
|
|
79
|
+
|
|
80
|
+
## 📖 [API Reference](#-api-reference)
|
|
81
|
+
|
|
82
|
+
### `TxDecoder`
|
|
83
|
+
|
|
84
|
+
The main class for decoding transactions.
|
|
85
|
+
|
|
86
|
+
#### Constructor
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
new TxDecoder(config: DecoderConfig)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Parameters:**
|
|
93
|
+
|
|
94
|
+
- `config: DecoderConfig` - Configuration object with the following properties:
|
|
95
|
+
- `registryUrl: string` - Registry URL to retrieve chain registries
|
|
96
|
+
- `restUrl: string` - REST endpoint of the Initia chain to query on-chain data
|
|
97
|
+
- `jsonRpcUrl?: string` - JSON-RPC endpoint for EVM L2 chains
|
|
98
|
+
- `timeoutMs?: number` - HTTP request timeout in milliseconds (default: 10000)
|
|
99
|
+
|
|
100
|
+
#### Methods
|
|
101
|
+
|
|
102
|
+
##### `decodeCosmosTransaction(txResponse: TxResponse): Promise<DecodedTx>`
|
|
103
|
+
|
|
104
|
+
Decodes a Cosmos transaction response for L1 and Move L2 chains into a human-readable format.
|
|
105
|
+
|
|
106
|
+
**Parameters:**
|
|
107
|
+
|
|
108
|
+
- `txResponse: TxResponse` - The raw transaction response from the blockchain
|
|
109
|
+
|
|
110
|
+
**Returns:** `Promise<DecodedTx>` - A promise that resolves to a decoded transaction object
|
|
111
|
+
|
|
112
|
+
##### `decodeCosmosEvmTransaction(txResponse: TxResponse): Promise<DecodedTx>`
|
|
113
|
+
|
|
114
|
+
Decodes a Cosmos transaction response for EVM L2 chains, processing only general message types (excludes `/initia.move` and `/opinit` prefixes).
|
|
115
|
+
|
|
116
|
+
**Note:** Requires providing `jsonRpcUrl` in `TxDecoder` config to resolve EVM denominations.
|
|
117
|
+
|
|
118
|
+
**Parameters:**
|
|
119
|
+
|
|
120
|
+
- `txResponse: TxResponse` - The raw transaction response from the blockchain
|
|
121
|
+
|
|
122
|
+
**Returns:** `Promise<DecodedTx>` - A promise that resolves to a decoded transaction object
|
|
123
|
+
|
|
124
|
+
##### `decodeCosmosWasmTransaction(txResponse: TxResponse): Promise<DecodedTx>`
|
|
125
|
+
|
|
126
|
+
Decodes a Cosmos transaction response for WASM L2 chains. Balance changes are tracked from `transfer` events in transaction logs.
|
|
127
|
+
|
|
128
|
+
**Parameters:**
|
|
129
|
+
|
|
130
|
+
- `txResponse: TxResponse` - The raw transaction response from the blockchain
|
|
131
|
+
|
|
132
|
+
**Returns:** `Promise<DecodedTx>` - A promise that resolves to a decoded transaction object
|
|
133
|
+
|
|
134
|
+
##### `decodeEthereumTransaction(payload: EthereumRpcPayload): Promise<DecodedEthereumTx>`
|
|
135
|
+
|
|
136
|
+
Decodes a native Ethereum RPC transaction with balance change tracking from transaction receipt logs.
|
|
137
|
+
|
|
138
|
+
**Parameters:**
|
|
139
|
+
|
|
140
|
+
- `payload: EthereumRpcPayload` - Object containing:
|
|
141
|
+
- `tx: EthereumTransaction` - The Ethereum transaction object from `eth_getTransactionByHash`
|
|
142
|
+
- `txReceipt: EthereumTransactionReceipt` - The transaction receipt from `eth_getTransactionReceipt`
|
|
143
|
+
|
|
144
|
+
**Returns:** `Promise<DecodedEthereumTx>` - A promise that resolves to a decoded Ethereum transaction object
|
|
145
|
+
|
|
146
|
+
### Type Definitions
|
|
147
|
+
|
|
148
|
+
#### `DecodedTx` (Cosmos Transactions)
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
interface DecodedTx {
|
|
152
|
+
messages: ProcessedMessage[];
|
|
153
|
+
metadata: Metadata;
|
|
154
|
+
totalBalanceChanges: BalanceChanges;
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### `DecodedEthereumTx` (Ethereum RPC Transactions)
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
interface DecodedEthereumTx {
|
|
162
|
+
decodedTransaction: DecodedEthereumCall;
|
|
163
|
+
metadata: Metadata;
|
|
164
|
+
totalBalanceChanges: EvmBalanceChanges;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### `DecodedEthereumCall`
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
type DecodedEthereumCall =
|
|
172
|
+
| DecodedErc20ApproveCall
|
|
173
|
+
| DecodedErc20TransferCall
|
|
174
|
+
| DecodedErc20TransferFromCall
|
|
175
|
+
| DecodedErc721ApproveCall
|
|
176
|
+
| DecodedErc721SafeTransferFromCall
|
|
177
|
+
| DecodedNotSupportedCall;
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### `ProcessedMessage`
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
interface ProcessedMessage {
|
|
184
|
+
balanceChanges: BalanceChanges;
|
|
185
|
+
decodedMessage: DecodedMessage;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### `BalanceChanges`
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
interface BaseBalanceChanges {
|
|
193
|
+
ft: { [address: string]: FtChange };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface MoveBalanceChanges extends BaseBalanceChanges {
|
|
197
|
+
vm: "move";
|
|
198
|
+
object: { [address: string]: ObjectChange };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
interface EvmBalanceChanges extends BaseBalanceChanges {
|
|
202
|
+
vm: "evm";
|
|
203
|
+
nft: { [address: string]: NftChange };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
interface WasmBalanceChanges extends BaseBalanceChanges {
|
|
207
|
+
vm: "wasm";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
type BalanceChanges =
|
|
211
|
+
| MoveBalanceChanges
|
|
212
|
+
| EvmBalanceChanges
|
|
213
|
+
| WasmBalanceChanges;
|
|
214
|
+
|
|
215
|
+
// Type aliases
|
|
216
|
+
type FtChange = { [denom: string]: string };
|
|
217
|
+
type NftChange = { [contract: string]: { [tokenId: string]: string } };
|
|
218
|
+
type ObjectChange = { [address: string]: string };
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Note on NFT Balance Changes:**
|
|
222
|
+
|
|
223
|
+
- NFT balance changes are tracked with 3-level nesting: `address → contract → tokenId → value`
|
|
224
|
+
- Each NFT transfer shows `"1"` for receiving and `"-1"` for sending
|
|
225
|
+
- This structure allows tracking specific NFT tokens rather than just contract-level changes
|
|
226
|
+
- Example: `nft["0x123..."]["0xNFTContract"]["42"] = "1"` means address `0x123...` received NFT token #42 from contract `0xNFTContract`
|
|
227
|
+
|
|
228
|
+
#### `DecodedMessage`
|
|
229
|
+
|
|
230
|
+
Please see [here](src/interfaces/decoded-messages.ts)
|
|
231
|
+
|
|
232
|
+
### Response Structure
|
|
233
|
+
|
|
234
|
+
The decoder returns a structured object with the following format:
|
|
235
|
+
|
|
236
|
+
#### Move VM Example (Bank Send)
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
{
|
|
240
|
+
messages: [
|
|
241
|
+
{
|
|
242
|
+
balanceChanges: {
|
|
243
|
+
vm: "move",
|
|
244
|
+
ft: {
|
|
245
|
+
"init1...": { "uinit": "-1000000" },
|
|
246
|
+
"init1...": { "uinit": "1000000" }
|
|
247
|
+
},
|
|
248
|
+
object: {}
|
|
249
|
+
},
|
|
250
|
+
decodedMessage: {
|
|
251
|
+
action: "send",
|
|
252
|
+
data: {
|
|
253
|
+
from: "init1...",
|
|
254
|
+
to: "init1...",
|
|
255
|
+
coins: [
|
|
256
|
+
{
|
|
257
|
+
amount: "1000000",
|
|
258
|
+
denom: "uinit"
|
|
259
|
+
},
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
isIbc: false,
|
|
263
|
+
isOp: false
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
],
|
|
267
|
+
metadata: {},
|
|
268
|
+
totalBalanceChanges: {
|
|
269
|
+
vm: "move",
|
|
270
|
+
ft: {
|
|
271
|
+
"init1...": { "uinit": "-1000000" },
|
|
272
|
+
"init1...": { "uinit": "1000000" }
|
|
273
|
+
},
|
|
274
|
+
object: {}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### EVM Example (NFT Transfer)
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
{
|
|
283
|
+
messages: [
|
|
284
|
+
{
|
|
285
|
+
balanceChanges: {
|
|
286
|
+
vm: "evm",
|
|
287
|
+
ft: {
|
|
288
|
+
"0x19f8a98c...": { "evm/E1Ff7038eAAAF027031688E1535a055B2Bac2546": "-24400000000001" },
|
|
289
|
+
"0xf1829676...": { "evm/E1Ff7038eAAAF027031688E1535a055B2Bac2546": "737822500000" }
|
|
290
|
+
},
|
|
291
|
+
nft: {
|
|
292
|
+
"0x19f8a98c...": {
|
|
293
|
+
"0x5d4376b62fa8AC16dFabe6a9861E11c33A48C677": {
|
|
294
|
+
"4561": "-1"
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"0x8f433715...": {
|
|
298
|
+
"0x5d4376b62fa8AC16dFabe6a9861E11c33A48C677": {
|
|
299
|
+
"4561": "1"
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
decodedMessage: {
|
|
305
|
+
action: "not_supported",
|
|
306
|
+
data: {
|
|
307
|
+
msgType: "/minievm.evm.v1.MsgCall"
|
|
308
|
+
},
|
|
309
|
+
isIbc: false,
|
|
310
|
+
isOp: false
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
],
|
|
314
|
+
metadata: {},
|
|
315
|
+
totalBalanceChanges: {
|
|
316
|
+
vm: "evm",
|
|
317
|
+
ft: {
|
|
318
|
+
"0x19f8a98c...": { "evm/E1Ff7038eAAAF027031688E1535a055B2Bac2546": "-24400000000001" },
|
|
319
|
+
"0xf1829676...": { "evm/E1Ff7038eAAAF027031688E1535a055B2Bac2546": "737822500000" }
|
|
320
|
+
},
|
|
321
|
+
nft: {
|
|
322
|
+
"0x19f8a98c...": {
|
|
323
|
+
"0x5d4376b62fa8AC16dFabe6a9861E11c33A48C677": {
|
|
324
|
+
"4561": "-1"
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
"0x8f433715...": {
|
|
328
|
+
"0x5d4376b62fa8AC16dFabe6a9861E11c33A48C677": {
|
|
329
|
+
"4561": "1"
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## 📝 [Supported Message Types](#-supported-message-types)
|
|
338
|
+
|
|
339
|
+
### Cosmos Messages
|
|
340
|
+
|
|
341
|
+
#### Bank Messages
|
|
342
|
+
|
|
343
|
+
- `/cosmos.bank.v1beta1.MsgSend` (supported on Move, EVM, and WASM VMs)
|
|
344
|
+
|
|
345
|
+
#### Distribution Messages
|
|
346
|
+
|
|
347
|
+
- `/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward`
|
|
348
|
+
|
|
349
|
+
#### Staking Messages (Multi-Staking)
|
|
350
|
+
|
|
351
|
+
- `/initia.mstaking.v1.MsgDelegate`
|
|
352
|
+
- `/initia.mstaking.v1.MsgUndelegate`
|
|
353
|
+
- `/initia.mstaking.v1.MsgBeginRedelegate`
|
|
354
|
+
|
|
355
|
+
#### Authz Messages
|
|
356
|
+
|
|
357
|
+
- `/cosmos.authz.v1beta1.MsgExec` - Execute authorized messages on behalf of another account
|
|
358
|
+
- `/cosmos.authz.v1beta1.MsgGrant` - Grant authorization to another account
|
|
359
|
+
- `/cosmos.authz.v1beta1.MsgRevoke` - Revoke a previously granted authorization
|
|
360
|
+
|
|
361
|
+
#### Feegrant Messages
|
|
362
|
+
|
|
363
|
+
- `/cosmos.feegrant.v1beta1.MsgGrantAllowance` - Grant a fee allowance to another account
|
|
364
|
+
- `/cosmos.feegrant.v1beta1.MsgRevokeAllowance` - Revoke an existing fee allowance
|
|
365
|
+
|
|
366
|
+
**Note:** MsgExec recursively decodes the inner messages it contains. All currently supported message types can be wrapped within MsgExec and will be properly decoded.
|
|
367
|
+
|
|
368
|
+
### Move VM Messages
|
|
369
|
+
|
|
370
|
+
- `/initia.move.v1.MsgExecute`
|
|
371
|
+
- `/initia.move.v1.MsgExecuteJSON`
|
|
372
|
+
|
|
373
|
+
#### Supported Move Scripts
|
|
374
|
+
|
|
375
|
+
**DEX & Liquidity:**
|
|
376
|
+
|
|
377
|
+
- `0x1::dex::swap_script` - Token swap
|
|
378
|
+
- `0x1::dex::provide_liquidity_script` - Provide liquidity
|
|
379
|
+
- `0x1::dex::provide_liquidity_and_stake` - Provide liquidity and stake LP tokens
|
|
380
|
+
- `0x1::dex::provide_liquidity_and_stake_lock` - Provide liquidity and stake-lock LP tokens
|
|
381
|
+
- `0x1::dex::withdraw_liquidity_script` - Withdraw liquidity
|
|
382
|
+
- `0x1::dex::extend_lock` - Extend LP lock period
|
|
383
|
+
- `0x1::dex::merge_lock` - Merge locked LP positions
|
|
384
|
+
|
|
385
|
+
**Stableswap:**
|
|
386
|
+
|
|
387
|
+
- `0x1::stableswap::swap_script` - Stableswap token swap
|
|
388
|
+
- `0x1::stableswap::provide` - Provide liquidity to stableswap
|
|
389
|
+
- `0x1::stableswap::withdraw` - Withdraw liquidity from stableswap
|
|
390
|
+
|
|
391
|
+
**Minitswap:**
|
|
392
|
+
|
|
393
|
+
- `0x1::minitswap::provide` - Provide liquidity to minitswap
|
|
394
|
+
- `0x1::minitswap::unbond` - Unbond from minitswap
|
|
395
|
+
- `0x1::minitswap::withdraw_unbond` - Withdraw unbonded tokens
|
|
396
|
+
|
|
397
|
+
**NFT:**
|
|
398
|
+
|
|
399
|
+
- `0x1::simple_nft::mint` - Mint NFT
|
|
400
|
+
- `0x1::simple_nft::burn` - Burn NFT
|
|
401
|
+
|
|
402
|
+
**Object Transfer:**
|
|
403
|
+
|
|
404
|
+
- `0x1::object::transfer_call` - Transfer Move objects
|
|
405
|
+
|
|
406
|
+
**Lock Staking:**
|
|
407
|
+
|
|
408
|
+
- `<module_address>::lock_staking::delegate` - Delegate with lock
|
|
409
|
+
- `<module_address>::lock_staking::undelegate` - Undelegate locked tokens
|
|
410
|
+
- `<module_address>::lock_staking::redelegate` - Redelegate locked tokens
|
|
411
|
+
- `<module_address>::lock_staking::withdraw_delegator_reward` - Withdraw rewards from locked stake
|
|
412
|
+
- `<module_address>::lock_staking::extend` - Extend lock period
|
|
413
|
+
- `<module_address>::lock_staking::batch_extend` - Batch extend lock periods
|
|
414
|
+
|
|
415
|
+
**VIP (Voting Incentive Program):**
|
|
416
|
+
|
|
417
|
+
- `<module_address>::vip::batch_claim_user_reward_script` - Claim VIP rewards
|
|
418
|
+
- `<module_address>::vip::batch_lock_stake_script` - Lock stake for VIP
|
|
419
|
+
- `<module_address>::weight_vote::vote` - Vote on gauge weights
|
|
420
|
+
|
|
421
|
+
### OpInit Messages (L1 ↔ L2 Bridge)
|
|
422
|
+
|
|
423
|
+
- `/opinit.ophost.v1.MsgInitiateTokenDeposit` - Initiate deposit from L1 to L2
|
|
424
|
+
- `/opinit.ophost.v1.MsgFinalizeTokenWithdrawal` - Finalize withdrawal on L1
|
|
425
|
+
- `/opinit.opchild.v1.MsgFinalizeTokenDeposit` - Finalize deposit on L2
|
|
426
|
+
- `/opinit.opchild.v1.MsgInitiateTokenWithdrawal` - Initiate withdrawal from L2 to L1
|
|
427
|
+
|
|
428
|
+
### IBC Messages
|
|
429
|
+
|
|
430
|
+
#### IBC Fungible Token Transfer
|
|
431
|
+
|
|
432
|
+
- `/ibc.applications.transfer.v1.MsgTransfer` - Send fungible tokens via IBC
|
|
433
|
+
- `/ibc.core.channel.v1.MsgRecvPacket` (with `transfer` application) - Receive fungible tokens via IBC
|
|
434
|
+
|
|
435
|
+
#### IBC Non-Fungible Token Transfer
|
|
436
|
+
|
|
437
|
+
- `/ibc.applications.nft_transfer.v1.MsgTransfer` - Send NFTs via IBC (Move & EVM)
|
|
438
|
+
- `/ibc.core.channel.v1.MsgRecvPacket` (with `nft-transfer` application) - Receive NFTs via IBC (Move & EVM)
|
|
439
|
+
|
|
440
|
+
### Ethereum RPC Transactions
|
|
441
|
+
|
|
442
|
+
The library supports decoding native Ethereum RPC transactions (via `decodeEthereumTransaction`):
|
|
443
|
+
|
|
444
|
+
#### ERC-20 Functions
|
|
445
|
+
|
|
446
|
+
- `approve(address spender, uint256 amount)` - Approve ERC-20 spending
|
|
447
|
+
- `transfer(address to, uint256 amount)` - Transfer ERC-20 tokens
|
|
448
|
+
- `transferFrom(address from, address to, uint256 amount)` - Transfer ERC-20 tokens from approved address
|
|
449
|
+
|
|
450
|
+
#### ERC-721 Functions
|
|
451
|
+
|
|
452
|
+
- `approve(address to, uint256 tokenId)` - Approve NFT transfer
|
|
453
|
+
- `safeTransferFrom(address from, address to, uint256 tokenId)` - Safe transfer NFT
|
|
454
|
+
|
|
455
|
+
#### Native ETH Transfer
|
|
456
|
+
|
|
457
|
+
- Native ETH transfer (value transfer without function call)
|
|
458
|
+
|
|
459
|
+
#### Contract Deployment
|
|
460
|
+
|
|
461
|
+
- Contract creation transactions
|
|
462
|
+
|
|
463
|
+
#### Kami721 NFT
|
|
464
|
+
|
|
465
|
+
- `publicMint()` - Public mint function for Kami721 NFTs
|
|
466
|
+
|
|
467
|
+
### WASM Event Processing
|
|
468
|
+
|
|
469
|
+
The library automatically processes WASM event logs for balance tracking:
|
|
470
|
+
|
|
471
|
+
- `transfer` event type with `recipient`, `sender`, and `amount` attributes
|
|
472
|
+
|
|
473
|
+
### EVM Event Processing
|
|
474
|
+
|
|
475
|
+
The library automatically processes EVM event logs for balance tracking:
|
|
476
|
+
|
|
477
|
+
- `Transfer(address indexed from, address indexed to, uint256 value)` (ERC-20)
|
|
478
|
+
- `Transfer(address indexed from, address indexed to, uint256 indexed tokenId)` (ERC-721)
|
|
479
|
+
|
|
480
|
+
## 💻 [Development](#-development)
|
|
481
|
+
|
|
482
|
+
### Prerequisites
|
|
483
|
+
|
|
484
|
+
- Node.js >= 20
|
|
485
|
+
- pnpm
|
|
486
|
+
|
|
487
|
+
```bash
|
|
488
|
+
# Clone the repository
|
|
489
|
+
git clone https://github.com/initia-labs/tx-decoder.git
|
|
490
|
+
cd tx-decoder
|
|
491
|
+
|
|
492
|
+
# Install dependencies
|
|
493
|
+
pnpm install
|
|
494
|
+
|
|
495
|
+
# Run tests
|
|
496
|
+
pnpm test
|
|
497
|
+
|
|
498
|
+
# Build
|
|
499
|
+
pnpm build
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## 📁 Folder Structure
|
|
503
|
+
|
|
504
|
+
```
|
|
505
|
+
tx-decoder/
|
|
506
|
+
├── src/
|
|
507
|
+
│ ├── api/ # API client architecture
|
|
508
|
+
│ │ ├── api.ts # Main API client with service composition
|
|
509
|
+
│ │ └── services/ # Modular API services
|
|
510
|
+
│ │ ├── base.ts # Base service with caching
|
|
511
|
+
│ │ ├── cosmos.ts # Cosmos chain API interactions
|
|
512
|
+
│ │ ├── evm.ts # EVM-specific API calls (contract detection, etc.)
|
|
513
|
+
│ │ └── move.ts # Move VM API interactions
|
|
514
|
+
│ ├── balance-changes.ts # Balance aggregation helpers per VM
|
|
515
|
+
│ ├── constants/ # Application constants
|
|
516
|
+
│ │ ├── index.ts # Main constants export
|
|
517
|
+
│ │ ├── balance-changes.ts # Default balance change structures
|
|
518
|
+
│ │ ├── evm-abis.ts # EVM contract ABIs (ERC20, ERC721, etc.)
|
|
519
|
+
│ │ └── evm-selectors.ts # EVM function selectors and event signatures
|
|
520
|
+
│ ├── decoder.ts # Main transaction decoding logic
|
|
521
|
+
│ ├── decoder-registry.ts # Decoder registry arrays (Cosmos EVM, Cosmos Move, Ethereum)
|
|
522
|
+
│ ├── validation.ts # Transaction validation functions
|
|
523
|
+
│ ├── index.ts # Entry point for exports
|
|
524
|
+
│ ├── message-types.ts # Supported message types
|
|
525
|
+
│ ├── metadata-resolver.ts # Resolves and fetches NFT metadata for token addresses
|
|
526
|
+
│ ├── decoders/ # Message decoders
|
|
527
|
+
│ │ ├── cosmos/ # Cosmos SDK message decoders
|
|
528
|
+
│ │ ├── ethereum/ # Ethereum RPC transaction decoders
|
|
529
|
+
│ │ │ └── erc20/ # ERC-20 transfer and transferFrom decoders
|
|
530
|
+
│ │ ├── ibc/ # IBC message decoders
|
|
531
|
+
│ │ ├── move/ # Move message decoders
|
|
532
|
+
│ │ └── op-init/ # OpInit message decoders
|
|
533
|
+
│ ├── interfaces/ # TypeScript interfaces and discriminated unions
|
|
534
|
+
│ │ ├── balance-changes.ts # Balance change type definitions
|
|
535
|
+
│ │ ├── decoder.ts # Decoder interface definitions
|
|
536
|
+
│ │ ├── ethereum.ts # Ethereum transaction type definitions
|
|
537
|
+
│ │ └── processor.ts # Event processor interfaces
|
|
538
|
+
│ ├── processors/ # Event processors
|
|
539
|
+
│ │ ├── evm/ # ABI-driven EVM event processors
|
|
540
|
+
│ │ │ ├── index.ts # EVM processor registry
|
|
541
|
+
│ │ │ └── transfer.ts # ERC-20/ERC-721 Transfer event processor
|
|
542
|
+
│ │ └── move/ # Move event processors
|
|
543
|
+
│ ├── schema/ # Zod schemas for validation
|
|
544
|
+
│ │ ├── common.ts # Common validation schemas
|
|
545
|
+
│ │ ├── cosmos/ # Cosmos transaction schemas
|
|
546
|
+
│ │ ├── ethereum/ # Ethereum RPC transaction schemas
|
|
547
|
+
│ │ └── evm.ts # EVM log schemas
|
|
548
|
+
│ ├── utils/ # Utility helpers
|
|
549
|
+
│ │ ├── index.ts # Utility exports
|
|
550
|
+
│ │ ├── denom.ts # Denomination handling utilities
|
|
551
|
+
│ │ └── merge-balances.ts # Balance merging logic (supports 3-level NFT nesting)
|
|
552
|
+
│ └── tests/ # Jest unit tests grouped by domain
|
|
553
|
+
│ ├── _shared/ # Shared test utilities and helpers
|
|
554
|
+
│ ├── common/ # Common functionality tests
|
|
555
|
+
│ ├── cosmos/ # Cosmos message decoder tests
|
|
556
|
+
│ ├── ethereum/ # Ethereum RPC transaction tests
|
|
557
|
+
│ │ └── erc20/ # ERC-20 transfer and transferFrom tests
|
|
558
|
+
│ ├── protocols/ # Protocol-specific tests (IBC, OpInit)
|
|
559
|
+
│ └── utils/ # Utility function tests
|
|
560
|
+
├── package.json # Project metadata and dependencies
|
|
561
|
+
├── README.md # Project documentation
|
|
562
|
+
└── ... # Config and other files
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
|
|
566
|
+
|
|
567
|
+
## 📄 [License](#-license)
|
|
568
|
+
|
|
569
|
+
MIT
|