Skip to content

Commit 63282cb

Browse files
committed
receipts: add new FetchReceiptTokenTransfers method to fetch and decode logs
1 parent 2eebc81 commit 63282cb

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

receipts/token_transfers.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package receipts
2+
3+
import (
4+
"context"
5+
"math/big"
6+
7+
"github.com/0xsequence/ethkit/ethrpc"
8+
"github.com/0xsequence/ethkit/go-ethereum/common"
9+
"github.com/0xsequence/ethkit/go-ethereum/core/types"
10+
"github.com/0xsequence/go-sequence/contracts/gen/tokens"
11+
)
12+
13+
// FetchReceiptTokenTransfers fetches the transaction receipt for the given transaction hash
14+
// and decodes any token transfer events (ERC20) that occurred within that transaction. TODOXXX: we
15+
// currently only support ERC20 token transfers, but we can extend this to support ERC721 and ERC1155 as well.
16+
func FetchReceiptTokenTransfers(ctx context.Context, provider *ethrpc.Provider, transactionHash common.Hash) (*types.Receipt, TokenTransfers, error) {
17+
receipt, err := provider.TransactionReceipt(ctx, transactionHash)
18+
if err != nil {
19+
return nil, nil, err
20+
}
21+
if receipt == nil {
22+
return nil, nil, nil
23+
}
24+
25+
transferTopic := common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
26+
polLogTransferTopic := common.HexToHash("0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4")
27+
28+
var decoded []*TokenTransfer
29+
30+
for _, log := range receipt.Logs {
31+
if len(log.Topics) == 0 {
32+
continue
33+
}
34+
if log.Topics[0] != transferTopic && log.Topics[0] != polLogTransferTopic {
35+
continue
36+
}
37+
38+
if log.Topics[0] == transferTopic {
39+
filterer, err := tokens.NewIERC20Filterer(log.Address, provider)
40+
if err == nil {
41+
if ev, err := filterer.ParseTransfer(*log); err == nil && ev != nil {
42+
decoded = append(decoded, &TokenTransfer{From: ev.From, To: ev.To, Value: ev.Value, Raw: *log})
43+
continue
44+
}
45+
}
46+
}
47+
48+
// TODO: need to try all of the various versions of this.. and we may as well support ERC721 and ERC1155 too
49+
// note: "indexed" args, etc.
50+
51+
if len(log.Topics) >= 3 {
52+
from := common.BytesToAddress(log.Topics[1].Bytes())
53+
to := common.BytesToAddress(log.Topics[2].Bytes())
54+
value := new(big.Int).SetBytes(log.Data)
55+
decoded = append(decoded, &TokenTransfer{From: from, To: to, Value: value, Raw: *log})
56+
}
57+
}
58+
59+
return receipt, decoded, nil
60+
}
61+
62+
type TokenTransfer struct {
63+
From common.Address
64+
To common.Address
65+
Value *big.Int
66+
Raw types.Log
67+
}
68+
69+
type TokenTransfers []*TokenTransfer
70+
71+
func (t TokenTransfers) FilterTokenTransfersByContractAddress(ctx context.Context, contract common.Address) TokenTransfers {
72+
var out TokenTransfers
73+
for _, transfer := range t {
74+
if transfer.Raw.Address == contract {
75+
out = append(out, transfer)
76+
}
77+
}
78+
return out
79+
}
80+
81+
func (t TokenTransfers) FilterTokenTransfersByFromAddress(ctx context.Context, from common.Address) TokenTransfers {
82+
var out TokenTransfers
83+
for _, transfer := range t {
84+
if transfer.From == from {
85+
out = append(out, transfer)
86+
}
87+
}
88+
return out
89+
}
90+
91+
func (t TokenTransfers) FilterTokenTransfersByToAddress(ctx context.Context, to common.Address) TokenTransfers {
92+
var out TokenTransfers
93+
for _, transfer := range t {
94+
if transfer.To == to {
95+
out = append(out, transfer)
96+
}
97+
}
98+
return out
99+
}

receipts/token_transfers_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package receipts_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/0xsequence/ethkit/ethrpc"
8+
"github.com/0xsequence/ethkit/go-ethereum/common"
9+
"github.com/0xsequence/go-sequence/receipts"
10+
"github.com/davecgh/go-spew/spew"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestFetchReceiptTokenTransfers(t *testing.T) {
15+
// txnHash := https://polygonscan.com/tx/0x252419983224542bfb07dab75808fa57186a7a269d0d267ae655eb7ef037fdd5
16+
provider, err := ethrpc.NewProvider("https://nodes.sequence.app/polygon")
17+
require.NoError(t, err)
18+
19+
txnHash := common.HexToHash("0x252419983224542bfb07dab75808fa57186a7a269d0d267ae655eb7ef037fdd5")
20+
21+
receipt, transfers, err := receipts.FetchReceiptTokenTransfers(context.Background(), provider, txnHash)
22+
require.NoError(t, err)
23+
require.NotNil(t, receipt)
24+
require.Greater(t, len(transfers), 0)
25+
26+
spew.Dump(transfers)
27+
}

0 commit comments

Comments
 (0)