-
Notifications
You must be signed in to change notification settings - Fork 18
feat(svm): Initial SpokeUtils skeleton #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
c97baa1
feat(svm): Initial SpokeUtils skeleton
pxrl 39d9d13
Add export
pxrl 0da1adf
lint
pxrl c28fcae
improve(SpokePoolClient): Remove redundant relayFillStatus argument (…
pxrl 8fac709
Merge remote-tracking branch 'origin/master' into pxrl/svmSpokeUtilsM…
pxrl 1592e2c
Drop unnecessary implementations
pxrl 9cfd362
getSlotForBlock()
pxrl aa71f10
lint
pxrl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import { Rpc, SolanaRpcApi } from "@solana/kit"; | ||
import { Deposit, FillStatus, FillWithBlock, RelayData } from "../../interfaces"; | ||
import { BigNumber, isUnsafeDepositId } from "../../utils"; | ||
|
||
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; | ||
} | ||
|
||
/** | ||
* Return maximum of fill deadline buffer at start and end of block range. | ||
* @param spokePool SpokePool contract instance | ||
* @param startBlock start block | ||
* @param endBlock end block | ||
* @returns maximum of fill deadline buffer at start and end block | ||
*/ | ||
export function getMaxFillDeadlineInRange( | ||
_spokePool: unknown, | ||
_startBlock: number, | ||
_endBlock: number | ||
): Promise<number> { | ||
throw new Error("getMaxFillDeadlineInRange: not implemented"); | ||
} | ||
|
||
/** | ||
* 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"); | ||
} |
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export const platform = "svm"; // Placeholder for actual exports. | ||
export * from "./SpokeUtils"; |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.