Skip to content

Commit

Permalink
Add event based interpreters (#103)
Browse files Browse the repository at this point in the history
* Add basescan for abis fetching

* Add interpreter by events

* Update tests

* Add link to interpreter source code

* Add changeset
  • Loading branch information
anastasiarods authored Sep 17, 2024
1 parent bc6b699 commit dfeba79
Show file tree
Hide file tree
Showing 33 changed files with 423 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-jokes-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@3loop/transaction-decoder': minor
---

Add human redable signature to decoded transaciton events
5 changes: 5 additions & 0 deletions .changeset/gorgeous-planes-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@3loop/transaction-interpreter': minor
---

Add option to specify interpreters based on event signature. Add new event-based interpreter.
38 changes: 37 additions & 1 deletion apps/web/src/app/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,81 +6,115 @@ export const EXAMPLE_TXS = {
name: 'Repay',
hash: '0xc0bd04d7e94542e58709f51879f64946ff4a744e1c37f5f920cea3d478e115d7',
chainID: 1,
interpreter: 'aave',
},
{
name: 'Deposit',
hash: '0xe61092c0ce50d7cf7c43a060c3ca023f16f99729ccae7a6d011e408d93d6f93f',
chainID: 1,
interpreter: 'aave',
},
{
name: 'Borrow',
hash: '0x1fc39eea9247cd9aa9d311bf83666afa6c9b30d66515d313e4d04dcb07a73a8f',
chainID: 1,
interpreter: 'aave',
},
{
name: 'Withdraw',
hash: '0xf42e5d28e2fea319cf3675c57c57849ad5d178f17f8a17c94c7607321cf1b959',
chainID: 1,
interpreter: 'aave',
},
],
'NFTS BLUR': [
{
name: 'Sell',
hash: '0xb5c56b4213325cb3fba274d0467b40ab28d9d475ba4a652b46943251c3c0d697',
chainID: 1,
interpreter: 'blur',
},
{
name: 'Buy',
hash: '0x9ed41e3d626605673c282dc8a0f7429e7abcab112d6529b0c77ee43954202cab',
chainID: 1,
interpreter: 'blur',
},
],
'Account Abstraction': [
{
name: 'handleOps',
hash: '0xcc1f4e40e1186503bb19b5716c8527947ab4c7e972b79d3d64ad8a015cf10ff8',
chainID: 1,
interpreter: 'aa',
},
],
'Swap Transactions': [
{
name: '1inch',
hash: '0x8e36953374f7b71fe4c20898c8ade628cf71d5d0303ec8ad368b254629db2985',
chainID: 1,
interpreter: '1inch',
},
{
name: 'Kyberswap',
hash: '0xfe429c6acf3c372270374122fe922282311bea31e09419f7fb167c6d8912372d',
chainID: 1,
interpreter: 'kyberswap',
},
{
name: 'Metamask Router',
hash: '0xcb2b8448a1f5dc7a29dc4ab3e79051e7460a4602b82ee5af2b3202c2e8b614de',
chainID: 1,
interpreter: 'metamaskRouter',
},
{
name: 'OKX',
hash: '0xf30013e82cd1197cb867f89ac33480699827282ca19ff49f0810a75e138ec869',
chainID: 1,
interpreter: 'okx',
},
],
'Bridge Transactions': [
{
name: 'Hop Protocol',
hash: '0x7a7f39aee8c68f9be272b093f613280a8122291923edba83cc3f1f1754a70ecd',
chainID: 1,
interpreter: 'hop-protocol',
},
],
'Friend.Tech (Base mainnet)': [
{
name: 'Sell',
hash: '0x9e18a3ab3faed1b13412e5cca532e083761410bb58e0423a5cd865a18a8e49a3',
chainID: 8453,
interpreter: 'friend-tech',
},
{
name: 'Buy',
hash: '0x24067751e1bb553b8f5ccd6958edc3fa27489f9836bc0cd477383b143825dca5',
chainID: 8453,
interpreter: 'friend-tech',
},
],
'Moxie (Base mainnet)': [
{
name: 'Sell',
hash: '0x0f2540f5936228704cf94348085fb16fde87bfb554a76f0234dc8d5a804b0a7b',
chainID: 8453,
interpreter: 'moxie',
},
{
name: 'Buy',
hash: '0xc355f63566a9407d9a610b13f5e4e7fc64ce526f34503af18666904b63e0556f',
chainID: 8453,
interpreter: 'moxie',
},
{
name: 'Burn',
hash: '0x88833e8e873c09b3def62c2fe82f5ac3a20cdb936acce5ba27a5e4ab20417831',
chainID: 8453,
interpreter: 'moxie',
},
],
}
Expand All @@ -106,7 +140,7 @@ export const supportedChains: {
name: 'Base mainnet',
chainID: 8453,
rpcUrl: process.env.BASE_RPC_URL as string,
traceAPI: 'geth',
traceAPI: 'parity',
batchMaxCount: 1,
},
{
Expand Down Expand Up @@ -149,3 +183,5 @@ const generateNavItems = (transactions: any) => {
export const sidebarNavItems = Object.fromEntries(
Object.entries(EXAMPLE_TXS).map(([key, value]) => [key, generateNavItems(value)]),
)

export const INTERPRETER_REPO = 'https://github.com/3loop/loop-decoder/tree/main/packages/transaction-interpreter'
24 changes: 22 additions & 2 deletions apps/web/src/app/tx/[chainID]/[hash]/form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'
import * as React from 'react'
import { Label } from '@/components/ui/label'
import { DEFAULT_CHAIN_ID, sidebarNavItems } from '@/app/data'
import { DEFAULT_CHAIN_ID, sidebarNavItems, EXAMPLE_TXS, INTERPRETER_REPO } from '@/app/data'
import { useLocalStorage } from 'usehooks-ts'
import { SidebarNav } from '@/components/ui/sidebar-nav'
import { PlayIcon } from '@radix-ui/react-icons'
Expand Down Expand Up @@ -64,6 +64,16 @@ export default function DecodingForm({ decoded, currentHash, currentChainID }: F
}
}, [schema, decoded, result, onRun])

const interpreterSourceLink = React.useMemo(() => {
const matchingExample = Object.values(EXAMPLE_TXS)
.flatMap((categoryTxs) => categoryTxs)
.find((tx) => tx.hash.toLowerCase() === currentHash?.toLowerCase())

return matchingExample?.interpreter
? `${INTERPRETER_REPO}/interpreters/${matchingExample?.interpreter}.ts`
: INTERPRETER_REPO
}, [currentHash])

return (
<div className="grid h-full items-stretch gap-6 grid-cols-1 lg:grid-cols-[1fr_200px]">
<div className="md:order-1 flex flex-col space-y-4">
Expand Down Expand Up @@ -93,7 +103,17 @@ export default function DecodingForm({ decoded, currentHash, currentChainID }: F

<div className="grid gap-6 grid-cols-1 lg:grid-cols-2 h-full">
<div className="flex flex-col gap-2 lg:col-span-2 min-h-[40vh] lg:min-h-[initial]">
<Label>Interpretation:</Label>
<Label>
Interpretation:{' '}
<a
href={interpreterSourceLink}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-blue-500 hover:underline"
>
(Source Code)
</a>
</Label>

<CodeBlock
language="javascript"
Expand Down
11 changes: 7 additions & 4 deletions apps/web/src/lib/contract-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ export const AbiStoreLive = Layer.succeed(
AbiStore,
AbiStore.of({
strategies: {
default: [
default: [SourcifyStrategyResolver(), OpenchainStrategyResolver(), FourByteStrategyResolver()],
1: [
EtherscanStrategyResolver({
apikey: process.env.ETHERSCAN_API_KEY,
}),
SourcifyStrategyResolver(),
OpenchainStrategyResolver(),
FourByteStrategyResolver(),
],
8453: [
EtherscanStrategyResolver({
apikey: process.env.BASESCAN_API_KEY,
}),
],
169: [
BlockscoutStrategyResolver({
Expand Down
5 changes: 5 additions & 0 deletions packages/transaction-decoder/src/decoding/log-decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getAndCacheAbi } from '../abi-loader.js'
import { getAndCacheContractMeta } from '../contract-meta-loader.js'
import * as AbiDecoder from './abi-decode.js'
import { stringify } from '../helpers/stringify.js'
import { formatAbiItem } from 'viem/utils'

const decodedLog = (transaction: GetTransactionReturnType, logItem: Log) =>
Effect.gen(function* () {
Expand Down Expand Up @@ -85,11 +86,14 @@ const decodedLog = (transaction: GetTransactionReturnType, logItem: Log) =>
},
})

const textSignature = formatAbiItem(fragment)

const rawLog: RawDecodedLog = {
events: decodedParams.filter((x) => x != null) as DecodedLogEvent[],
name: eventName,
address,
logIndex: logItem.logIndex ?? -1,
signature: textSignature,
decoded: true,
}

Expand All @@ -115,6 +119,7 @@ const transformLog = (transaction: GetTransactionReturnType, log: RawDecodedLog)
decimals: contractData?.decimals || null,
chainID: Number(transaction.chainId),
contractType: contractData?.type ?? 'OTHER',
signature: log.signature,
event: {
eventName: log.name,
logIndex: log.logIndex,
Expand Down
1 change: 1 addition & 0 deletions packages/transaction-decoder/src/decoding/trace-decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export function augmentTraceLogs(
event: traceLogToEvent(log),
decimals: null,
chainID: Number(transaction.chainId),
signature: null,
}),
)
return [...interactionsWithoutNativeTransfers, ...nativeTransfers]
Expand Down
2 changes: 2 additions & 0 deletions packages/transaction-decoder/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export interface RawDecodedLog {
logIndex: number
events: DecodedLogEvent[]
decoded: boolean
signature: string
}

export type ContractType = 'ERC20' | 'ERC721' | 'ERC1155' | 'WETH' | 'OTHER' | string
Expand All @@ -69,6 +70,7 @@ export interface Interaction {
decimals: number | null
chainID: number
contractType: ContractType
signature: string | null
event: InteractionEvent
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"owner": "0x997162a6BEB886655d3e355B190fe0C8f0c37F0e",
},
},
"signature": "ApprovalForAll(address,address,bool)",
},
],
"methodCall": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"value": "10000000000000000",
},
},
"signature": null,
},
{
"chainID": 1,
Expand All @@ -88,6 +89,7 @@
"value": "5000000000000000",
},
},
"signature": null,
},
{
"chainID": 1,
Expand All @@ -106,6 +108,7 @@
"value": "5000000000000000",
},
},
"signature": null,
},
],
"methodCall": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"tokenId": "9912",
},
},
"signature": "Approval(address,address,uint256)",
},
{
"chainID": 1,
Expand All @@ -106,6 +107,7 @@
"tokenId": "9912",
},
},
"signature": "Transfer(address,address,uint256)",
},
{
"chainID": 1,
Expand All @@ -123,6 +125,7 @@
"to": "0xde02FFFb824720E25674a604BaF2277f21c66a0F",
},
},
"signature": "Transfer(address,address,uint256)",
},
{
"chainID": 1,
Expand All @@ -140,6 +143,7 @@
"tokenIdListingIndexTrader": "3708519897897837542598287020838563106149287084151295037",
},
},
"signature": "Execution721Packed(bytes32,uint256,uint256)",
},
],
"methodCall": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"user": "0xbbDd1b3C87c211E482CdA98eA14fa8bF50022CA0",
},
},
"signature": "CancelTrade(address,bytes32,uint256,uint256)",
},
],
"methodCall": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"value": "2",
},
},
"signature": "TransferSingle(address,address,address,uint256,uint256)",
},
],
"methodCall": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"wad": "1361017781386941",
},
},
"signature": "Transfer(address,address,uint256)",
},
{
"chainID": 1,
Expand All @@ -115,6 +116,7 @@
"reserve1": "179139477",
},
},
"signature": "Sync(uint112,uint112)",
},
{
"chainID": 1,
Expand All @@ -135,6 +137,7 @@
"to": "0x12D737470fB3ec6C3DeEC9b518100Bec9D520144",
},
},
"signature": "Swap(address,uint256,uint256,uint256,uint256,address)",
},
{
"chainID": 1,
Expand All @@ -151,6 +154,7 @@
"wad": "1361017781386941",
},
},
"signature": "Withdrawal(address,uint256)",
},
{
"chainID": 1,
Expand All @@ -169,6 +173,7 @@
"value": "1361017781386941",
},
},
"signature": null,
},
{
"chainID": 1,
Expand All @@ -187,6 +192,7 @@
"value": "396600581496154",
},
},
"signature": null,
},
{
"chainID": 1,
Expand All @@ -205,6 +211,7 @@
"value": "964417199890787",
},
},
"signature": null,
},
],
"methodCall": {
Expand Down
Loading

0 comments on commit dfeba79

Please sign in to comment.