bridge_ui: terra recovery
Change-Id: I0ae0da49a1d30f2f1a01b3dfd2cdf38f8667d6bf
This commit is contained in:
parent
ba9112ff14
commit
7b4a7ea17c
|
@ -163,7 +163,7 @@ export default function SolanaSourceTokenSelector(
|
|||
}}
|
||||
getOptionLabel={(option) => {
|
||||
const symbol = getSymbol(option);
|
||||
return `${symbol ? symbol : "Unknown"} ( Account: ${shortenAddress(
|
||||
return `${symbol ? symbol : "Unknown"} (Account: ${shortenAddress(
|
||||
option.publicKey
|
||||
)}, Mint: ${shortenAddress(option.mintKey)})`;
|
||||
}}
|
||||
|
|
|
@ -3,11 +3,14 @@ import {
|
|||
CHAIN_ID_BSC,
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_SOLANA,
|
||||
CHAIN_ID_TERRA,
|
||||
getEmitterAddressEth,
|
||||
getEmitterAddressSolana,
|
||||
getEmitterAddressTerra,
|
||||
getSignedVAA,
|
||||
parseSequenceFromLogEth,
|
||||
parseSequenceFromLogSolana,
|
||||
parseSequenceFromLogTerra,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
Box,
|
||||
|
@ -26,6 +29,7 @@ import {
|
|||
import { Restore } from "@material-ui/icons";
|
||||
import { Alert } from "@material-ui/lab";
|
||||
import { Connection } from "@solana/web3.js";
|
||||
import { LCDClient } from "@terra-money/terra.js";
|
||||
import { BigNumber, ethers } from "ethers";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
@ -50,6 +54,8 @@ import {
|
|||
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||
SOLANA_HOST,
|
||||
SOL_TOKEN_BRIDGE_ADDRESS,
|
||||
TERRA_HOST,
|
||||
TERRA_TOKEN_BRIDGE_ADDRESS,
|
||||
WORMHOLE_RPC_HOST,
|
||||
} from "../../utils/consts";
|
||||
import KeyAndBalance from "../KeyAndBalance";
|
||||
|
@ -104,6 +110,31 @@ async function solana(tx: string) {
|
|||
return "";
|
||||
}
|
||||
|
||||
async function terra(tx: string) {
|
||||
try {
|
||||
const lcd = new LCDClient(TERRA_HOST);
|
||||
const info = await lcd.tx.txInfo(tx);
|
||||
const sequence = parseSequenceFromLogTerra(info);
|
||||
if (!sequence) {
|
||||
throw new Error("Sequence not found");
|
||||
}
|
||||
const emitterAddress = await getEmitterAddressTerra(
|
||||
TERRA_TOKEN_BRIDGE_ADDRESS
|
||||
);
|
||||
console.log(emitterAddress);
|
||||
const { vaaBytes } = await getSignedVAA(
|
||||
WORMHOLE_RPC_HOST,
|
||||
CHAIN_ID_TERRA,
|
||||
emitterAddress,
|
||||
sequence
|
||||
);
|
||||
return uint8ArrayToHex(vaaBytes);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// 0 u256 amount
|
||||
// 32 [u8; 32] token_address
|
||||
// 64 u16 token_chain
|
||||
|
@ -153,6 +184,13 @@ function RecoveryDialogContent({ onClose }: { onClose: () => void }) {
|
|||
setRecoverySignedVAA(vaa);
|
||||
}
|
||||
})();
|
||||
} else if (recoverySourceChain === CHAIN_ID_TERRA) {
|
||||
(async () => {
|
||||
const vaa = await terra(recoverySourceTx);
|
||||
if (!cancelled) {
|
||||
setRecoverySignedVAA(vaa);
|
||||
}
|
||||
})();
|
||||
}
|
||||
return () => {
|
||||
cancelled = true;
|
||||
|
@ -236,9 +274,7 @@ function RecoveryDialogContent({ onClose }: { onClose: () => void }) {
|
|||
fullWidth
|
||||
margin="normal"
|
||||
>
|
||||
{CHAINS.filter(
|
||||
(x) => x.id === CHAIN_ID_ETH || x.id === CHAIN_ID_SOLANA
|
||||
).map(({ id, name }) => (
|
||||
{CHAINS.map(({ id, name }) => (
|
||||
<MenuItem key={id} value={id}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
|
|
|
@ -71,6 +71,7 @@ async function eth(
|
|||
dispatch(setSignedVAAHex(uint8ArrayToHex(vaaBytes)));
|
||||
enqueueSnackbar("Fetched Signed VAA", { variant: "success" });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
enqueueSnackbar(parseError(e), { variant: "error" });
|
||||
dispatch(setIsSending(false));
|
||||
}
|
||||
|
@ -114,6 +115,7 @@ async function solana(
|
|||
dispatch(setSignedVAAHex(uint8ArrayToHex(vaaBytes)));
|
||||
enqueueSnackbar("Fetched Signed VAA", { variant: "success" });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
enqueueSnackbar(parseError(e), { variant: "error" });
|
||||
dispatch(setIsSending(false));
|
||||
}
|
||||
|
@ -127,14 +129,17 @@ async function terra(
|
|||
) {
|
||||
dispatch(setIsSending(true));
|
||||
try {
|
||||
const infoMaybe = await attestFromTerra(
|
||||
const result = await attestFromTerra(
|
||||
TERRA_TOKEN_BRIDGE_ADDRESS,
|
||||
wallet,
|
||||
asset
|
||||
);
|
||||
const info = await waitForTerraExecution(wallet, infoMaybe);
|
||||
const info = await waitForTerraExecution(result);
|
||||
enqueueSnackbar("Transaction confirmed", { variant: "success" });
|
||||
const sequence = parseSequenceFromLogTerra(info);
|
||||
if (!sequence) {
|
||||
throw new Error("Sequence not found");
|
||||
}
|
||||
const emitterAddress = await getEmitterAddressTerra(
|
||||
TERRA_TOKEN_BRIDGE_ADDRESS
|
||||
);
|
||||
|
@ -148,6 +153,7 @@ async function terra(
|
|||
enqueueSnackbar("Fetched Signed VAA", { variant: "success" });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
enqueueSnackbar(parseError(e), { variant: "error" });
|
||||
dispatch(setIsSending(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,9 @@ import {
|
|||
TERRA_TOKEN_BRIDGE_ADDRESS,
|
||||
} from "../utils/consts";
|
||||
import { getSignedVAAWithRetry } from "../utils/getSignedVAAWithRetry";
|
||||
import parseError from "../utils/parseError";
|
||||
import { signSendAndConfirm } from "../utils/solana";
|
||||
import { waitForTerraExecution } from "../utils/terra";
|
||||
import useTransferTargetAddressHex from "./useTransferTargetAddress";
|
||||
|
||||
async function eth(
|
||||
|
@ -86,6 +88,7 @@ async function eth(
|
|||
enqueueSnackbar("Fetched Signed VAA", { variant: "success" });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
enqueueSnackbar(parseError(e), { variant: "error" });
|
||||
dispatch(setIsSending(false));
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +151,7 @@ async function solana(
|
|||
enqueueSnackbar("Fetched Signed VAA", { variant: "success" });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
enqueueSnackbar(parseError(e), { variant: "error" });
|
||||
dispatch(setIsSending(false));
|
||||
}
|
||||
}
|
||||
|
@ -177,10 +181,15 @@ async function terra(
|
|||
msgs: [...msgs],
|
||||
memo: "Wormhole - Initiate Transfer",
|
||||
});
|
||||
enqueueSnackbar("Transaction confirmed", { variant: "success" });
|
||||
console.log(result);
|
||||
const sequence = parseSequenceFromLogTerra(result);
|
||||
const info = await waitForTerraExecution(result);
|
||||
console.log(info);
|
||||
enqueueSnackbar("Transaction confirmed", { variant: "success" });
|
||||
const sequence = parseSequenceFromLogTerra(info);
|
||||
console.log(sequence);
|
||||
if (!sequence) {
|
||||
throw new Error("Sequence not found");
|
||||
}
|
||||
const emitterAddress = await getEmitterAddressTerra(
|
||||
TERRA_TOKEN_BRIDGE_ADDRESS
|
||||
);
|
||||
|
@ -195,6 +204,7 @@ async function terra(
|
|||
dispatch(setSignedVAAHex(uint8ArrayToHex(vaaBytes)));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
enqueueSnackbar(parseError(e), { variant: "error" });
|
||||
dispatch(setIsSending(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ export async function getSignedVAAWithRetry(
|
|||
sequence
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import {
|
||||
TxResult,
|
||||
ConnectedWallet as TerraConnectedWallet,
|
||||
} from "@terra-money/wallet-provider";
|
||||
import { LCDClient } from "@terra-money/terra.js";
|
||||
import { TxResult } from "@terra-money/wallet-provider";
|
||||
import { TERRA_HOST } from "./consts";
|
||||
|
||||
// TODO: Loop txInfo for timed out transactions.
|
||||
// lcd.tx.txInfo(transaction.result.txhash);
|
||||
export async function waitForTerraExecution(
|
||||
wallet: TerraConnectedWallet,
|
||||
transaction: TxResult
|
||||
) {
|
||||
new LCDClient({
|
||||
URL: wallet.network.lcd,
|
||||
chainID: "columbus-4",
|
||||
});
|
||||
return transaction;
|
||||
export async function waitForTerraExecution(transaction: TxResult) {
|
||||
const lcd = new LCDClient(TERRA_HOST);
|
||||
let info;
|
||||
while (!info) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
try {
|
||||
info = await lcd.tx.txInfo(transaction.result.txhash);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { TransactionResponse } from "@solana/web3.js";
|
||||
import { TxInfo } from "@terra-money/terra.js";
|
||||
import { ContractReceipt } from "ethers";
|
||||
import { TxResult } from "@terra-money/wallet-provider";
|
||||
import { Implementation__factory } from "../ethers-contracts";
|
||||
|
||||
export function parseSequenceFromLogEth(
|
||||
|
@ -17,21 +17,21 @@ export function parseSequenceFromLogEth(
|
|||
return sequence.toString();
|
||||
}
|
||||
|
||||
export function parseSequenceFromLogTerra(result: TxResult): string {
|
||||
export function parseSequenceFromLogTerra(info: TxInfo): string {
|
||||
// Scan for the Sequence attribute in all the outputs of the transaction.
|
||||
// TODO: Make this not horrible.
|
||||
let sequence = "";
|
||||
const jsonLog = JSON.parse(result.result.raw_log);
|
||||
const jsonLog = JSON.parse(info.raw_log);
|
||||
jsonLog.map((row: any) => {
|
||||
row.events.map((event: any) => {
|
||||
event.attributes.map((attribute: any) => {
|
||||
if(attribute.key === "message.sequence") {
|
||||
sequence = attribute.value;
|
||||
}
|
||||
});
|
||||
row.events.map((event: any) => {
|
||||
event.attributes.map((attribute: any) => {
|
||||
if (attribute.key === "message.sequence") {
|
||||
sequence = attribute.value;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
console.log('Terra Sequence: ', sequence);
|
||||
console.log("Terra Sequence: ", sequence);
|
||||
return sequence.toString();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue