-
Notifications
You must be signed in to change notification settings - Fork 18
feat(epic): add SVM client #985
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
Draft
james-a-morris
wants to merge
15
commits into
master
Choose a base branch
from
epic/svm-client
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
8b3ed44
chore: create skeleton for svm spoke client (#965)
james-a-morris 6b1b65a
feat(svm): Initial SpokeUtils skeleton (#960)
pxrl 1b6939c
fix: epic branch lint (#972)
melisaguevara dff7f94
improve(Address): Support new EVM address from Base58 encoding
pxrl 60ecbce
Add svm/base16 counterpart
pxrl 58f376c
lint
pxrl 1a79e88
Merge remote-tracking branch 'origin/master'
pxrl b8aedad
Add test
pxrl eb9ae20
lint
pxrl fc4c167
Merge remote-tracking branch 'origin/pxrl/base58EVMAddress' into epic…
pxrl 27ce8ec
chore: Unify svm w/ arch/svm (#977)
pxrl 57d86cd
refactor(sdk): transition SVM events client to use blocks instead of …
james-a-morris 06e400d
feat(svmSpokeUtils): get fill deadline buffer implementation (#978)
melisaguevara c9ee25e
improve: allow SVM events client to take in non-spoke IDLs (#982)
bmzig 3e20d7e
improve(svmEventsClient): enable pda events querying (#989)
melisaguevara 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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"); | ||
} |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function findFillBlock throws an error with the message 'fillStatusArray: not implemented' which appears to be a copy-paste error. Please update the error message to accurately reflect the function name, e.g., 'findFillBlock: not implemented'.
Copilot uses AI. Check for mistakes.