Created
June 4, 2024 14:41
-
-
Save 0xOlias/d1d4da2060822faea3fdafd6db428134 to your computer and use it in GitHub Desktop.
Dune script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
QueryParameter, | |
DuneClient, | |
QueryEngine, | |
type ResultsResponse, | |
} from "@duneanalytics/client-sdk"; | |
type Hex = `0x${string}`; | |
type LogFilter = { | |
// chainId: number; | |
id: string; | |
address?: Hex | Hex[]; | |
topics: (Hex | Hex[] | null)[]; | |
startBlock: number; | |
endBlock: number; | |
}; | |
type TraceFilter = { | |
// chainId: number; | |
id: string; | |
fromAddress?: Hex | Hex[]; | |
toAddress?: Hex | Hex[]; | |
startBlock: number; | |
endBlock: number; | |
}; | |
type BlockFilter = { | |
// chainId: number; | |
id: string; | |
interval: number; | |
offset: number; | |
startBlock: number; | |
endBlock: number; | |
}; | |
if (process.env.DUNE_API_KEY === undefined) { | |
throw new Error("DUNE_API_KEY environment variable is required"); | |
} | |
const client = new DuneClient(process.env.DUNE_API_KEY); | |
function waitForExecutionResults(executionId: string) { | |
return new Promise<ResultsResponse>((resolve, reject) => { | |
const interval = setInterval(async () => { | |
try { | |
const resultsResponse = await client.exec.getExecutionResults( | |
executionId | |
); | |
if (resultsResponse.is_execution_finished) { | |
clearInterval(interval); | |
resolve(resultsResponse); | |
} else { | |
console.log("Waiting 1s for execution to finish..."); | |
} | |
} catch (error) { | |
clearInterval(interval); | |
reject(error); | |
} | |
}, 1_000); | |
}); | |
} | |
function encodeAddressOrTopic(value: Hex | Hex[] | null | undefined) { | |
if (value === undefined || value === null) return null; | |
if (Array.isArray(value)) return value.join(","); | |
return value; | |
} | |
function buildQueryParameters( | |
logFilters: LogFilter[], | |
traceFilters: TraceFilter[] | |
) { | |
return [ | |
QueryParameter.text("log_filter_id", logFilters.map((l) => l.id).join(";")), | |
QueryParameter.text( | |
"log_filter_address", | |
logFilters.map((l) => encodeAddressOrTopic(l.address)).join(";") | |
), | |
QueryParameter.text( | |
"log_filter_topic0", | |
logFilters.map((l) => encodeAddressOrTopic(l.topics[0])).join(";") | |
), | |
QueryParameter.text( | |
"log_filter_topic1", | |
logFilters.map((l) => encodeAddressOrTopic(l.topics[1])).join(";") | |
), | |
QueryParameter.text( | |
"log_filter_topic2", | |
logFilters.map((l) => encodeAddressOrTopic(l.topics[2])).join(";") | |
), | |
QueryParameter.text( | |
"log_filter_topic3", | |
logFilters.map((l) => encodeAddressOrTopic(l.topics[3])).join(";") | |
), | |
QueryParameter.text( | |
"log_filter_start_block", | |
logFilters.map((l) => l.startBlock).join(";") | |
), | |
QueryParameter.text( | |
"log_filter_end_block", | |
logFilters.map((l) => l.endBlock).join(";") | |
), | |
QueryParameter.text( | |
"trace_filter_id", | |
traceFilters.map((l) => l.id).join(";") | |
), | |
QueryParameter.text( | |
"trace_filter_from_address", | |
traceFilters.map((l) => encodeAddressOrTopic(l.fromAddress)).join(";") | |
), | |
QueryParameter.text( | |
"trace_filter_to_address", | |
traceFilters.map((l) => encodeAddressOrTopic(l.toAddress)).join(";") | |
), | |
QueryParameter.text( | |
"trace_filter_start_block", | |
traceFilters.map((l) => l.startBlock).join(";") | |
), | |
QueryParameter.text( | |
"trace_filter_end_block", | |
traceFilters.map((l) => l.endBlock).join(";") | |
), | |
QueryParameter.number("start_block", 19970990), | |
QueryParameter.number("end_block", 19971010), | |
QueryParameter.number("limit", 1000), | |
]; | |
} | |
const logFilterErc20Transfer: LogFilter = { | |
id: "erc20-transfer", | |
topics: [ | |
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", | |
], | |
startBlock: 19971000, | |
endBlock: 19971100, | |
}; | |
const logFilterWethEvents: LogFilter = { | |
id: "weth", | |
address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", | |
topics: [ | |
[ | |
"0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c", // Weth Deposit | |
"0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65", // Weth Withdrawal | |
], | |
], | |
startBlock: 19971000, | |
endBlock: 19971100, | |
}; | |
const logFilterTokens: LogFilter = { | |
id: "erc20-tokens", | |
address: [ | |
"0x4d224452801ACEd8B2F0aebE155379bb5D594381", // ApeCoin | |
"0x6982508145454Ce325dDbE47a25d4ec3d2311933", // Pepe | |
], | |
topics: [], | |
startBlock: 19971000, | |
endBlock: 19971100, | |
}; | |
const traceFilterTokens: TraceFilter = { | |
id: "erc20-tokens", | |
toAddress: [ | |
"0x4d224452801ACEd8B2F0aebE155379bb5D594381", // ApeCoin | |
"0x6982508145454Ce325dDbE47a25d4ec3d2311933", // Pepe | |
], | |
startBlock: 19971000, | |
endBlock: 19971100, | |
}; | |
const queryParameters = buildQueryParameters( | |
[logFilterErc20Transfer, logFilterWethEvents, logFilterTokens], | |
[traceFilterTokens] | |
); | |
const executeResponse = await client.exec.executeQuery(3776025, { | |
// performance: QueryEngine.Medium, | |
query_parameters: queryParameters, | |
}); | |
const resultsResponse = await waitForExecutionResults( | |
executeResponse.execution_id | |
); | |
console.log(resultsResponse.result?.rows); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment