137 lines
4.3 KiB
TypeScript
137 lines
4.3 KiB
TypeScript
import { ethers } from "ethers";
|
|
import { Bridge__factory } from "../ethers-contracts";
|
|
import {
|
|
ETH_TOKEN_BRIDGE_ADDRESS,
|
|
SOL_BRIDGE_ADDRESS,
|
|
SOL_TOKEN_BRIDGE_ADDRESS,
|
|
SOLANA_HOST,
|
|
} from "./consts";
|
|
import Wallet from "@project-serum/sol-wallet-adapter";
|
|
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
|
|
import { postVaa } from "./postVaa";
|
|
import {
|
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
Token,
|
|
TOKEN_PROGRAM_ID,
|
|
} from "@solana/spl-token";
|
|
import { CHAIN_ID_ETH, CHAIN_ID_SOLANA } from "@certusone/wormhole-sdk";
|
|
import { ixFromRust } from "@certusone/wormhole-sdk";
|
|
|
|
export async function redeemOnEth(
|
|
provider: ethers.providers.Web3Provider | undefined,
|
|
signer: ethers.Signer | undefined,
|
|
signedVAA: Uint8Array
|
|
) {
|
|
console.log(provider, signer, signedVAA);
|
|
if (!provider || !signer) return;
|
|
console.log("completing transfer");
|
|
const bridge = Bridge__factory.connect(ETH_TOKEN_BRIDGE_ADDRESS, signer);
|
|
const v = await bridge.completeTransfer(signedVAA);
|
|
const receipt = await v.wait();
|
|
console.log(receipt);
|
|
}
|
|
|
|
export async function redeemOnSolana(
|
|
wallet: Wallet | undefined,
|
|
payerAddress: string | undefined, //TODO: we may not need this since we have wallet
|
|
signedVAA: Uint8Array,
|
|
isSolanaNative: boolean,
|
|
mintAddress?: string // TODO: read the signedVAA and create the account if it doesn't exist
|
|
) {
|
|
if (!wallet || !wallet.publicKey || !payerAddress) return;
|
|
console.log("completing transfer");
|
|
console.log("PROGRAM:", SOL_TOKEN_BRIDGE_ADDRESS);
|
|
console.log("BRIDGE:", SOL_BRIDGE_ADDRESS);
|
|
console.log("PAYER:", payerAddress);
|
|
console.log("VAA:", signedVAA);
|
|
// TODO: share connection in context?
|
|
const connection = new Connection(SOLANA_HOST, "confirmed");
|
|
const { complete_transfer_wrapped_ix, complete_transfer_native_ix } =
|
|
await import("token-bridge");
|
|
|
|
await postVaa(
|
|
connection,
|
|
wallet,
|
|
SOL_BRIDGE_ADDRESS,
|
|
payerAddress,
|
|
Buffer.from(signedVAA)
|
|
);
|
|
console.log(Buffer.from(signedVAA).toString("hex"));
|
|
const ixs = [];
|
|
if (isSolanaNative) {
|
|
console.log("COMPLETE TRANSFER NATIVE");
|
|
ixs.push(
|
|
ixFromRust(
|
|
complete_transfer_native_ix(
|
|
SOL_TOKEN_BRIDGE_ADDRESS,
|
|
SOL_BRIDGE_ADDRESS,
|
|
payerAddress,
|
|
signedVAA
|
|
)
|
|
)
|
|
);
|
|
} else {
|
|
// TODO: we should always do this, they could buy wrapped somewhere else and transfer it back for the first time, but again, do it based on vaa
|
|
if (mintAddress) {
|
|
console.log("CHECK ASSOCIATED TOKEN ACCOUNT FOR", mintAddress);
|
|
const mintPublicKey = new PublicKey(mintAddress);
|
|
const associatedAddress = await Token.getAssociatedTokenAddress(
|
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
TOKEN_PROGRAM_ID,
|
|
mintPublicKey,
|
|
wallet.publicKey
|
|
);
|
|
const associatedAddressInfo = await connection.getAccountInfo(
|
|
associatedAddress
|
|
);
|
|
console.log(
|
|
"CREATE ASSOCIATED TOKEN ACCOUNT",
|
|
associatedAddress.toString()
|
|
);
|
|
if (!associatedAddressInfo) {
|
|
ixs.push(
|
|
await Token.createAssociatedTokenAccountInstruction(
|
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
TOKEN_PROGRAM_ID,
|
|
mintPublicKey,
|
|
associatedAddress,
|
|
wallet.publicKey,
|
|
wallet.publicKey
|
|
)
|
|
);
|
|
}
|
|
}
|
|
console.log("COMPLETE TRANSFER WRAPPED");
|
|
ixs.push(
|
|
ixFromRust(
|
|
complete_transfer_wrapped_ix(
|
|
SOL_TOKEN_BRIDGE_ADDRESS,
|
|
SOL_BRIDGE_ADDRESS,
|
|
payerAddress,
|
|
signedVAA
|
|
)
|
|
)
|
|
);
|
|
}
|
|
const transaction = new Transaction().add(...ixs);
|
|
const { blockhash } = await connection.getRecentBlockhash();
|
|
transaction.recentBlockhash = blockhash;
|
|
transaction.feePayer = new PublicKey(payerAddress);
|
|
// Sign transaction, broadcast, and confirm
|
|
const signed = await wallet.signTransaction(transaction);
|
|
console.log("SIGNED", signed);
|
|
const txid = await connection.sendRawTransaction(signed.serialize());
|
|
console.log("SENT", txid);
|
|
const conf = await connection.confirmTransaction(txid);
|
|
console.log("CONFIRMED", conf);
|
|
const info = await connection.getTransaction(txid);
|
|
console.log("INFO", info);
|
|
}
|
|
|
|
const redeemOn = {
|
|
[CHAIN_ID_ETH]: redeemOnEth,
|
|
[CHAIN_ID_SOLANA]: redeemOnSolana,
|
|
};
|
|
|
|
export default redeemOn;
|