200 lines
5.9 KiB
TypeScript
200 lines
5.9 KiB
TypeScript
import * as web3s from "@solana/web3.js";
|
|
import { NETWORKS } from "./networks";
|
|
import { impossible, Payload, VAA } from "./vaa";
|
|
import base58 from "bs58";
|
|
import { postVaaSolanaWithRetry } from "@certusone/wormhole-sdk/lib/cjs/solana";
|
|
import {
|
|
CHAINS,
|
|
CONTRACTS,
|
|
SolanaChainName,
|
|
} from "@certusone/wormhole-sdk/lib/cjs/utils/consts";
|
|
import {
|
|
createUpgradeContractInstruction as createWormholeUpgradeContractInstruction,
|
|
createUpgradeGuardianSetInstruction,
|
|
} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole";
|
|
import {
|
|
createCompleteTransferNativeInstruction,
|
|
createCompleteTransferWrappedInstruction,
|
|
createCreateWrappedInstruction,
|
|
createRegisterChainInstruction as createTokenBridgeRegisterChainInstruction,
|
|
createUpgradeContractInstruction as createTokenBridgeUpgradeContractInstruction,
|
|
} from "@certusone/wormhole-sdk/lib/cjs/solana/tokenBridge";
|
|
import {
|
|
createRegisterChainInstruction as createNFTBridgeRegisterChainInstruction,
|
|
createUpgradeContractInstruction as createNFTBridgeUpgradeContractInstruction,
|
|
} from "@certusone/wormhole-sdk/lib/cjs/solana/nftBridge";
|
|
|
|
export async function execute_solana(
|
|
v: VAA<Payload>,
|
|
vaa: Buffer,
|
|
network: "MAINNET" | "TESTNET" | "DEVNET",
|
|
chain: SolanaChainName
|
|
) {
|
|
let ix: web3s.TransactionInstruction;
|
|
const connection = setupConnection(NETWORKS[network][chain].rpc);
|
|
const bridgeId = new web3s.PublicKey(CONTRACTS[network][chain].core);
|
|
const tokenBridgeId =
|
|
CONTRACTS[network][chain].token_bridge &&
|
|
new web3s.PublicKey(CONTRACTS[network][chain].token_bridge);
|
|
const nftBridgeId =
|
|
CONTRACTS[network][chain].nft_bridge &&
|
|
new web3s.PublicKey(CONTRACTS[network][chain].nft_bridge);
|
|
|
|
const from = web3s.Keypair.fromSecretKey(
|
|
base58.decode(NETWORKS[network][chain].key)
|
|
);
|
|
|
|
switch (v.payload.module) {
|
|
case "Core":
|
|
if (bridgeId === undefined) {
|
|
throw Error("core bridge contract is undefined");
|
|
}
|
|
switch (v.payload.type) {
|
|
case "GuardianSetUpgrade":
|
|
console.log("Submitting new guardian set");
|
|
ix = createUpgradeGuardianSetInstruction(
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "ContractUpgrade":
|
|
console.log("Upgrading core contract");
|
|
ix = createWormholeUpgradeContractInstruction(
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "RecoverChainId":
|
|
throw new Error("RecoverChainId not supported on solana")
|
|
default:
|
|
ix = impossible(v.payload);
|
|
}
|
|
break;
|
|
case "NFTBridge":
|
|
if (nftBridgeId === undefined) {
|
|
throw Error("nft bridge contract is undefined");
|
|
}
|
|
switch (v.payload.type) {
|
|
case "ContractUpgrade":
|
|
console.log("Upgrading contract");
|
|
ix = createNFTBridgeUpgradeContractInstruction(
|
|
nftBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "RecoverChainId":
|
|
throw new Error("RecoverChainId not supported on solana")
|
|
case "RegisterChain":
|
|
console.log("Registering chain");
|
|
ix = createNFTBridgeRegisterChainInstruction(
|
|
nftBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "Transfer":
|
|
throw Error("Can't redeem NFTs from CLI");
|
|
// TODO: what's the authority account? just bail for now
|
|
default:
|
|
ix = impossible(v.payload);
|
|
}
|
|
break;
|
|
case "TokenBridge":
|
|
if (tokenBridgeId === undefined) {
|
|
throw Error("token bridge contract is undefined");
|
|
}
|
|
const payload = v.payload;
|
|
switch (payload.type) {
|
|
case "ContractUpgrade":
|
|
console.log("Upgrading contract");
|
|
ix = createTokenBridgeUpgradeContractInstruction(
|
|
tokenBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "RecoverChainId":
|
|
throw new Error("RecoverChainId not supported on solana")
|
|
case "RegisterChain":
|
|
console.log("Registering chain");
|
|
ix = createTokenBridgeRegisterChainInstruction(
|
|
tokenBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "Transfer":
|
|
console.log("Completing transfer");
|
|
if (payload.tokenChain === CHAINS[chain]) {
|
|
ix = createCompleteTransferNativeInstruction(
|
|
tokenBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
} else {
|
|
ix = createCompleteTransferWrappedInstruction(
|
|
tokenBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
}
|
|
break;
|
|
case "AttestMeta":
|
|
console.log("Creating wrapped token");
|
|
ix = createCreateWrappedInstruction(
|
|
tokenBridgeId,
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa
|
|
);
|
|
break;
|
|
case "TransferWithPayload":
|
|
throw Error("Can't complete payload 3 transfer from CLI");
|
|
default:
|
|
impossible(payload);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
ix = impossible(v.payload);
|
|
}
|
|
|
|
// First upload the VAA
|
|
await postVaaSolanaWithRetry(
|
|
connection,
|
|
async (tx) => {
|
|
tx.partialSign(from);
|
|
return tx;
|
|
},
|
|
bridgeId,
|
|
from.publicKey,
|
|
vaa,
|
|
);
|
|
|
|
// Then do the actual thing
|
|
const transaction = new web3s.Transaction().add(ix);
|
|
|
|
const signature = await web3s.sendAndConfirmTransaction(
|
|
connection,
|
|
transaction,
|
|
[from],
|
|
{
|
|
skipPreflight: true,
|
|
}
|
|
);
|
|
console.log("SIGNATURE", signature);
|
|
}
|
|
|
|
function setupConnection(rpc: string): web3s.Connection {
|
|
return new web3s.Connection(rpc, "confirmed");
|
|
}
|