Skip to content

Commit 4384599

Browse files
committed
add Etherscan integration to fetch Torch transfer events
1 parent 9946d7d commit 4384599

File tree

2 files changed

+68
-49
lines changed

2 files changed

+68
-49
lines changed

src/lib/torch/etherscan.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { type Address } from "viem"
2+
3+
import Torch from "@/data/Torch.json"
4+
5+
const TORCH_CONTRACT_ADDRESS = Torch.address as Address
6+
const TORCH_BLOCK_NUMBER = Torch.blockNumber
7+
8+
export type TransferEvent = {
9+
from: Address
10+
to: Address
11+
blockNumber: number
12+
transactionHash: string
13+
timestamp: number
14+
}
15+
16+
// You'll need to get an API key from https://etherscan.io/apis
17+
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || ""
18+
19+
export const fetchTorchTransfersFromEtherscan = async (): Promise<
20+
TransferEvent[]
21+
> => {
22+
if (!ETHERSCAN_API_KEY) {
23+
throw new Error("ETHERSCAN_API_KEY environment variable is required")
24+
}
25+
26+
try {
27+
// Get contract events from Etherscan
28+
const response = await fetch(
29+
[
30+
"https://api.etherscan.io/api",
31+
"?module=logs",
32+
"&action=getLogs",
33+
`&address=${TORCH_CONTRACT_ADDRESS}`,
34+
`&fromBlock=${TORCH_BLOCK_NUMBER}`,
35+
"&toBlock=latest",
36+
// ERC721 Transfer event signature
37+
"&topic0=0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
38+
`&apikey=${ETHERSCAN_API_KEY}`,
39+
].join("")
40+
)
41+
42+
const data = await response.json()
43+
44+
if (data.status !== "1") {
45+
throw new Error(`Etherscan API error: ${data.message}`)
46+
}
47+
48+
return data.result.map(
49+
(log: {
50+
topics: string[]
51+
blockNumber: string
52+
transactionHash: string
53+
timeStamp: string
54+
}) => ({
55+
from: `0x${log.topics[1].slice(26)}` as Address, // Remove padding from topic1
56+
to: `0x${log.topics[2].slice(26)}` as Address, // Remove padding from topic2
57+
blockNumber: parseInt(log.blockNumber, 16),
58+
transactionHash: log.transactionHash,
59+
timestamp: parseInt(log.timeStamp, 16),
60+
})
61+
)
62+
} catch (error) {
63+
console.error("Failed to fetch torch transfers from Etherscan:", error)
64+
return []
65+
}
66+
}

src/lib/torch/index.ts

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import { getPublicClient } from "@wagmi/core"
66
import Torch from "@/data/Torch.json"
77

88
import { config } from "./config"
9+
import { fetchTorchTransfersFromEtherscan } from "./etherscan"
910

1011
const TORCH_CONTRACT_ADDRESS = Torch.address as Address
1112
const TORCH_ABI = Torch.abi
12-
const TORCH_BLOCK_NUMBER = Torch.blockNumber
1313

1414
// Addresses to filter from the UI (show as "Unknown Holder")
1515
const FILTERED_ADDRESSES: string[] = [
@@ -50,54 +50,7 @@ export type TorchHolderEvent = TorchHolder & {
5050

5151
export const getTransferEvents = cache(
5252
async () => {
53-
const publicClient = getPublicClient(config)
54-
55-
// Get the current block number to ensure consistent results
56-
const currentBlock = await publicClient.getBlockNumber()
57-
58-
// Get Transfer events from the contract
59-
// ERC721 Transfer event signature: Transfer(address indexed from, address indexed to, uint256 indexed tokenId)
60-
const logs = await publicClient.getLogs({
61-
address: TORCH_CONTRACT_ADDRESS,
62-
event: {
63-
type: "event",
64-
name: "Transfer",
65-
inputs: [
66-
{ name: "from", type: "address", indexed: true },
67-
{ name: "to", type: "address", indexed: true },
68-
{ name: "tokenId", type: "uint256", indexed: true },
69-
],
70-
},
71-
args: {
72-
tokenId: BigInt(1), // Torch NFT token ID is always 1
73-
},
74-
fromBlock: BigInt(TORCH_BLOCK_NUMBER) || "earliest",
75-
toBlock: currentBlock,
76-
})
77-
78-
// Process logs and get timestamps
79-
const transferEvents: TransferEvent[] = []
80-
81-
for (const log of logs) {
82-
if (log.args?.from && log.args?.to) {
83-
// Get block details to get timestamp
84-
const block = await publicClient.getBlock({
85-
blockNumber: log.blockNumber,
86-
})
87-
88-
transferEvents.push({
89-
from: log.args.from as Address,
90-
to: log.args.to as Address,
91-
blockNumber: Number(log.blockNumber),
92-
transactionHash: log.transactionHash,
93-
timestamp: Number(block.timestamp),
94-
})
95-
}
96-
}
97-
98-
// Sort by block number (oldest first)
99-
transferEvents.sort((a, b) => a.blockNumber - b.blockNumber)
100-
53+
const transferEvents = await fetchTorchTransfersFromEtherscan()
10154
return transferEvents
10255
},
10356
["torch-transfer-events"],

0 commit comments

Comments
 (0)