Skip to content

Commit 51966dc

Browse files
committed
fix(fallback): erc721 transfer
1 parent 574bc26 commit 51966dc

File tree

6 files changed

+183
-79
lines changed

6 files changed

+183
-79
lines changed

api/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ app.get("/api/v1/healthcheck", (_req: Request, res: Response) => {
2121
res.json({
2222
success: true,
2323
timestamp: now.toISOString(),
24-
// time: TimestampParser(now, "descriptive"),
2524
uptime: process.uptime(),
2625
});
2726
});

services/decoder/decoder.ts

+21-28
Original file line numberDiff line numberDiff line change
@@ -151,35 +151,28 @@ export class GoldRushDecoder {
151151
tx: Transaction,
152152
covalent_api_key: string
153153
) => {
154-
try {
155-
const covalent_client = new CovalentClient(covalent_api_key);
156-
const events: EventType[] = [];
157-
const logs = tx.log_events.reverse();
158-
for (const log of logs) {
159-
const {
160-
raw_log_topics: [topic0_hash],
161-
sender_address: contract_address,
162-
// !ERROR: add factory_contract_address in the log_event(s)
163-
// factory_contract_address,
164-
} = log;
165-
const decoding_index =
166-
// !ERROR: add factory_contract_address in the log_event(s)
167-
// factory_contract_address ||
168-
this.decoders[network][contract_address]?.[topic0_hash];
169-
const fallback_index = this.fallbacks[topic0_hash];
170-
if (
171-
decoding_index !== undefined ||
172-
fallback_index !== undefined
173-
) {
174-
const event = await this.decoding_functions[
175-
decoding_index ?? fallback_index
176-
](log, tx, network, covalent_client);
177-
events.push(event);
178-
}
154+
const covalent_client = new CovalentClient(covalent_api_key);
155+
const events: EventType[] = [];
156+
const logs = tx.log_events.reverse();
157+
for (const log of logs) {
158+
const {
159+
raw_log_topics: [topic0_hash],
160+
sender_address: contract_address,
161+
// !ERROR: add factory_contract_address in the log_event(s)
162+
// factory_contract_address,
163+
} = log;
164+
const decoding_index =
165+
// !ERROR: add factory_contract_address in the log_event(s)
166+
// factory_contract_address ||
167+
this.decoders[network][contract_address]?.[topic0_hash];
168+
const fallback_index = this.fallbacks[topic0_hash];
169+
if (decoding_index !== undefined || fallback_index !== undefined) {
170+
const event = await this.decoding_functions[
171+
decoding_index ?? fallback_index
172+
](log, tx, network, covalent_client);
173+
events.push(event);
179174
}
180-
return events;
181-
} catch (error) {
182-
console.error(error);
183175
}
176+
return events;
184177
};
185178
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[
2+
{
3+
"anonymous": false,
4+
"inputs": [
5+
{
6+
"indexed": true,
7+
"internalType": "address",
8+
"name": "from",
9+
"type": "address"
10+
},
11+
{
12+
"indexed": true,
13+
"internalType": "address",
14+
"name": "to",
15+
"type": "address"
16+
},
17+
{
18+
"indexed": true,
19+
"internalType": "uint256",
20+
"name": "tokenId",
21+
"type": "uint256"
22+
}
23+
],
24+
"name": "Transfer",
25+
"type": "event"
26+
}
27+
]
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,117 @@
11
import { GoldRushDecoder } from "../../decoder";
2-
import { type EventType } from "../../decoder.types";
2+
import { type EventDetails, type EventType } from "../../decoder.types";
33
import {
44
DECODED_ACTION,
55
DECODED_EVENT_CATEGORY,
66
} from "../../decoder.constants";
77
import { decodeEventLog, type Abi } from "viem";
8-
import ABI from "./abis/transfer.abi.json";
8+
import ERC20ABI from "./abis/transfer-erc20.abi.json";
9+
import ERC721ABI from "./abis/transfer-erc721.abi.json";
910
import { TimestampParser } from "../../../../utils/functions";
1011
import { prettifyCurrency } from "@covalenthq/client-sdk";
1112

1213
GoldRushDecoder.fallback(
1314
"Transfer",
14-
ABI as Abi,
15+
ERC20ABI as Abi,
1516
async (log_event, tx, chain_name, covalent_client): Promise<EventType> => {
1617
const { raw_log_data, raw_log_topics } = log_event;
1718

18-
const { args: decoded } = decodeEventLog({
19-
abi: ABI,
20-
topics: raw_log_topics as [],
21-
data: raw_log_data as `0x${string}`,
22-
eventName: "Transfer",
23-
}) as {
24-
eventName: "Transfer";
25-
args: {
26-
from: string;
27-
to: string;
28-
value: bigint;
19+
let decoded:
20+
| {
21+
from: string;
22+
to: string;
23+
value: bigint;
24+
tokenId?: never;
25+
}
26+
| {
27+
from: string;
28+
to: string;
29+
tokenId: bigint;
30+
value?: never;
31+
};
32+
33+
try {
34+
const { args } = decodeEventLog({
35+
abi: ERC20ABI,
36+
topics: raw_log_topics as [],
37+
data: raw_log_data as `0x${string}`,
38+
eventName: "Transfer",
39+
}) as {
40+
eventName: "Transfer";
41+
args: {
42+
from: string;
43+
to: string;
44+
value: bigint;
45+
};
2946
};
30-
};
47+
decoded = args;
48+
} catch (error) {
49+
const { args } = decodeEventLog({
50+
abi: ERC721ABI,
51+
topics: raw_log_topics as [],
52+
data: raw_log_data as `0x${string}`,
53+
eventName: "Transfer",
54+
}) as {
55+
eventName: "Transfer";
56+
args: {
57+
from: string;
58+
to: string;
59+
tokenId: bigint;
60+
};
61+
};
62+
decoded = args;
63+
}
3164

32-
const date = TimestampParser(log_event.block_signed_at, "YYYY-MM-DD");
33-
const { data } = await covalent_client.PricingService.getTokenPrices(
34-
chain_name,
35-
"USD",
36-
log_event.sender_address,
65+
const details: EventDetails = [
3766
{
38-
from: date,
39-
to: date,
40-
}
41-
);
42-
43-
const pretty_quote =
44-
data?.[0]?.items?.[0]?.price *
45-
(Number(decoded.value) /
46-
Math.pow(
47-
10,
48-
data?.[0]?.items?.[0]?.contract_metadata
49-
?.contract_decimals ?? 18
50-
));
67+
title: "From",
68+
value: decoded.from,
69+
type: "address",
70+
},
71+
{
72+
title: "To",
73+
value: decoded.to,
74+
type: "address",
75+
},
76+
];
5177

52-
return {
78+
const parsedData: EventType = {
5379
action: DECODED_ACTION.SWAPPED,
5480
category: DECODED_EVENT_CATEGORY.DEX,
5581
name: "Transfer",
5682
protocol: {
5783
logo: log_event.sender_logo_url as string,
5884
name: log_event.sender_name as string,
5985
},
60-
details: [
61-
{
62-
title: "From",
63-
value: decoded.from,
64-
type: "address",
65-
},
66-
{
67-
title: "To",
68-
value: decoded.to,
69-
type: "address",
70-
},
71-
],
72-
tokens: [
86+
details: details,
87+
};
88+
89+
if (decoded.value) {
90+
const date = TimestampParser(
91+
log_event.block_signed_at,
92+
"YYYY-MM-DD"
93+
);
94+
const { data } =
95+
await covalent_client.PricingService.getTokenPrices(
96+
chain_name,
97+
"USD",
98+
log_event.sender_address,
99+
{
100+
from: date,
101+
to: date,
102+
}
103+
);
104+
105+
const pretty_quote =
106+
data?.[0]?.items?.[0]?.price *
107+
(Number(decoded.value) /
108+
Math.pow(
109+
10,
110+
data?.[0]?.items?.[0]?.contract_metadata
111+
?.contract_decimals ?? 18
112+
));
113+
114+
parsedData.tokens = [
73115
{
74116
decimals:
75117
data?.[0]?.items?.[0]?.contract_metadata
@@ -85,7 +127,45 @@ GoldRushDecoder.fallback(
85127
?.contract_ticker_symbol,
86128
value: decoded.value.toString(),
87129
},
88-
],
89-
};
130+
];
131+
} else if (decoded.tokenId) {
132+
const { data } =
133+
await covalent_client.NftService.getNftMetadataForGivenTokenIdForContract(
134+
chain_name,
135+
log_event.sender_address,
136+
decoded.tokenId.toString(),
137+
{
138+
withUncached: true,
139+
}
140+
);
141+
142+
parsedData.nfts = [
143+
{
144+
heading: "NFT Transferred",
145+
collection_address: data?.items?.[0]?.contract_address,
146+
collection_name:
147+
data?.items?.[0]?.nft_data?.external_data?.name || null,
148+
token_identifier:
149+
data?.items?.[0]?.nft_data?.token_id?.toString() ||
150+
null,
151+
images: {
152+
"1024":
153+
data?.items?.[0]?.nft_data?.external_data
154+
?.image_1024 || null,
155+
"512":
156+
data?.items?.[0]?.nft_data?.external_data
157+
?.image_512 || null,
158+
"256":
159+
data?.items?.[0]?.nft_data?.external_data
160+
?.image_256 || null,
161+
default:
162+
data?.items?.[0]?.nft_data?.external_data?.image ||
163+
null,
164+
},
165+
},
166+
];
167+
}
168+
169+
return parsedData;
90170
}
91171
);

services/decoder/fallbacks/transfer/transfer.test.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ describe("fallback", () => {
1818
throw Error("Event not found");
1919
}
2020
expect(event.details?.length).toEqual(2);
21-
expect(event.tokens?.length).toEqual(1);
21+
if (event.tokens) {
22+
expect(event.tokens?.length).toEqual(1);
23+
}
24+
if (event.nfts) {
25+
expect(event.nfts?.length).toEqual(1);
26+
}
2227
});
2328
});

0 commit comments

Comments
 (0)