Skip to content

Instantly share code, notes, and snippets.

@0xOlias
Created June 4, 2024 14:41
Show Gist options
  • Save 0xOlias/d1d4da2060822faea3fdafd6db428134 to your computer and use it in GitHub Desktop.
Save 0xOlias/d1d4da2060822faea3fdafd6db428134 to your computer and use it in GitHub Desktop.
Dune script
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