Skip to content
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

feat(svm): include solana artifacts in package build output #806

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ target
**/*.rs.bk
test-ledger
idls
src/svm/assets
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./typechain";
export * from "./src/DeploymentUtils";
export * from "./utils";
export * from "./src/svm";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The program getters, types, and IDLs can be imported directly from @across-protocol/contracts, as well as utility functions (we should move the latter to the SDK next).

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
"lint-fix": "yarn prettier --write **/*.js **/*.ts ./programs/**/*.rs ./contracts**/*.sol && cargo +nightly fmt --all && cargo clippy",
"clean-fast": "for dir in node_modules cache cache-zk artifacts artifacts-zk dist typechain; do mv \"${dir}\" \"_${dir}\"; rm -rf \"_${dir}\" &; done",
"clean": "rm -rf node_modules cache cache-zk artifacts artifacts-zk dist typechain",
"generate-svm-assets": "sh ./scripts/generate-svm-assets.sh",
Copy link
Member

Choose a reason for hiding this comment

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

we should think about making this file easier to reason about with this new command you've added. the equivalent evm command is generate-contract-types. I tried with the other commands to make it clear what they are (solidity/js/rust/evm/svm) but this one is now a bit inconsistent. perhaps if we call it generate-svm-assets and then re-name the generate-contract-types to generate-evm-assets?

also, I think that given this command is not yet within the prepublish command we could actually be safe to merge this into master without it joining the released package.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated ✅

also, I think that given this command is not yet within the prepublish command we could actually be safe to
merge this into master without it joining the released package.

I think it is, its part of the build as we need to run yarn generate-svm-assets before yarn build-ts. See this:

"build": "yarn build-evm && yarn build-svm && yarn generate-svm-assets && yarn build-ts",

Let's wait for @mrice32 & @nicholaspai to see what they think the proposed changes.

"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": "yarn build-evm && yarn build-svm && yarn build-ts",
"build": "yarn build-evm && yarn build-svm && yarn generate-svm-assets && yarn build-ts",
"test-evm": "IS_TEST=true hardhat test",
"test-svm": "anchor test -- --features test",
"test": "yarn test-evm && yarn test-svm",
Expand Down
89 changes: 89 additions & 0 deletions scripts/generate-svm-assets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/bin/bash

# Set paths for source and destination
TARGET_IDL="./target/idl"
TARGET_TYPES="./target/types"
SVM_ASSETS="./src/svm/assets"
SVM_IDL="$SVM_ASSETS/idl"
SVM_TYPES="$SVM_ASSETS"
IDL_OUTPUT_FILE="$SVM_IDL/index.ts"
TYPES_OUTPUT_FILE="$SVM_TYPES/index.ts"

# Ensure the destination directories exist
mkdir -p "$SVM_IDL"
mkdir -p "$SVM_TYPES"

# --- Copy Files ---
echo "Copying IDL files..."
cp -r "$TARGET_IDL/"* "$SVM_IDL/"

echo "Copying Types files..."
cp -r "$TARGET_TYPES/"* "$SVM_TYPES/"

# --- Generate IDL index.ts ---
echo "Generating IDL index.ts..."
> "$IDL_OUTPUT_FILE"

# Add autogenerated file note
{
echo "// This file has been autogenerated. Do not edit manually."
echo "// Generated by a script."
echo
} >> "$IDL_OUTPUT_FILE"

IMPORTS=""
EXPORTS=""

for file in "$SVM_IDL"/*.json; do
filename=$(basename -- "$file")
name="${filename%.json}"
camelCaseName=$(echo "$name" | awk -F'_' '{
for (i=1; i<=NF; i++) {
printf toupper(substr($i,1,1)) tolower(substr($i,2));
}
}')
IMPORTS="${IMPORTS}const ${camelCaseName}Idl = require(\"./${filename}\");\n"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We use require() for the IDLs similarly as before in the scripts to avoid ts issues:

const svmSpokeIdl = require("../../target/idl/svm_spoke.json");

EXPORTS="${EXPORTS} ${camelCaseName}Idl,\n"
done

# Write the imports to the file
printf "$IMPORTS" >> "$IDL_OUTPUT_FILE"

# Write the exports block
{
echo "export {"
printf "$EXPORTS" | sed '$ s/,$//'
echo "};"
} >> "$IDL_OUTPUT_FILE"

echo "IDL index.ts generated successfully at $IDL_OUTPUT_FILE"

# --- Generate svm-types index.ts ---
echo "Generating svm-types index.ts..."
> "$TYPES_OUTPUT_FILE"

# Add autogenerated file note
{
echo "// This file has been autogenerated. Do not edit manually."
echo "// Generated by a script."
echo
} >> "$TYPES_OUTPUT_FILE"

# Export * from ./idl
echo "export * from \"./idl\";" >> "$TYPES_OUTPUT_FILE"

# Export * from each .ts file in ./svm-types, removing underscores and capitalizing names
for file in "$SVM_TYPES"/*.ts; do
[ "$(basename -- "$file")" = "index.ts" ] && continue
filename=$(basename -- "$file")
name="${filename%.ts}"
camelCaseName=$(echo "$name" | awk -F'_' '{
for (i=1; i<=NF; i++) {
printf toupper(substr($i,1,1)) tolower(substr($i,2));
}
}')
newName="${camelCaseName}Anchor"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Prepend "Anchor" to the types to prevent conflicts with evm types

echo "export {${camelCaseName} as ${newName}} from \"./${name}\";" >> "$TYPES_OUTPUT_FILE"
done

echo "svm-types index.ts generated successfully at $TYPES_OUTPUT_FILE"
18 changes: 6 additions & 12 deletions scripts/svm/bridgeLiabilityToHubPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@
*/

import * as anchor from "@coral-xyz/anchor";
import { AnchorProvider, BN, Program } from "@coral-xyz/anchor";
import { AnchorProvider, BN } from "@coral-xyz/anchor";
import { ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { PublicKey, SystemProgram } from "@solana/web3.js";
// eslint-disable-next-line camelcase
import { MessageTransmitter } from "../../target/types/message_transmitter";
import { SvmSpoke } from "../../target/types/svm_spoke";
// eslint-disable-next-line camelcase
import {
CIRCLE_IRIS_API_URL_DEVNET,
CIRCLE_IRIS_API_URL_MAINNET,
Expand All @@ -44,20 +41,17 @@ import {
import { TOKEN_SYMBOLS_MAP } from "@across-protocol/constants";
import { getNodeUrl } from "@uma/common";
import { BigNumber, ethers } from "ethers";
import { TokenMessengerMinter } from "../../target/types/token_messenger_minter";
import { getMessageTransmitterProgram, getSpokePoolProgram, getTokenMessengerMinterProgram } from "../../src/svm";
import { getMessages } from "../../test/svm/cctpHelpers";
import { BondToken__factory } from "../../typechain";
import { formatUsdc, requireEnv, isSolanaDevnet } from "./utils/helpers";
import { formatUsdc, isSolanaDevnet, requireEnv } from "./utils/helpers";

// Set up Solana provider.
const provider = AnchorProvider.env();
anchor.setProvider(provider);

// Get Solana programs and IDLs.
const svmSpokeIdl = require("../../target/idl/svm_spoke.json");
const svmSpokeProgram = new Program<SvmSpoke>(svmSpokeIdl, provider);
const messageTransmitterIdl = require("../../target/idl/message_transmitter.json");
const tokenMessengerMinterIdl = require("../../target/idl/token_messenger_minter.json");
const svmSpokeProgram = getSpokePoolProgram(provider);

// CCTP domains.
const ethereumDomain = 0; // Ethereum
Expand Down Expand Up @@ -199,7 +193,7 @@ async function bridgeLiabilityToHubPool(): Promise<void> {
}

async function bridgeTokensToHubPool(amount: BN, signer: anchor.Wallet, statePda: PublicKey, inputToken: PublicKey) {
const messageTransmitterProgram = new Program<MessageTransmitter>(messageTransmitterIdl, provider);
const messageTransmitterProgram = getMessageTransmitterProgram(provider);

const vault = getAssociatedTokenAddressSync(
inputToken,
Expand All @@ -214,7 +208,7 @@ async function bridgeTokensToHubPool(amount: BN, signer: anchor.Wallet, statePda
[Buffer.from("transfer_liability"), inputToken.toBuffer()],
svmSpokeProgram.programId
);
const tokenMessengerMinterProgram = new Program<TokenMessengerMinter>(tokenMessengerMinterIdl, provider);
const tokenMessengerMinterProgram = getTokenMessengerMinterProgram(provider);

const [tokenMessengerMinterSenderAuthority] = PublicKey.findProgramAddressSync(
[Buffer.from("sender_authority")],
Expand Down
8 changes: 3 additions & 5 deletions scripts/svm/closeRelayerPdas.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
// This script closes all Relayer PDAs associated with tracking fill Status. Relayers should do this periodically to
// reclaim the lamports within these tracking accounts. Fill Status PDAs can be closed on the deposit has expired.
import * as anchor from "@coral-xyz/anchor";
import { BN, Program, AnchorProvider } from "@coral-xyz/anchor";
import { AnchorProvider, BN } from "@coral-xyz/anchor";
import { PublicKey, SystemProgram } from "@solana/web3.js";
import { SvmSpoke } from "../../target/types/svm_spoke";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { calculateRelayEventHashUint8Array, readProgramEvents } from "../../src/svm";
import { calculateRelayEventHashUint8Array, getSpokePoolProgram, readProgramEvents } from "../../src/svm";

// Set up the provider
const provider = AnchorProvider.env();
anchor.setProvider(provider);
const idl = require("../../target/idl/svm_spoke.json");
const program = new Program<SvmSpoke>(idl, provider);
const program = getSpokePoolProgram(provider);
const programId = program.programId;

// Parse arguments
Expand Down
9 changes: 4 additions & 5 deletions scripts/svm/enableRoute.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// This script is used by a chain admin to enable or disable a route for a token on the Solana Spoke Pool.

import * as anchor from "@coral-xyz/anchor";
import { BN, Program, AnchorProvider } from "@coral-xyz/anchor";
import { PublicKey, SystemProgram } from "@solana/web3.js";
import { AnchorProvider, BN } from "@coral-xyz/anchor";
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync } from "@solana/spl-token";
import { SvmSpoke } from "../../target/types/svm_spoke";
import { PublicKey, SystemProgram } from "@solana/web3.js";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { getSpokePoolProgram } from "../../src/svm";

// Set up the provider
const provider = AnchorProvider.env();
anchor.setProvider(provider);
const idl = require("../../target/idl/svm_spoke.json");
const program = new Program<SvmSpoke>(idl, provider);
const program = getSpokePoolProgram(provider);
const programId = program.programId;
console.log("SVM-Spoke Program ID:", programId.toString());

Expand Down
19 changes: 8 additions & 11 deletions scripts/svm/executeRebalanceToHubPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ import {
import { BigNumber, ethers } from "ethers";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { MessageTransmitter } from "../../target/types/message_transmitter";
import { SvmSpoke } from "../../target/types/svm_spoke";
import { CHAIN_IDs } from "../../utils/constants";
// eslint-disable-next-line camelcase
import { HubPool__factory } from "../../typechain";
Expand All @@ -60,24 +58,23 @@ import {
constructSimpleRebalanceTreeToHubPool,
formatUsdc,
getSolanaChainId,
requireEnv,
isSolanaDevnet,
requireEnv,
} from "./utils/helpers";

import { getNodeUrl, MerkleTree } from "@uma/common";
import { decodeMessageHeader, getMessages } from "../../test/svm/cctpHelpers";
import { getMessageTransmitterProgram, getSpokePoolProgram, loadExecuteRelayerRefundLeafParams } from "../../src/svm";
import { SvmSpokeAnchor } from "../../src/svm/assets";
import { RelayerRefundLeafSolana, RelayerRefundLeafType } from "../../src/types/svm";
import { loadExecuteRelayerRefundLeafParams } from "../../src/svm";

import { decodeMessageHeader, getMessages } from "../../test/svm/cctpHelpers";
// Set up Solana provider.
const provider = AnchorProvider.env();
anchor.setProvider(provider);

// Get Solana programs.
const svmSpokeIdl = require("../../target/idl/svm_spoke.json");
const svmSpokeProgram = new Program<SvmSpoke>(svmSpokeIdl, provider);
const messageTransmitterIdl = require("../../target/idl/message_transmitter.json");
const messageTransmitterProgram = new Program<MessageTransmitter>(messageTransmitterIdl, provider);

const svmSpokeProgram = getSpokePoolProgram(provider);
const messageTransmitterProgram = getMessageTransmitterProgram(provider);

const [messageTransmitterState] = PublicKey.findProgramAddressSync(
[Buffer.from("message_transmitter")],
Expand Down Expand Up @@ -339,7 +336,7 @@ async function executeRootBalanceOnHubPool(solanaChainId: BigNumber) {

async function executeRelayerRefundLeaf(
signer: anchor.Wallet,
program: Program<SvmSpoke>,
program: Program<SvmSpokeAnchor>,
statePda: PublicKey,
rootBundle: PublicKey,
relayerRefundLeaf: RelayerRefundLeafSolana,
Expand Down
31 changes: 15 additions & 16 deletions scripts/svm/executeRebalanceToSpokePool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,41 @@
// - HUB_POOL_ADDRESS: Hub Pool address

import * as anchor from "@coral-xyz/anchor";
import { BN, Program, AnchorProvider } from "@coral-xyz/anchor";
import { AccountMeta, PublicKey, SystemProgram } from "@solana/web3.js";
import { AnchorProvider, BN } from "@coral-xyz/anchor";
import { TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync } from "@solana/spl-token";
import { AccountMeta, PublicKey, SystemProgram } from "@solana/web3.js";
import { getNodeUrl } from "@uma/common";
// eslint-disable-next-line camelcase
import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../../utils/constants";
import { SvmSpoke } from "../../target/types/svm_spoke";
import { BigNumber, ethers } from "ethers";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { evmAddressToPublicKey } from "../../src/svm";
import { MessageTransmitter } from "../../target/types/message_transmitter";
import { TokenMessengerMinter } from "../../target/types/token_messenger_minter";
import { ethers, BigNumber } from "ethers";
import {
evmAddressToPublicKey,
getMessageTransmitterProgram,
getSpokePoolProgram,
getTokenMessengerMinterProgram,
} from "../../src/svm";
import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../../utils/constants";
// eslint-disable-next-line camelcase
import { decodeMessageHeader, getMessages } from "../../test/svm/cctpHelpers";
import { HubPool__factory } from "../../typechain";
import {
CIRCLE_IRIS_API_URL_DEVNET,
CIRCLE_IRIS_API_URL_MAINNET,
SOLANA_USDC_DEVNET,
SOLANA_USDC_MAINNET,
} from "./utils/constants";
import { constructSimpleRebalanceTree } from "./utils/poolRebalanceTree";
import { decodeMessageHeader, getMessages } from "../../test/svm/cctpHelpers";
import { getSolanaChainId, isSolanaDevnet, requireEnv } from "./utils/helpers";
import { constructSimpleRebalanceTree } from "./utils/poolRebalanceTree";

// Set up Solana provider.
const provider = AnchorProvider.env();
anchor.setProvider(provider);

// Get Solana programs.
const svmSpokeIdl = require("../../target/idl/svm_spoke.json");
const svmSpokeProgram = new Program<SvmSpoke>(svmSpokeIdl, provider);
const messageTransmitterIdl = require("../../target/idl/message_transmitter.json");
const messageTransmitterProgram = new Program<MessageTransmitter>(messageTransmitterIdl, provider);
const tokenMessengerMinterIdl = require("../../target/idl/token_messenger_minter.json");
const tokenMessengerMinterProgram = new Program<TokenMessengerMinter>(tokenMessengerMinterIdl, provider);
const svmSpokeProgram = getSpokePoolProgram(provider);
const messageTransmitterProgram = getMessageTransmitterProgram(provider);
const tokenMessengerMinterProgram = getTokenMessengerMinterProgram(provider);

// Set up Ethereum provider and signer.
const isDevnet = isSolanaDevnet(provider);
Expand Down
13 changes: 6 additions & 7 deletions scripts/svm/fakeFillWithRandomDistribution.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// This script implements a fill where relayed tokens are distributed to random recipients via the message handler.
// Note that this should be run only on devnet as this is fake fill and all filled tokens are sent to random recipients.
import * as anchor from "@coral-xyz/anchor";
import { BN, Program, AnchorProvider } from "@coral-xyz/anchor";
import { AccountMeta, Keypair, PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js";
import { AnchorProvider, BN } from "@coral-xyz/anchor";
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
createApproveCheckedInstruction,
createTransferCheckedInstruction,
getAssociatedTokenAddressSync,
getOrCreateAssociatedTokenAccount,
getMint,
createApproveCheckedInstruction,
getOrCreateAssociatedTokenAccount,
} from "@solana/spl-token";
import { SvmSpoke } from "../../target/types/svm_spoke";
import { AccountMeta, Keypair, PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import {
AcrossPlusMessageCoder,
MulticallHandlerCoder,
calculateRelayHashUint8Array,
getSpokePoolProgram,
loadFillV3RelayParams,
sendTransactionWithLookupTable,
} from "../../src/svm";
Expand All @@ -29,8 +29,7 @@ const provider = AnchorProvider.env();
anchor.setProvider(provider);
const signer = (anchor.AnchorProvider.env().wallet as anchor.Wallet).payer;

const idl = require("../../target/idl/svm_spoke.json");
const program = new Program<SvmSpoke>(idl, provider);
const program = getSpokePoolProgram(provider);
const programId = program.programId;

// Parse arguments
Expand Down
8 changes: 3 additions & 5 deletions scripts/svm/initialize.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
// This script initializes a SVM spoke pool with initialization parameters.

import * as anchor from "@coral-xyz/anchor";
import { BN, Program, AnchorProvider } from "@coral-xyz/anchor";
import { AnchorProvider, BN } from "@coral-xyz/anchor";
import { PublicKey, SystemProgram } from "@solana/web3.js";
import { SvmSpoke } from "../../target/types/svm_spoke";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { evmAddressToPublicKey } from "../../src/svm";
import { evmAddressToPublicKey, getSpokePoolProgram } from "../../src/svm";

// Set up the provider
const provider = AnchorProvider.env();
anchor.setProvider(provider);
const idl = require("../../target/idl/svm_spoke.json");
const program = new Program<SvmSpoke>(idl, provider);
const program = getSpokePoolProgram(provider);
const programId = program.programId;

// Parse arguments
Expand Down
Loading
Loading