Skip to content

Commit f8f8e9c

Browse files
committed
WIP: svm version of get fill deadline buffer
1 parent 1b6939c commit f8f8e9c

File tree

3 files changed

+76
-6
lines changed

3 files changed

+76
-6
lines changed

Diff for: src/arch/svm/SpokeUtils.ts

+58-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
1-
import { Rpc, SolanaRpcApi } from "@solana/kit";
1+
import {
2+
Rpc,
3+
SolanaRpcApi,
4+
Address,
5+
getProgramDerivedAddress,
6+
address,
7+
getStructDecoder,
8+
getBooleanCodec,
9+
getU32Codec,
10+
getU64Codec,
11+
getAddressCodec,
12+
getAddressDecoder,
13+
} from "@solana/kit";
14+
215
import { Deposit, FillStatus, FillWithBlock, RelayData } from "../../interfaces";
316
import { BigNumber, isUnsafeDepositId } from "../../utils";
17+
import { snakeToCamel } from "../../svm/utils/events";
418

519
type Provider = Rpc<SolanaRpcApi>;
620

@@ -52,12 +66,16 @@ export async function getTimestampForBlock(provider: Provider, blockNumber: numb
5266
* @param endBlock end block
5367
* @returns maximum of fill deadline buffer at start and end block
5468
*/
55-
export function getMaxFillDeadlineInRange(
56-
_spokePool: unknown,
69+
export async function getMaxFillDeadlineInRange(
70+
_spokePool: { provider: Provider },
5771
_startBlock: number,
5872
_endBlock: number
59-
): Promise<number> {
60-
throw new Error("getMaxFillDeadlineInRange: not implemented");
73+
): Promise<any> {
74+
const programId = "JAZWcGrpSWNPTBj8QtJ9UyQqhJCDhG9GJkDeMf5NQBiq"; // TODO: read this from the spokePool
75+
const statePda = await getStatePda(programId);
76+
const state = await queryStateFromStatePda(statePda, _spokePool.provider);
77+
78+
return state.fillDeadlineBuffer;
6179
}
6280

6381
/**
@@ -176,3 +194,38 @@ export function findFillEvent(
176194
): Promise<FillWithBlock | undefined> {
177195
throw new Error("fillStatusArray: not implemented");
178196
}
197+
198+
export async function queryStateFromStatePda(statePda: Address, provider: Provider) {
199+
const pdaAccountInfo = await provider.getAccountInfo(statePda, { encoding: "base64" }).send();
200+
if (!pdaAccountInfo.value?.data) {
201+
throw new Error("State account data not found");
202+
}
203+
const stateDecoder = getStructDecoder([
204+
["paused_deposits", getBooleanCodec()],
205+
["paused_fills", getBooleanCodec()],
206+
["owner", getAddressDecoder()],
207+
["seed", getU64Codec()],
208+
["number_of_deposits", getU32Codec()],
209+
["chain_id", getU64Codec()],
210+
["current_time", getU32Codec()],
211+
["remote_domain", getU32Codec()],
212+
["cross_domain_admin", getAddressCodec()],
213+
["root_bundle_id", getU32Codec()],
214+
["deposit_quote_time_buffer", getU32Codec()],
215+
["fill_deadline_buffer", getU32Codec()],
216+
]);
217+
const stateData = pdaAccountInfo.value.data[0];
218+
const stateDataBytes = Buffer.from(stateData, "base64");
219+
const discriminatorBytesSize = 8;
220+
const decodedState = stateDecoder.decode(Uint8Array.from(stateDataBytes), discriminatorBytesSize);
221+
return Object.fromEntries(Object.entries(decodedState).map(([key, value]) => [snakeToCamel(key), value]));
222+
}
223+
224+
// TODO: Should accept seed
225+
export async function getStatePda(programId: string): Promise<Address> {
226+
const [statePda] = await getProgramDerivedAddress({
227+
programAddress: address(programId),
228+
seeds: ["state", new Uint8Array(8)], // This only works if second seed is zero, make it dynamic
229+
});
230+
return statePda;
231+
}

Diff for: src/svm/utils/events.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function parseEventData(eventData: any): any {
3333
/**
3434
* Converts a snake_case string to camelCase.
3535
*/
36-
function snakeToCamel(s: string): string {
36+
export function snakeToCamel(s: string): string {
3737
return s.replace(/(_\w)/g, (match) => match[1].toUpperCase());
3838
}
3939

Diff for: test/SpokeUtils.ts

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { utils as ethersUtils } from "ethers";
22
import { UNDEFINED_MESSAGE_HASH, ZERO_BYTES } from "../src/constants";
33
import { getMessageHash, getRelayEventKey, keccak256, randomAddress, toBN, validateFillForDeposit } from "../src/utils";
44
import { expect } from "./utils";
5+
import { CachedSolanaRpcFactory } from "../src/providers";
6+
import { getMaxFillDeadlineInRange } from "../src/arch/svm/SpokeUtils";
57

68
const random = () => Math.round(Math.random() * 1e8);
79
const randomBytes = () => `0x${ethersUtils.randomBytes(48).join("").slice(0, 64)}`;
@@ -26,6 +28,21 @@ describe("SpokeUtils", function () {
2628
exclusivityDeadline: random(),
2729
};
2830

31+
it.only("getMaxFillDeadlineInRange returns the correct fill deadline", async function () {
32+
const rpcFactory = new CachedSolanaRpcFactory(
33+
"sdk-test",
34+
undefined,
35+
10,
36+
0,
37+
undefined,
38+
"https://api.mainnet-beta.solana.com",
39+
34268394551451
40+
);
41+
const provider = rpcFactory.createRpcClient();
42+
const fillDeadline = await getMaxFillDeadlineInRange({ provider }, 0, 100);
43+
console.log(fillDeadline);
44+
});
45+
2946
it("getRelayEventKey correctly concatenates an event key", function () {
3047
const eventKey = getRelayEventKey(sampleData);
3148
const expectedKey =

0 commit comments

Comments
 (0)