bridge_ui: transfer components

Change-Id: I3a8d03687d2ebff5d7654eb52bbc5678c7e96bb8
This commit is contained in:
Reisen 2021-08-30 10:32:31 +00:00 committed by Evan Gray
parent 1fa5baedca
commit 0ef1bf4374
13 changed files with 141 additions and 89 deletions

View File

@ -22,7 +22,7 @@ const mainnet = {
const localnet = {
name: "localnet",
chainID: "localnet",
lcd: TERRA_HOST,
lcd: TERRA_HOST.URL,
};
const walletConnectChainIds: Record<number, NetworkInfo> = {

View File

@ -6,6 +6,7 @@ import {
} from "@certusone/wormhole-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
import { useConnectedWallet } from "@terra-money/wallet-provider";
import { LCDClient } from "@terra-money/terra.js";
import { formatUnits } from "ethers/lib/utils";
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
@ -21,7 +22,7 @@ import {
setSourceParsedTokenAccount,
setTargetParsedTokenAccount,
} from "../store/transferSlice";
import { SOLANA_HOST } from "../utils/consts";
import { SOLANA_HOST, TERRA_HOST } from "../utils/consts";
import { createParsedTokenAccount } from "./useGetSourceParsedTokenAccounts";
/**
@ -47,6 +48,7 @@ function useGetBalanceEffect(sourceOrTarget: "source" | "target") {
const solanaWallet = useSolanaWallet();
const solPK = solanaWallet?.publicKey;
const terraWallet = useConnectedWallet();
const lcd = new LCDClient(TERRA_HOST);
const { provider, signerAddress } = useEthereumProvider();
useEffect(() => {
// source is now handled by getsourceparsedtokenaccounts
@ -59,9 +61,29 @@ function useGetBalanceEffect(sourceOrTarget: "source" | "target") {
let cancelled = false;
if (lookupChain === CHAIN_ID_TERRA && terraWallet) {
lcd.bank.balance(terraWallet.terraAddress).then((value) => {
console.log(lookupAsset);
console.log(value.toIntCoins());
});
dispatch(
setSourceParsedTokenAccount(
createParsedTokenAccount("", "", "0", 0, 0, "0")
setAction(
// TODO: Replace with the following once LCD lookup in place.
// createParsedTokenAccount(
// undefined,
// n.toString(),
// decimals,
// Number(formatUnits(n, decimals)),
// formatUnits(n, decimals)
// )
createParsedTokenAccount(
"",
"",
"100000",
5,
Number(formatUnits(100000, 5)),
formatUnits(100000, 5)
)
)
);
}

View File

@ -94,7 +94,15 @@ async function terra(
) {
dispatch(setIsCreating(true));
try {
await createWrappedOnTerra(TERRA_TOKEN_BRIDGE_ADDRESS, wallet, signedVAA);
const msg = await createWrappedOnTerra(
TERRA_TOKEN_BRIDGE_ADDRESS,
wallet.terraAddress,
signedVAA
);
await wallet.post({
msgs: [msg],
memo: "Wormhole - Create Wrapped",
});
dispatch(reset());
enqueueSnackbar("Transaction confirmed", { variant: "success" });
} catch (e) {

View File

@ -5,10 +5,10 @@ import {
postVaaSolana,
redeemOnEth,
redeemOnSolana,
redeemOnTerra,
} from "@certusone/wormhole-sdk";
import { WalletContextState } from "@solana/wallet-adapter-react";
import { Connection } from "@solana/web3.js";
import { MsgExecuteContract } from "@terra-money/terra.js";
import {
ConnectedWallet,
useConnectedWallet,
@ -96,20 +96,14 @@ async function terra(
) {
dispatch(setIsRedeeming(true));
try {
const msg = await redeemOnTerra(
TERRA_TOKEN_BRIDGE_ADDRESS,
wallet.terraAddress,
signedVAA
);
await wallet.post({
msgs: [
new MsgExecuteContract(
wallet.terraAddress,
TERRA_TOKEN_BRIDGE_ADDRESS,
{
submit_vaa: {
data: fromUint8Array(signedVAA),
},
},
{ uluna: 1000 }
),
],
memo: "Complete Transfer",
msgs: [msg],
memo: "Wormhole - Complete Transfer",
});
dispatch(reset());
enqueueSnackbar("Transaction confirmed", { variant: "success" });

View File

@ -5,15 +5,17 @@ import {
CHAIN_ID_TERRA,
getEmitterAddressEth,
getEmitterAddressSolana,
getEmitterAddressTerra,
parseSequenceFromLogEth,
parseSequenceFromLogSolana,
parseSequenceFromLogTerra,
transferFromEth,
transferFromSolana,
transferFromTerra,
} from "@certusone/wormhole-sdk";
import { WalletContextState } from "@solana/wallet-adapter-react";
import { Connection } from "@solana/web3.js";
import { MsgExecuteContract } from "@terra-money/terra.js";
import * as bech32 from "bech32";
import {
ConnectedWallet,
useConnectedWallet,
@ -162,33 +164,24 @@ async function terra(
) {
dispatch(setIsSending(true));
try {
// TODO: SDK
const msg = await transferFromTerra(
wallet.terraAddress,
TERRA_TOKEN_BRIDGE_ADDRESS,
asset,
amount,
targetChain,
targetAddress
);
const result = await wallet.post({
msgs: [
new MsgExecuteContract(
wallet.terraAddress,
TERRA_TOKEN_BRIDGE_ADDRESS,
{
initiate_transfer: {
asset: asset,
amount: amount,
recipient_chain: targetChain,
recipient: targetAddress,
fee: 1000,
nonce: 0,
},
},
{ uluna: 1000 }
),
],
memo: "Complete Transfer",
msgs: [msg],
memo: "Wormhole - Initiate Transfer",
});
enqueueSnackbar("Transaction confirmed", { variant: "success" });
console.log(result);
const sequence = parseSequenceFromLogTerra(result);
console.log(sequence);
const emitterAddress = await getEmitterAddressSolana(
SOL_TOKEN_BRIDGE_ADDRESS
const emitterAddress = await getEmitterAddressTerra(
TERRA_TOKEN_BRIDGE_ADDRESS
);
console.log(emitterAddress);
enqueueSnackbar("Fetching VAA", { variant: "info" });

View File

@ -82,7 +82,7 @@ function useSyncTargetAddress(shouldFire: boolean) {
setTargetAddressHex(
uint8ArrayToHex(
zeroPad(
new Uint8Array(bech32.decode(terraWallet.walletAddress).words),
new Uint8Array(bech32.fromWords(bech32.decode(terraWallet.walletAddress).words)),
32
)
)

View File

@ -94,6 +94,7 @@ export const selectTransferIsSourceComplete = (state: RootState) =>
state.transfer.sourceParsedTokenAccount.decimals
)
);
// TODO: check wrapped asset exists or is native transfer
export const selectTransferIsTargetComplete = (state: RootState) =>
selectTransferIsSourceComplete(state) &&

View File

@ -55,8 +55,11 @@ export const SOLANA_HOST =
process.env.REACT_APP_CLUSTER === "testnet"
? clusterApiUrl("testnet")
: "http://localhost:8899";
export const TERRA_HOST = "http://localhost:1317";
export const TERRA_HOST = {
URL: "http://localhost:1317",
chainID: "columbus-4",
name: "localterra",
};
export const ETH_TEST_TOKEN_ADDRESS = getAddress(
process.env.REACT_APP_CLUSTER === "testnet"
? "0xcEE940033DA197F551BBEdED7F4aA55Ee55C582B"

View File

@ -2,15 +2,19 @@ import {
ChainId,
CHAIN_ID_SOLANA,
getForeignAssetEth as getForeignAssetEthTx,
getForeignAssetSol as getForeignAssetSolTx,
getForeignAssetSolana as getForeignAssetSolanaTx,
getForeignAssetTerra as getForeignAssetTerraTx,
} from "@certusone/wormhole-sdk";
import { Connection, PublicKey } from "@solana/web3.js";
import { ethers } from "ethers";
import { arrayify, isHexString, zeroPad } from "ethers/lib/utils";
import { LCDClient } from "@terra-money/terra.js";
import {
ETH_TOKEN_BRIDGE_ADDRESS,
SOLANA_HOST,
TERRA_HOST,
SOL_TOKEN_BRIDGE_ADDRESS,
TERRA_TOKEN_BRIDGE_ADDRESS,
} from "./consts";
export async function getForeignAssetEth(
@ -49,7 +53,7 @@ export async function getForeignAssetSol(
);
// TODO: share connection in context?
const connection = new Connection(SOLANA_HOST, "confirmed");
return await getForeignAssetSolTx(
return await getForeignAssetSolanaTx(
connection,
SOL_TOKEN_BRIDGE_ADDRESS,
originChain,
@ -67,5 +71,21 @@ export async function getForeignAssetTerra(
originChain: ChainId,
originAsset: string
) {
return null;
try {
const originAssetBytes = zeroPad(
originChain === CHAIN_ID_SOLANA
? new PublicKey(originAsset).toBytes()
: arrayify(originAsset),
32
);
const lcd = new LCDClient(TERRA_HOST);
return await getForeignAssetTerraTx(
TERRA_TOKEN_BRIDGE_ADDRESS,
lcd,
originChain,
originAssetBytes
);
} catch (e) {
return ethers.constants.AddressZero;
}
}

View File

@ -19,27 +19,19 @@ export async function createWrappedOnEth(
export async function createWrappedOnTerra(
tokenBridgeAddress: string,
wallet: TerraConnectedWallet,
signedVAA: Uint8Array,
walletAddress: string,
signedVAA: Uint8Array
) {
console.log(tokenBridgeAddress);
console.log(wallet.terraAddress);
console.log(signedVAA);
await wallet.post({
msgs: [
new MsgExecuteContract(
wallet.terraAddress,
tokenBridgeAddress,
{
submit_vaa: {
data: fromUint8Array(signedVAA),
},
},
{ uluna: 1000 }
),
],
memo: "Create Wrapped",
});
return new MsgExecuteContract(
walletAddress,
tokenBridgeAddress,
{
submit_vaa: {
data: fromUint8Array(signedVAA),
},
},
{ uluna: 1000 }
);
}
export async function createWrappedOnSolana(

View File

@ -50,7 +50,7 @@ export async function getForeignAssetTerra(
* @param originAsset zero pad to 32 bytes
* @returns
*/
export async function getForeignAssetSol(
export async function getForeignAssetSolana(
connection: Connection,
tokenBridgeAddress: string,
originChain: ChainId,

View File

@ -1,4 +1,11 @@
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
Token,
TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import { MsgExecuteContract } from "@terra-money/terra.js";
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
import { fromUint8Array } from "js-base64";
import { ethers } from "ethers";
import { Bridge__factory } from "../ethers-contracts";
import { ixFromRust } from "../solana";
@ -15,6 +22,23 @@ export async function redeemOnEth(
return receipt;
}
export async function redeemOnTerra(
tokenBridgeAddress: string,
walletAddress: string,
signedVAA: Uint8Array
) {
return new MsgExecuteContract(
walletAddress,
tokenBridgeAddress,
{
submit_vaa: {
data: fromUint8Array(signedVAA),
},
},
{ uluna: 1000 }
);
}
export async function redeemOnSolana(
connection: Connection,
bridgeAddress: string,

View File

@ -42,7 +42,7 @@ export async function transferFromEth(
}
export async function transferFromTerra(
wallet: TerraConnectedWallet,
walletAddress: string,
tokenBridgeAddress: string,
tokenAddress: string,
amount: ethers.BigNumberish,
@ -50,26 +50,21 @@ export async function transferFromTerra(
recipientAddress: Uint8Array
) {
const nonce = Math.round(Math.random() * 100000);
return await wallet.post({
msgs: [
new MsgExecuteContract(
wallet.terraAddress,
tokenBridgeAddress,
{
initiate_transfer: {
asset: tokenAddress,
amount: amount,
recipient_chain: recipientChain,
recipient: recipientAddress,
fee: 1000,
nonce: nonce,
},
},
{ uluna: 10000 }
),
],
memo: "Complete Transfer",
});
return new MsgExecuteContract(
walletAddress,
tokenBridgeAddress,
{
initiate_transfer: {
asset: tokenAddress,
amount: amount,
recipient_chain: recipientChain,
recipient: recipientAddress,
fee: 1000,
nonce: nonce,
},
},
{ uluna: 10000 }
);
}
export async function transferFromSolana(