-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathSpokeUtils.ts
176 lines (157 loc) · 5.82 KB
/
SpokeUtils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import { Rpc, SolanaRpcApi, Address } from "@solana/kit";
import { Deposit, FillStatus, FillWithBlock, RelayData } from "../../interfaces";
import { BigNumber, isUnsafeDepositId } from "../../utils";
import { fetchState } from "@across-protocol/contracts/dist/src/svm/clients/SvmSpoke";
type Provider = Rpc<SolanaRpcApi>;
/**
* @param spokePool SpokePool Contract instance.
* @param deposit V3Deopsit instance.
* @param repaymentChainId Optional repaymentChainId (defaults to destinationChainId).
* @returns An Ethers UnsignedTransaction instance.
*/
export function populateV3Relay(
_spokePool: unknown,
_deposit: Omit<Deposit, "messageHash">,
_relayer: string,
_repaymentChainId = _deposit.destinationChainId
): Promise<unknown> {
throw new Error("populateV3Relay: not implemented");
}
/**
* Retrieves the time from the SpokePool contract at a particular block.
* @returns The time at the specified block tag.
*/
export function getTimeAt(_spokePool: unknown, _blockNumber: number): Promise<number> {
throw new Error("getTimeAt: not implemented");
}
/**
* Retrieves the chain time at a particular block.
* @note This should be the same as getTimeAt() but can differ in test. These two functions should be consolidated.
* @returns The chain time at the specified block tag.
*/
export async function getTimestampForBlock(provider: Provider, blockNumber: number): Promise<number> {
const block = await provider.getBlock(BigInt(blockNumber)).send();
let timestamp: number;
if (!block?.blockTime) {
console.error(`Unable to resolve svm block ${blockNumber}`);
timestamp = 0; // @todo: How to handle this?
} else {
timestamp = Number(block.blockTime); // Unix timestamps fit within number.
}
return timestamp;
}
/**
* Returns the current fill deadline buffer.
* @param provider SVM Provider instance
* @param statePda Spoke Pool's State PDA
* @returns fill deadline buffer
*/
export async function getFillDeadline(provider: Provider, statePda: Address): Promise<number> {
const state = await fetchState(provider, statePda);
return state.data.fillDeadlineBuffer;
}
/**
* Finds the deposit id at a specific block number.
* @param blockTag The block number to search for the deposit ID at.
* @returns The deposit ID.
*/
export function getDepositIdAtBlock(_contract: unknown, _blockTag: number): Promise<BigNumber> {
throw new Error("getDepositIdAtBlock: not implemented");
}
/**
* xxx todo
*/
export async function getSlotForBlock(
provider: Provider,
blockNumber: bigint,
lowSlot: bigint,
_highSlot?: bigint
): Promise<bigint | undefined> {
// @todo: Factor getBlock out to SlotFinder ??
const getBlockNumber = async (slot: bigint): Promise<bigint> => {
const block = await provider
.getBlock(slot, { transactionDetails: "none", maxSupportedTransactionVersion: 0 })
.send();
return block?.blockHeight ?? BigInt(0); // @xxx Handle undefined here!
};
let highSlot = _highSlot ?? (await provider.getSlot().send());
const [blockLow = 0, blockHigh = 1_000_000_000] = await Promise.all([
getBlockNumber(lowSlot),
getBlockNumber(highSlot),
]);
if (blockLow > blockNumber || blockHigh < blockNumber) {
return undefined; // blockNumber did not occur within the specified block range.
}
// Find the lowest slot number where blockHeight is greater than the requested blockNumber.
do {
const midSlot = (highSlot + lowSlot) / BigInt(2);
const midBlock = await getBlockNumber(midSlot);
if (midBlock < blockNumber) {
lowSlot = midSlot + BigInt(1);
} else if (midBlock > blockNumber) {
highSlot = midSlot + BigInt(1); // blockNumber occurred at or earlier than midBlock.
} else {
return midSlot;
}
} while (lowSlot <= highSlot);
return undefined;
}
export function findDepositBlock(
_spokePool: unknown,
depositId: BigNumber,
_lowBlock: number,
_highBlock?: number
): Promise<number | undefined> {
// We can only perform this search when we have a safe deposit ID.
if (isUnsafeDepositId(depositId)) {
throw new Error(`Cannot binary search for depositId ${depositId}`);
}
throw new Error("findDepositBlock: not implemented");
}
/**
* Find the amount filled for a deposit at a particular block.
* @param spokePool SpokePool contract instance.
* @param relayData Deposit information that is used to complete a fill.
* @param blockTag Block tag (numeric or "latest") to query at.
* @returns The amount filled for the specified deposit at the requested block (or latest).
*/
export function relayFillStatus(
_spokePool: unknown,
_relayData: RelayData,
_blockTag?: number | "latest",
_destinationChainId?: number
): Promise<FillStatus> {
throw new Error("relayFillStatus: not implemented");
}
export function fillStatusArray(
_spokePool: unknown,
_relayData: RelayData[],
_blockTag = "processed"
): Promise<(FillStatus | undefined)[]> {
throw new Error("fillStatusArray: not implemented");
}
/**
* Find the block at which a fill was completed.
* @todo After SpokePool upgrade, this function can be simplified to use the FillStatus enum.
* @param spokePool SpokePool contract instance.
* @param relayData Deposit information that is used to complete a fill.
* @param lowBlockNumber The lower bound of the search. Must be bounded by SpokePool deployment.
* @param highBlocknumber Optional upper bound for the search.
* @returns The block number at which the relay was completed, or undefined.
*/
export function findFillBlock(
_spokePool: unknown,
_relayData: RelayData,
_lowBlockNumber: number,
_highBlockNumber?: number
): Promise<number | undefined> {
throw new Error("fillStatusArray: not implemented");
}
export function findFillEvent(
_spokePool: unknown,
_relayData: RelayData,
_lowBlockNumber: number,
_highBlockNumber?: number
): Promise<FillWithBlock | undefined> {
throw new Error("fillStatusArray: not implemented");
}