Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"generate-svm-clients": "yarn ts-node ./scripts/svm/utils/generate-svm-clients.ts && yarn ts-node ./scripts/svm/utils/rename-clients-imports.ts",
"build-evm": "hardhat compile",
"build-svm": "echo 'Generating IDLs...' && anchor build > /dev/null 2>&1 || true && anchor run generateExternalTypes && anchor build",
"build-ts": "tsc && rsync -a --include '*/' --include '*.d.ts' --exclude '*' ./typechain ./dist/",
"build-ts": "rm -rf ./dist && tsc && rsync -a --include '*/' --include '*.d.ts' --exclude '*' ./typechain ./dist/",
"copy-idl": "mkdir -p dist/src/svm/assets/idl && cp src/svm/assets/idl/*.json dist/src/svm/assets/idl/",
"build": "yarn build-evm && yarn build-svm && yarn generate-svm-assets && yarn build-ts && yarn copy-idl",
"test-evm": "IS_TEST=true hardhat test",
Expand All @@ -53,8 +53,8 @@
"@openzeppelin/contracts-upgradeable": "4.9.6",
"@scroll-tech/contracts": "^0.1.0",
"@solana-developers/helpers": "^2.4.0",
"@solana/kit": "^2.1.0",
"@solana/spl-token": "^0.4.6",
"@solana/web3-v2.js": "npm:@solana/web3.js@2",
"@solana/web3.js": "^1.31.0",
"@types/yargs": "^17.0.33",
"@uma/common": "^2.37.3",
Expand Down
2 changes: 1 addition & 1 deletion scripts/svm/queryEventsV2.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// 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 { address, createSolanaRpc } from "@solana/kit";
import { stringifyCpiEvent } from "../../src/svm/web3-v1";
import { SvmSpokeIdl } from "../../src/svm";
import yargs from "yargs";
Expand Down
2 changes: 1 addition & 1 deletion scripts/svm/utils/rename-clients-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function replaceInFiles(dir: string): void {
replaceInFiles(filePath);
} else if (file.endsWith(".ts")) {
const fileContent = fs.readFileSync(filePath, "utf8");
const updatedContent = fileContent.replace("@solana/web3.js", "@solana/web3-v2.js");
const updatedContent = fileContent.replace("@solana/web3.js", "@solana/kit");
fs.writeFileSync(filePath, updatedContent);
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/svm/web3-v2/solanaProgramUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import web3, {
GetTransactionApi,
RpcTransport,
Signature,
} from "@solana/web3-v2.js";
} from "@solana/kit";

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

Expand Down
67 changes: 65 additions & 2 deletions test/svm/SvmSpoke.Routes.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import * as anchor from "@coral-xyz/anchor";
import { BN } from "@coral-xyz/anchor";
import {
address,
appendTransactionMessageInstruction,
createKeyPairFromBytes,
createSignerFromKeyPair,
getProgramDerivedAddress,
pipe,
} from "@solana/kit";
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, createMint, getAccount } from "@solana/spl-token";
import { PublicKey, Keypair } from "@solana/web3.js";
import { Keypair, PublicKey } from "@solana/web3.js";
import { assert } from "chai";
import { common } from "./SvmSpoke.common";
import { SvmSpokeClient } from "../../src/svm";
import { SetEnableRouteInput } from "../../src/svm/clients/SvmSpoke";
import { readEventsUntilFound } from "../../src/svm/web3-v1";
import { common } from "./SvmSpoke.common";
import { createDefaultSolanaClient, createDefaultTransaction, signAndSendTransaction } from "./utils";

const { provider, program, owner, initializeState, createRoutePda, getVaultAta } = common;

Expand Down Expand Up @@ -116,4 +127,56 @@ describe("svm_spoke.routes", () => {
assert.strictEqual(err.error.errorCode.code, "InvalidMint", "Expected error code InvalidMint");
}
});

describe("codama client and solana kit", () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is great to verify.

it("Sets and retrieves route enablement with codama", async () => {
const rpcClient = createDefaultSolanaClient();
const signer = await createSignerFromKeyPair(
await createKeyPairFromBytes((anchor.AnchorProvider.env().wallet as anchor.Wallet).payer.secretKey)
);

const [eventAuthority] = await getProgramDerivedAddress({
programAddress: address(program.programId.toString()),
seeds: ["__event_authority"],
});

const input: SetEnableRouteInput = {
signer: signer,
payer: signer,
state: address(state.toString()),
route: address(routePda.toString()),
vault: address(vault.toString()),
originTokenMint: address(tokenMint.toString()),
tokenProgram: address(TOKEN_PROGRAM_ID.toString()),
associatedTokenProgram: address(ASSOCIATED_TOKEN_PROGRAM_ID.toString()),
systemProgram: address(anchor.web3.SystemProgram.programId.toString()),
eventAuthority: address(eventAuthority.toString()),
program: address(program.programId.toString()),
originToken: address(tokenMint.toString()),
destinationChainId: routeChainId.toNumber(),
enabled: true,
};
const instructions = SvmSpokeClient.getSetEnableRouteInstruction(input);
const tx = await pipe(
await createDefaultTransaction(rpcClient, signer),
(tx) => appendTransactionMessageInstruction(instructions, tx),
(tx) => signAndSendTransaction(rpcClient, tx)
);

// Retrieve and verify the route is enabled
let routeAccount = await SvmSpokeClient.fetchRoute(rpcClient.rpc, address(routePda.toString()));
assert.isTrue(routeAccount.data.enabled, "Route should be enabled");

// Verify the enabledDepositRoute event
let events = await readEventsUntilFound(provider.connection, tx, [program]);
let event = events[0].data;
assert.strictEqual(event.originToken.toString(), tokenMint.toString(), "originToken event match");
assert.strictEqual(
event.destinationChainId.toString(),
routeChainId.toString(),
"destinationChainId should match"
);
assert.isTrue(event.enabled, "enabledDepositRoute enabled");
});
});
});
70 changes: 69 additions & 1 deletion test/svm/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
import { BN, Program, workspace } from "@coral-xyz/anchor";
import {
airdropFactory,
Commitment,
CompilableTransactionMessage,
createSolanaRpc,
createSolanaRpcSubscriptions,
createTransactionMessage,
generateKeyPairSigner,
getSignatureFromTransaction,
lamports,
pipe,
Rpc,
RpcSubscriptions,
RpcTransport,
sendAndConfirmTransactionFactory,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
SignatureNotificationsApi,
signTransactionMessageWithSigners,
SlotNotificationsApi,
SolanaRpcApiFromTransport,
TransactionMessageWithBlockhashLifetime,
TransactionSigner,
} from "@solana/kit";
import { AccountMeta, Keypair, PublicKey } from "@solana/web3.js";
import * as crypto from "crypto";
import { BigNumber, ethers } from "ethers";
import { MulticallHandler } from "../../target/types/multicall_handler";
import {
AcrossPlusMessageCoder,
calculateRelayHashUint8Array,
Expand All @@ -12,6 +35,8 @@ import {
readProgramEvents,
relayerRefundHashFn,
} from "../../src/svm";
import { MulticallHandler } from "../../target/types/multicall_handler";

import { MerkleTree } from "@uma/common";
import { RelayerRefundLeaf, RelayerRefundLeafType } from "../../src/types/svm";

Expand Down Expand Up @@ -143,3 +168,46 @@ export function testAcrossPlusMessage() {
];
return { encodedMessage, fillRemainingAccounts };
}

export const signAndSendTransaction = async (
rpcClient: RpcClient,
transactionMessage: CompilableTransactionMessage & TransactionMessageWithBlockhashLifetime,
commitment: Commitment = "confirmed"
) => {
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
const signature = getSignatureFromTransaction(signedTransaction);
await sendAndConfirmTransactionFactory(rpcClient)(signedTransaction, {
commitment,
});
return signature;
};

export const createDefaultTransaction = async (rpcClient: RpcClient, signer: TransactionSigner) => {
const { value: latestBlockhash } = await rpcClient.rpc.getLatestBlockhash().send();
return pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(signer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx)
);
};

export const createDefaultSolanaClient = () => {
const rpc = createSolanaRpc("http://127.0.0.1:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://127.0.0.1:8900");
return { rpc, rpcSubscriptions };
};

type RpcClient = {
rpc: Rpc<SolanaRpcApiFromTransport<RpcTransport>>;
rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi & SlotNotificationsApi>;
};

export const generateKeyPairSignerWithSol = async (rpcClient: RpcClient, putativeLamports: bigint = 1_000_000_000n) => {
const signer = await generateKeyPairSigner();
await airdropFactory(rpcClient)({
recipientAddress: signer.address,
lamports: lamports(putativeLamports),
commitment: "confirmed",
});
return signer;
};
Loading
Loading