Skip to content
This repository was archived by the owner on Jun 16, 2025. It is now read-only.

Commit dac3573

Browse files
committed
deploy: adds solana matching engine initialize script
1 parent 6f48c74 commit dac3573

File tree

3 files changed

+156
-2
lines changed

3 files changed

+156
-2
lines changed

deployment/helpers/solana.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1-
import { PublicKey } from '@solana/web3.js';
1+
import {
2+
Transaction,
3+
TransactionInstruction,
4+
Keypair,
5+
PublicKey,
6+
Connection,
7+
Commitment
8+
} from "@solana/web3.js";
9+
import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana";
10+
import { ecosystemChains, getEnv } from "./env";
11+
import type { SolanaScriptCb } from "./interfaces";
12+
import { inspect } from "util";
13+
14+
export const connectionCommitmentLevel = (process.env.SOLANA_COMMITMENT || "confirmed") as Commitment;
215

316
export function validateSolAddress(address: string){
417
try {
@@ -7,4 +20,71 @@ export function validateSolAddress(address: string){
720
} catch (error) {
821
return false;
922
}
23+
}
24+
25+
export function solanaOperatingChains() {
26+
const { operatingChains } = ecosystemChains;
27+
if (Array.isArray(operatingChains) && operatingChains.length >= 1) {
28+
return ecosystemChains.solana.networks.filter((x) => {
29+
return operatingChains.includes(x.chainId);
30+
});
31+
}
32+
return ecosystemChains.solana.networks;
33+
};
34+
35+
export async function runOnSolana(scriptName: string, cb: SolanaScriptCb) {
36+
const chains = solanaOperatingChains();
37+
38+
console.log(`Running script on Solana:`, scriptName);
39+
40+
const result = chains.map(async chain => {
41+
const log = (...args: any[]) => console.log(`[${chain.chainId}]`, ...args);
42+
const signer = await getSigner();
43+
log(`Starting script. Signer: ${await signer.getAddress()}`);
44+
45+
try {
46+
await cb(chain, signer, log);
47+
log("Success");
48+
} catch (error) {
49+
log("Error: ", (error as any)?.stack || inspect(error, {depth: 5}));
50+
}
51+
console.log();
52+
});
53+
54+
await Promise.all(result);
55+
}
56+
57+
let signer: SolanaLedgerSigner | null;
58+
export async function getSigner(): Promise<SolanaLedgerSigner> {
59+
if (!signer) {
60+
const derivationPath = getEnv("LEDGER_BIP32_PATH");
61+
signer = await SolanaLedgerSigner.create(derivationPath);
62+
}
63+
64+
return signer;
65+
}
66+
67+
export async function ledgerSignAndSend(connection: Connection, instructions: TransactionInstruction[], signers: Keypair[]) {
68+
const deployerSigner = await getSigner();
69+
const deployerPk = new PublicKey(await deployerSigner.getAddress());
70+
71+
const tx = new Transaction();
72+
73+
tx.add(...instructions);
74+
75+
const recentBlockHash = await connection.getLatestBlockhash();
76+
77+
tx.recentBlockhash = recentBlockHash.blockhash;
78+
tx.feePayer = deployerPk;
79+
80+
signers.forEach((signer) => tx.partialSign(signer));
81+
82+
await addLedgerSignature(tx, deployerSigner, deployerPk);
83+
84+
return connection.sendRawTransaction(tx.serialize());
85+
}
86+
87+
async function addLedgerSignature(tx: Transaction, signer: SolanaLedgerSigner, signerPk: PublicKey) {
88+
const signedByPayer = await signer.signTransaction(tx.compileMessage().serialize());
89+
tx.addSignature(signerPk, signedByPayer);
1090
}

deployment/scripts/evm/TokenRouter/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export async function deployImplementation(chain: ChainInfo, signer: ethers.Sign
2222

2323
const matchingEngineMintRecipient = (new UniversalAddress(getMintRecipientAddress(), 'base58')).toString();
2424
const matchinEngineChain = 1; // Solana wormhole chain id
25-
const matchingEngineDomain = 5; // Solana cctp domain
25+
const matchingEngineDomain = 5; // Solana cctp domain
2626
let matchingEngineAddress = (getContractAddress(
2727
"MatchingEngineProxy",
2828
matchinEngineChain
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {
2+
ComputeBudgetProgram,
3+
Connection,
4+
PublicKey,
5+
} from "@solana/web3.js";
6+
import "dotenv/config";
7+
import { uint64ToBN } from "@wormhole-foundation/example-liquidity-layer-solana/common";
8+
import { AuctionParameters, MatchingEngineProgram } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine";
9+
import { LoggerFn, connectionCommitmentLevel, getChainConfig, getContractAddress, ledgerSignAndSend, runOnSolana } from "../../helpers";
10+
import { MatchingEngineConfiguration } from "../../config/config-types";
11+
import { ProgramId } from "@wormhole-foundation/example-liquidity-layer-solana/matchingEngine";
12+
import { SolanaLedgerSigner } from "@xlabs-xyz/ledger-signer-solana";
13+
import { circle } from "@wormhole-foundation/sdk-base";
14+
15+
16+
const AUCTION_PARAMS: AuctionParameters = {
17+
userPenaltyRewardBps: 400000, // 40%
18+
initialPenaltyBps: 250000, // 25%
19+
duration: 5, // slots
20+
gracePeriod: 10, // slots
21+
penaltyPeriod: 20, // slots
22+
minOfferDeltaBps: 50000, // 5%
23+
securityDepositBase: uint64ToBN(1000000n), // 1 USDC
24+
securityDepositBps: 5000, // 0.5%
25+
};
26+
27+
runOnSolana("deploy-matching-engine", async (chain, signer, log) => {
28+
const config = await getChainConfig<MatchingEngineConfiguration>("matching-engine", chain.chainId);
29+
const matchingEngineId = getContractAddress("MatchingEngine", chain.chainId) as ProgramId;
30+
31+
const env = "Mainnet";
32+
const usdcMint = new PublicKey(circle.usdcContract(env, "Solana"));
33+
const connection = new Connection(chain.rpc, connectionCommitmentLevel);
34+
const matchingEngine = new MatchingEngineProgram(connection, matchingEngineId, usdcMint);
35+
36+
await initialize(matchingEngine, signer, log, config, usdcMint);
37+
});
38+
39+
async function initialize(matchingEngine: MatchingEngineProgram, signer: SolanaLedgerSigner, log: LoggerFn, config: MatchingEngineConfiguration, usdcMint: PublicKey) {
40+
const connection = matchingEngine.program.provider.connection;
41+
42+
const custodian = matchingEngine.custodianAddress();
43+
log("custodian", custodian.toString());
44+
45+
const exists = await connection.getAccountInfo(custodian).then((acct) => acct != null);
46+
if (exists) {
47+
log("already initialized");
48+
return;
49+
}
50+
51+
const signerPubkey = new PublicKey(await signer.getAddress());
52+
const initializeIx = await matchingEngine.initializeIx(
53+
{
54+
owner: signerPubkey,
55+
ownerAssistant: signerPubkey,
56+
feeRecipient: signerPubkey,
57+
},
58+
AUCTION_PARAMS,
59+
);
60+
61+
const splToken = await import("@solana/spl-token");
62+
const assocciatedTokenProgramId = splToken.ASSOCIATED_TOKEN_PROGRAM_ID;
63+
const associatedToken = splToken.getAssociatedTokenAddressSync(usdcMint, signerPubkey, undefined, usdcMint, assocciatedTokenProgramId);
64+
const createAtaInstructions = [];
65+
createAtaInstructions.push(splToken.createAssociatedTokenAccountInstruction(signerPubkey, associatedToken, signerPubkey, usdcMint));
66+
createAtaInstructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }));
67+
68+
const createAtaTxid = await ledgerSignAndSend(connection, createAtaInstructions, []);
69+
log(`CreateAtaTxid ${createAtaTxid}`);
70+
71+
const initializeTxid = await ledgerSignAndSend(connection, [initializeIx], []);
72+
log(`InitializeTxid ${initializeTxid}`);
73+
}
74+

0 commit comments

Comments
 (0)