Skip to content

Commit

Permalink
Track all addresses involved into a transaction (#17)
Browse files Browse the repository at this point in the history
* Track all addresses involved into a transaction

* Add test for disperse app batch transfers

* Changeset

* Rename all addresses field to interacted addresses
  • Loading branch information
Ferossgp authored Dec 24, 2023
1 parent 7121c4c commit bcd03ed
Show file tree
Hide file tree
Showing 24 changed files with 8,250 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/khaki-schools-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@3loop/transaction-decoder": minor
---

Add all addresses involved in the transaction in the decode output
11 changes: 7 additions & 4 deletions packages/transaction-decoder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "@3loop/transaction-decoder",
"version": "0.2.0",
"description": "A library for decoding Ethereum transactions",
"type": "module",
"types": "dist/index.d.ts",
"main": "dist/index.cjs",
"license": "GPL-3.0-only",
Expand Down Expand Up @@ -32,8 +31,8 @@
"fix": "eslint --ignore-path .eslintignore --ext .ts . --fix",
"test": "vitest run --config ./vitest.config.mts",
"test:watch": "vitest run --config ./vitest.config.mts --watch",
"gen:mock": "ts-node --esm -T test/mocks/create-mock.ts",
"example": "ts-node --esm -T example/index.ts"
"gen:mock": "ts-node -T test/mocks/create-mock.ts",
"example": "ts-node -T example/index.ts"
},
"files": [
"dist/**/*",
Expand All @@ -50,6 +49,7 @@
"@effect/schema": "^0.33.2",
"@total-typescript/ts-reset": "^0.5.1",
"@types/node": "^20.6.0",
"@types/traverse": "^0.6.35",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6",
"@vitest/coverage-v8": "0.34.2",
Expand All @@ -74,5 +74,8 @@
"engines": {
"node": ">=18.16"
},
"sideEffects": false
"sideEffects": false,
"dependencies": {
"traverse": "^0.6.7"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function transferDecode({
reverted: receipt.status === 0, // will return true if status==undefined
assetsReceived: [],
assetsSent: [], // TDOO: display the eth sent
interactedAddresses: [receipt.from, receipt.to].filter(Boolean),
}

return decodedTx
Expand Down
34 changes: 32 additions & 2 deletions packages/transaction-decoder/src/transaction-decoder.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Effect } from 'effect'
import type { TransactionReceipt, TransactionResponse } from 'ethers'
import { Network, formatEther } from 'ethers'
import { Network, formatEther, isAddress } from 'ethers'
import { getBlockTimestamp, getTrace, getTransaction, getTransactionReceipt } from './transaction-loader.js'
import * as AbiDecoder from './decoding/abi-decode.js'
import * as LogDecoder from './decoding/log-decode.js'
import * as TraceDecoder from './decoding/trace-decode.js'
import { transferDecode } from './decoding/transfer-decode.js'
import type { DecodedTx, Interaction } from './types.js'
import type { DecodeResult, DecodedTx, Interaction } from './types.js'
import { TxType } from './types.js'
import type { TraceLog } from './schema/trace.js'
import { getAssetsReceived, getAssetsSent } from './transformers/tokens.js'
import { getProxyStorageSlot } from './decoding/proxies.js'
import { getAndCacheAbi } from './abi-loader.js'
import { getAndCacheContractMeta } from './contract-meta-loader.js'
import traverse from 'traverse'

export class UnsupportedEvent {
readonly _tag = 'UnsupportedEvent'
Expand Down Expand Up @@ -118,6 +119,34 @@ export const decodeTrace = ({ trace, transaction }: { trace: TraceLog[]; transac
)
})

const collectAllAddresses = ({
interactions,
decodedData,
}: {
interactions: Interaction[]
decodedData: DecodeResult
}) => {
const addresses = new Set<string>()
for (const interaction of interactions) {
addresses.add(interaction.contractAddress)
traverse(interaction.event).forEach(function (value: string) {
if (this.isLeaf && isAddress(value)) {
addresses.add(value)
}
})
}

if (decodedData.params) {
for (const param of decodedData.params) {
if (param.value && isAddress(param.value)) {
addresses.add(param.value)
}
}
}

return [...addresses]
}

export const decodeTransaction = ({
transaction,
receipt,
Expand Down Expand Up @@ -182,6 +211,7 @@ export const decodeTransaction = ({
// NOTE: Explore how to set assets for more flexible tracking of the in and out addresses
assetsReceived: getAssetsReceived(interactions, receipt.from),
assetsSent: getAssetsSent(interactions, value, receipt.from, receipt.from),
interactedAddresses: collectAllAddresses({ interactions, decodedData }),
}

return decodedTx
Expand Down
1 change: 1 addition & 0 deletions packages/transaction-decoder/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export interface DecodedTx {
effectiveGasPrice: string | null
assetsReceived: Asset[]
assetsSent: Asset[]
interactedAddresses: string[]
}

export interface MethodCall {
Expand Down
4 changes: 4 additions & 0 deletions packages/transaction-decoder/test/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ export const TEST_TRANSACTIONS = [
hash: '0x1cf9beb600427c0fef7b4b5794f0f3eccef6a75cec1f1680b9295187effa3788', //ERC-1155 Mint
chainID: 5,
},
{
hash: '0x9d20b73d7b102aacc63dadf01ed7767cbbfd1c3f92302b08f6741be4bd8fb6cf', // Disperse app
chainID: 5,
},
]
3 changes: 2 additions & 1 deletion packages/transaction-decoder/test/mocks/abi-loader-mock.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Effect, Layer } from 'effect'
import fs from 'node:fs'
import { AbiStore } from '@/abi-loader.js'
import { EtherscanStrategyResolver } from '@/effect.js'

export const MockedAbiStoreLive = Layer.succeed(
AbiStore,
AbiStore.of({
strategies: [],
strategies: [EtherscanStrategyResolver()],
set: ({ address = {}, func = {}, event = {} }) =>
Effect.gen(function* (_) {
const addressMatches = Object.entries(address)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"recipients","type":"address[]"},{"name":"values","type":"uint256[]"}],"name":"disperseTokenSimple","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"recipients","type":"address[]"},{"name":"values","type":"uint256[]"}],"name":"disperseToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipients","type":"address[]"},{"name":"values","type":"uint256[]"}],"name":"disperseEther","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}]
2 changes: 1 addition & 1 deletion packages/transaction-decoder/test/mocks/create-mock.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { JsonRpcProvider } from 'ethers'
import fs from 'fs'
import fs from 'node:fs'

const GOERLI_RPC = 'https://rpc.ankr.com/eth_goerli'

Expand Down
Loading

0 comments on commit bcd03ed

Please sign in to comment.