Skip to content
Open
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
53 changes: 43 additions & 10 deletions solana/app/StakeConnection.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {
AnchorProvider,
Idl,
IdlAccounts,
Program,
utils,
Wallet,
} from "@coral-xyz/anchor";
import {
Connection,
ComputeBudgetProgram,
Keypair,
PublicKey,
SYSVAR_CLOCK_PUBKEY,
Expand All @@ -23,7 +23,6 @@ import {
} from "@solana/spl-token";
import BN from "bn.js";
import { Staking } from "../target/types/staking";
import IDL from "../target/idl/staking.json";
import { WHTokenBalance } from "./whTokenBalance";
import { contracts } from "@wormhole-foundation/sdk-base";
import {
Expand All @@ -40,6 +39,12 @@ import {
import { signaturesToSolanaArray } from "@wormhole-foundation/wormhole-query-sdk";
import { deriveGuardianSetKey } from "./helpers/guardianSet";
import crypto from "crypto";
import {
STAKING_ADDRESS as mainnetStakingAddress,
} from "./deploy/mainnet/constants";
import {
STAKING_ADDRESS as devnetStakingAddress,
} from "./deploy/devnet/constants";

let wasm = importedWasm;
export { wasm };
Expand Down Expand Up @@ -102,10 +107,12 @@ export class StakeConnection {
priorityFeeConfig?: PriorityFeeConfig,
): Promise<StakeConnection> {
const provider = new AnchorProvider(connection, wallet, {});
const program = new Program(
IDL as Idl,
provider,
) as unknown as Program<Staking>;
const stakingAddress = connection.rpcEndpoint.includes("mainnet")
? mainnetStakingAddress
: devnetStakingAddress;
const idl = (await Program.fetchIdl(stakingAddress, provider))!;
const program = new Program(idl, provider) as unknown as Program<Staking>;

// Sometimes in the browser, the import returns a promise.
// Don't fully understand, but this workaround is not terrible
if (wasm.hasOwnProperty("default")) {
Expand Down Expand Up @@ -747,7 +754,8 @@ export class StakeConnection {
guardianSignatures: PublicKey,
guardianSetIndex: number,
unoptimized?: boolean,
): Promise<void> {
simulateOnly?: boolean,
): Promise<void | SimulateResponse<any, any>> {
const { proposalAccount } = await this.fetchProposalAccount(proposalId);
const networkType = this.provider.connection.rpcEndpoint.includes("mainnet")
? "Mainnet"
Expand All @@ -767,13 +775,28 @@ export class StakeConnection {
guardianSet: deriveGuardianSetKey(coreBridge, guardianSetIndex),
});

if (unoptimized) {
if (simulateOnly) {
const { blockhash } = await this.provider.connection.getLatestBlockhash("finalized");
const computeBudgetInstruction = ComputeBudgetProgram.setComputeUnitLimit({
units: 400000,
});

const simulationResult = await methodsBuilder
.preInstructions([computeBudgetInstruction])
.transaction()
.then((tx) => {
tx.recentBlockhash = blockhash;
return methodsBuilder.simulate({
commitment: "finalized",
});
});

return simulationResult;
} else if (unoptimized) {
await methodsBuilder.rpc().then(this.confirm);
} else {
const instructions: TransactionInstruction[] = [];

instructions.push(await methodsBuilder.instruction());

await this.sendAndConfirmAsVersionedTransaction(instructions);
}
}
Expand Down Expand Up @@ -852,6 +875,16 @@ export interface BalanceSummary {
balance: WHTokenBalance;
}

export type SimulateResponse<E = any, Defined = any> = {
events: readonly Event<E, Defined>[];
raw: readonly string[];
};

export type Event<E, Defined> = {
name: string;
data: Defined;
};

export class StakeAccount {
address: PublicKey;
checkpointAccount: CheckpointAccount;
Expand Down
10 changes: 5 additions & 5 deletions solana/app/deploy/mainnet/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ export const RPC_NODE = "https://api.mainnet-beta.solana.com";

/// Wormhole Token (W) (mainnet solana address)
export const WORMHOLE_TOKEN = new PublicKey(
"85VBFQZC9TZkfaptBWjvUw7YbZjy52A6mjtPGjstQAmQ",
"3bgLkkFyNRejfYXZMsbAodnskvaF9jXaScvK1KtTv8W4",
);

export const STAKING_ADDRESS = new PublicKey(
"AFuHPdrQGsW8rNQ4oEFF35sm5fg36gwrxyqjkjKvi6ap",
"H3mSXnmYN3fChvRU6rhkLf9nGkytpEenSGm5DrgjFgHK",
);

export const CORE_BRIDGE_PID = new PublicKey(
contracts.coreBridge.get("Mainnet", "Solana")!, // worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth
);
console.log(CORE_BRIDGE_PID);
// console.log("CORE_BRIDGE_PID:", CORE_BRIDGE_PID);

/// Wormhole Hub Proposal Metadata Contract (mainnet ethereum address)
export const HUB_PROPOSAL_METADATA_ADDRESS =
"0x1a3e5624769c3dc9106347a239523e4a08d85c38"; // TODO: needs to be updated after a deployment to ethereum mainnet
"0xe1485b53e6E94aD4B82b19E48DA1911d2E19bFaE"; // TODO: needs to be updated after a deployment to ethereum mainnet
export const hubProposalMetadataUint8Array = new Uint8Array(
HUB_PROPOSAL_METADATA_ADDRESS.slice(2)
.toLowerCase()
Expand All @@ -37,7 +37,7 @@ export const CHECKPOINTS_ACCOUNT_LIMIT = 654998;

/// Wormhole hubSolanaMessageDispatcher Contract (mainnet ethereum address)
export const HUB_SOLANA_MESSAGE_DISPATCHER_ADDRESS =
"0xaeb78fb7ddedbbcab908e91e94f1fb04a23fbce5"; // TODO: needs to be updated after a deployment to ethereum mainnet
"0xadB8de6dfB41a1Fce6635460E77bEaDc73148BE4"; // TODO: needs to be updated after a deployment to ethereum mainnet
const hubSolanaMessageDispatcherHex20 =
HUB_SOLANA_MESSAGE_DISPATCHER_ADDRESS.slice(2);
const hubSolanaMessageDispatcherHex32 =
Expand Down
87 changes: 87 additions & 0 deletions solana/app/deploy/mainnet/tests/15_addProposal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Usage: npx ts-node app/deploy/mainnet/tests/15_addProposal.ts

import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
import { Connection, PublicKey } from "@solana/web3.js";
import { StakeConnection } from "../../../StakeConnection";
import {
CORE_BRIDGE_PID,
DEPLOYER_AUTHORITY_KEYPAIR,
RPC_NODE,
} from "../constants";
import { getWormholeBridgeData } from "../../../helpers/wormholeBridgeConfig";
import input from "@inquirer/input";

async function main() {
try {
const connection = new Connection(RPC_NODE);

const provider = new AnchorProvider(
connection,
new Wallet(DEPLOYER_AUTHORITY_KEYPAIR),
{},
);

const stakeConnection = await StakeConnection.createStakeConnection(
connection,
provider.wallet as Wallet,
);

const info = await getWormholeBridgeData(connection, CORE_BRIDGE_PID);
let guardianSetIndex = info.guardianSetIndex;

const mainnetEthProposalResponse = {
bytes:
"01000091c88387e43b5949ff6c07d4251571f9328baf9accb55ef61480117a540a9d4a6b845f8c0410b0244f8e9c0c8378642f1ad175ad77e2ca1c326941fff9246d60000000006401000000000100020300000057000000093078313531643936650000000966696e616c697a656401e1485b53e6e94ad4b82b19e48da1911d2e19bfae00000024eb9b9838fcdbb9499c27488ca8300323b4f6b3b08802093c3d822d931ef0149f797116df0100020300000075000000000151d96e08eaca24e456367d064e1fdaa2fed41e383bc581dfa6010d6c4443199ab117100006315aa3ab63c00100000040fcdbb9499c27488ca8300323b4f6b3b08802093c3d822d931ef0149f797116df0000000000000000000000000000000000000000000000000000000067e5527d",
signatures: [
"a9e756c766edaae672144d8799dbb927f6bc6c34f4769e9a1010cfea0818ce074ba9fd65713914e3f4dd66f45181032129c76b0af825213187be3c53ef62f0330100",
"82c78d62baa11304c1fa0c345e819d68798f9e183b55a4fc506b64a72bb0681e41b243d87d53fd9766723c1dc02a951730f1b4b178ceb11412d0891afd63bf4c0002",
"5819250b9ac5eb8a2896c99ea3a91af418643fab0b25e4547021e5ad673412fb6226e820ae6454bad9c0a15da406a32b0341d8b73fa426453df204f2f9f4ded20103",
"218c79a4deaf8a111d4573b55e33e77c40bc3f995d79d9edfc271d6a1bf1a1111aee8332800d45e8ad629429bbde3f6026f31bb8baa72c23adbc8a55cbaf44700106",
"40f0738532d9c3fd5921bbd2b058768f79ecbc4efd9dc3f14cbabb04e378cf1023792ea66ab44e92205f12c6552c25a2377460ca3fa1d90396de8e69bb99e5080007",
"72f0a5715c5c069baeba3e9586abfe661812671f9a12c73af375b3de92c128834657ded1a9159c9ce9ea6bb712cc98f4b0d5d3d45173ecac68b70f2a31aa3efa0109",
"eea28b273c3bc13f2e0ccabfea2e9760d92b45d87217281babce73976097a04106da9d153abd7d344b3a99b77065c095cfa85bc6ae95518d105ba73b5c06faf3000b",
"2655cdba9ef7707c6f9204d0ca02f779c8686e559d94cd4145eab84f9cb2df702daaced2bb74b1dd242b59a6b670da8c127c855c1b6b502e215e4e08467580bf010c",
"deed51fa86f355c5b6916873aa6b5d2b8bf798feec720da5e16b5ec05049b511278cb1f952cd9d01a3b3585ba7fe4a57c94c2f387137fa985424ae406d368467000d",
"53df6deebeda09aa91dacd9e32aa10663a03fb081c51d0a19887fddb30f147290ed1a74e3185009d961b235828792efa7c1a44fb2b39342837a4e321187e6673010e",
"7b88e420e5337bbb04cfd39b1c7f1c076837e32e859e8dc841fde3a71c9fffcc30400ec2896202ed37b7ca9ba12e2b03d6d35ad45f8501a77234bacf4f6698280010",
"186079ac19355cc723ae9276eef7c6940b45ed6993757f06a21c0c640ed45a8139ff2b7480e1a290bc8ffa1ced663af74b9fc56ac60dc7ff316bb6ec2bf6faf10111",
"f9412d3c8847878a62379b9e65ac598541e3b5892582ced8c1584815e4bae29702b609ee84a9ed294c9c6f75f544a6ccd4a488b5e496f7e0c5354b85232874910112"
],
};

const proposalId = await input({ message: "Enter the proposal id:" });
const proposalIdHex = BigInt(proposalId).toString(16).padStart(64, "0");
// console.log("proposalIdHex:", proposalIdHex);
const proposalIdArray = Buffer.from(proposalIdHex, "hex");

// const guardianSignaturesPda = await stakeConnection.postSignatures(
// mainnetEthProposalResponse.signatures,
// );
const guardianSignaturesPda = new PublicKey(
"WfU95bkYavZdQHi4dMJ17K7HtfzRqzduwHKAnLzkaiA",
);

const simulationResult = await stakeConnection.addProposal(
proposalIdArray,
Buffer.from(mainnetEthProposalResponse.bytes, "hex"),
guardianSignaturesPda,
guardianSetIndex,
false, // unoptimized
true, // simulateOnly
);

console.log("Simulation result:", simulationResult);

// await stakeConnection.addProposal(
// proposalIdArray,
// Buffer.from(mainnetEthProposalResponse.bytes, "hex"),
// guardianSignaturesPda,
// guardianSetIndex,
// true
// );
} catch (err) {
console.error("Error:", err);
}
}

main();
Loading