Skip to content

Commit

Permalink
feat: fixes and test script
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Maldonado <[email protected]>
  • Loading branch information
md0x committed Jan 17, 2025
1 parent 0135718 commit f9216c3
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 13 deletions.
1 change: 1 addition & 0 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ wallet = "test/svm/keys/localnet-wallet.json"
[scripts]
test = "anchor run generateExternalTypes && yarn run ts-mocha -p ./tsconfig.json -t 1000000 test/svm/**/*.ts"
queryEvents = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryEvents.ts"
queryEventsV2 = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryEventsV2.ts"
initialize = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/initialize.ts"
queryState = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/queryState.ts"
enableRoute = "NODE_NO_WARNINGS=1 yarn run ts-node ./scripts/svm/enableRoute.ts"
Expand Down
52 changes: 52 additions & 0 deletions scripts/svm/queryEventsV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// This script queries the events of the spoke pool and prints them in a human readable format.
import { AnchorProvider } from "@coral-xyz/anchor";
import { address, createSolanaRpc } from "@solana/web3-v2.js";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { readProgramEventsV2, stringifyCpiEvent, SvmSpokeIdl } from "../../src/svm";

// Set up the provider
const provider = AnchorProvider.env();

const argvPromise = yargs(hideBin(process.argv))
.option("eventName", {
type: "string",
demandOption: false,
describe: "Name of the event to query",
choices: [
"any",
"FilledV3Relay",
"V3FundsDeposited",
"EnabledDepositRoute",
"RelayedRootBundle",
"ExecutedRelayerRefundRoot",
"BridgedToHubPool",
"PausedDeposits",
"PausedFills",
"SetXDomainAdmin",
"EmergencyDeletedRootBundle",
"RequestedV3SlowFill",
"ClaimedRelayerRefund",
"TokensBridged",
],
})
.option("programId", {
type: "string",
demandOption: true,
describe: "SvmSpokeProgram ID to query events from",
}).argv;

async function queryEvents(): Promise<void> {
const argv = await argvPromise;
const eventName = argv.eventName || "any";
const programId = argv.programId;
const rpc = createSolanaRpc(provider.connection.rpcEndpoint);
const events = await readProgramEventsV2(rpc, address(programId), SvmSpokeIdl, "confirmed");
const filteredEvents = events.filter((event) => (eventName == "any" ? true : event.name == eventName));
const formattedEvents = filteredEvents.map((event) => stringifyCpiEvent(event));

console.log(JSON.stringify(formattedEvents, null, 2));
}

// Run the queryEvents function
queryEvents();
1 change: 1 addition & 0 deletions src/svm/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./web3-v1";
export * from "./web3-v2";
export * from "./assets";
export * from "./clients";
2 changes: 2 additions & 0 deletions src/svm/web3-v1/solanaProgramUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ export function stringifyCpiEvent(obj: any): any {
return obj.toString();
} else if (BN.isBN(obj)) {
return obj.toString();
} else if (typeof obj === "bigint" && obj !== 0n) {
return obj.toString();
} else if (Array.isArray(obj) && obj.length == 32) {
return Buffer.from(obj).toString("hex"); // Hex representation for fixed-length arrays
} else if (Array.isArray(obj)) {
Expand Down
1 change: 1 addition & 0 deletions src/svm/web3-v2/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./solanaProgramUtils";
27 changes: 14 additions & 13 deletions src/svm/web3-v2/solanaProgramUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { BorshEventCoder, Idl, utils } from "@coral-xyz/anchor";
import web3, {
Address,
Commitment,
GetSignaturesForAddressApi,
GetTransactionApi,
RpcTransport,
Signature,
Slot,
TransactionError,
Expand All @@ -11,13 +13,7 @@ import web3, {

type GetTransactionReturnType = ReturnType<GetTransactionApi["getTransaction"]>;

type GetSignaturesForAddressConfig = Readonly<{
before?: Signature;
commitment?: Exclude<Commitment, "processed">;
limit?: number;
minContextSlot?: Slot;
until?: Signature;
}>;
type GetSignaturesForAddressConfig = Parameters<GetSignaturesForAddressApi["getSignaturesForAddress"]>[1];

type GetSignaturesForAddressTransaction = {
blockTime: UnixTimestamp | null;
Expand All @@ -31,8 +27,8 @@ type GetSignaturesForAddressTransaction = {
/**
* Reads all events for a specific program.
*/
export async function readProgramEvents(
rpc: web3.Rpc<web3.SolanaRpcApiFromTransport<any>>,
export async function readProgramEventsV2(
rpc: web3.Rpc<web3.SolanaRpcApiFromTransport<RpcTransport>>,
program: Address,
anchorIdl: Idl,
finality: Commitment = "confirmed",
Expand All @@ -56,7 +52,7 @@ export async function readProgramEvents(
// Fetch events for all signatures in parallel
const eventsWithSlots = await Promise.all(
allSignatures.map(async (signatureTransaction) => {
const events = await readEvents(rpc, signatureTransaction.signature, program, anchorIdl, finality);
const events = await readEventsV2(rpc, signatureTransaction.signature, program, anchorIdl, finality);

return events.map((event) => ({
...event,
Expand All @@ -74,8 +70,8 @@ export async function readProgramEvents(
/**
* Reads events from a transaction.
*/
export async function readEvents(
rpc: web3.Rpc<web3.SolanaRpcApiFromTransport<any>>,
export async function readEventsV2(
rpc: web3.Rpc<web3.SolanaRpcApiFromTransport<RpcTransport>>,
txSignature: Signature,
programId: Address,
programIdl: Idl,
Expand All @@ -102,7 +98,12 @@ async function processEventFromTx(
const [pda] = await web3.getProgramDerivedAddress({ programAddress: programId, seeds: ["__event_authority"] });
eventAuthorities.set(programId, pda);

const messageAccountKeys = txResult.transaction.message.accountKeys;
const accountKeys = txResult.transaction.message.accountKeys;
const messageAccountKeys = [...accountKeys];
// Order matters here. writable accounts must be processed before readonly accounts.
// See https://docs.anza.xyz/proposals/versioned-transactions#new-transaction-format
messageAccountKeys.push(...(txResult?.meta?.loadedAddresses?.writable ?? []));
messageAccountKeys.push(...(txResult?.meta?.loadedAddresses?.readonly ?? []));

for (const ixBlock of txResult.meta?.innerInstructions ?? []) {
for (const ix of ixBlock.instructions) {
Expand Down

0 comments on commit f9216c3

Please sign in to comment.