Skip to content

Commit a5ef0c8

Browse files
authored
Merge pull request #107 from DefiLlama/solana-get-block-by-timestamp
Solana get block by timestamp
2 parents 74c8615 + 81501c8 commit a5ef0c8

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

src/utils/adapter.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getLatestBlockNumber } from "./blocks";
1+
import { getLatestBlockNumber, getTimestampBySolanaSlot } from "./blocks";
22
import { Chain } from "@defillama/sdk/build/general";
33
import { sql } from "./db";
44
import { getBridgeID } from "./wrappa/postgres/query";
@@ -438,6 +438,9 @@ export const runAdapterHistorical = async (
438438
blockTimestamps[i] = block.timestamp;
439439
break;
440440
}
441+
} else if (chain === "solana") {
442+
blockTimestamps[i] = await getTimestampBySolanaSlot(blockNumber);
443+
break;
441444
} else {
442445
blockTimestamps[i] = currentTimestamp;
443446
break;

src/utils/blocks.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { getLatestBlock as getLatestBlockSdk } from "@defillama/sdk/build/util";
1+
import { getLatestBlock as getLatestBlockSdk, lookupBlock } from "@defillama/sdk/build/util";
22
// import { getClient } from "../helpers/sui";
33
import { tronGetLatestBlock } from "../helpers/tron";
44
import { getConnection } from "../helpers/solana";
5+
import { Chain } from "@defillama/sdk/build/general";
56

67
export async function getLatestBlockNumber(chain: string): Promise<number> {
78
if (chain === "sui") {
@@ -35,3 +36,27 @@ export async function getLatestBlock(chain: string): Promise<{ number: number; t
3536
}
3637
return await getLatestBlockSdk(chain);
3738
}
39+
40+
export async function getBlockByTimestamp(timestamp: number, chain: Chain) {
41+
if (chain === "solana") {
42+
const { timestamp: latestTimestamp, number } = await getLatestBlock(chain);
43+
// There is not an easy way to get the slot number from a timestamp on Solana
44+
// without hammering the RPC node with requests.
45+
// So we estimate it by assuming that a slot is produced every 400ms.
46+
if (timestamp <= latestTimestamp) {
47+
const slot = number - Math.floor(((latestTimestamp - timestamp) * 1000) / 400);
48+
return { block: slot, timestamp };
49+
}
50+
} else {
51+
return await lookupBlock(timestamp, { chain });
52+
}
53+
throw new Error(`Could not find block for timestamp ${timestamp} on chain ${chain}`);
54+
}
55+
56+
export async function getTimestampBySolanaSlot(slot: number) {
57+
const { timestamp: latestTimestamp, number } = await getLatestBlock("solana");
58+
59+
const timestamp = latestTimestamp - ((number - slot) * 400) / 1000;
60+
61+
return timestamp;
62+
}

src/utils/runAdapterHistorical.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Chain } from "@defillama/sdk/build/general";
2-
import { lookupBlock } from "@defillama/sdk/build/util";
32
import bridgeNetworkData from "../data/bridgeNetworkData";
43
import { wait } from "../helpers/etherscan";
54
import { runAdapterHistorical } from "./adapter";
5+
import { getBlockByTimestamp } from "./blocks";
66

77
const startTs = Number(process.argv[2]);
88
const endTs = Number(process.argv[3]);
@@ -35,8 +35,8 @@ async function fillAdapterHistorical(
3535
if (restrictChainTo && nChain !== restrictChainTo) return;
3636
console.log(`Running adapter for ${chain} for ${bridgeDbName}`);
3737
await wait(500 * i);
38-
const startBlock = await lookupBlock(startTimestamp, { chain: nChain as Chain });
39-
const endBlock = await lookupBlock(endTimestamp, { chain: nChain as Chain });
38+
const startBlock = await getBlockByTimestamp(startTimestamp, nChain as Chain);
39+
const endBlock = await getBlockByTimestamp(endTimestamp, nChain as Chain);
4040
await runAdapterHistorical(
4141
startBlock.block,
4242
endBlock.block,

0 commit comments

Comments
 (0)