bridge_ui: wrapped to wrapped
Change-Id: Icb12978ce7be6cc468d650039f508fc8ad19babe
This commit is contained in:
parent
a79ef81721
commit
42702dfbe8
|
@ -10,29 +10,32 @@ import {
|
||||||
} from "../../store/attestSlice";
|
} from "../../store/attestSlice";
|
||||||
import {
|
import {
|
||||||
selectAttestSignedVAAHex,
|
selectAttestSignedVAAHex,
|
||||||
selectTransferSourceAsset,
|
selectTransferOriginAsset,
|
||||||
selectTransferSourceChain,
|
selectTransferOriginChain,
|
||||||
selectTransferTargetChain,
|
selectTransferTargetChain,
|
||||||
} from "../../store/selectors";
|
} from "../../store/selectors";
|
||||||
|
import { hexToNativeString } from "../../utils/array";
|
||||||
|
|
||||||
export default function RegisterNowButton() {
|
export default function RegisterNowButton() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const sourceChain = useSelector(selectTransferSourceChain);
|
const originChain = useSelector(selectTransferOriginChain);
|
||||||
const sourceAsset = useSelector(selectTransferSourceAsset);
|
const originAsset = useSelector(selectTransferOriginAsset);
|
||||||
const targetChain = useSelector(selectTransferTargetChain);
|
const targetChain = useSelector(selectTransferTargetChain);
|
||||||
// user might be in the middle of a different attest
|
// user might be in the middle of a different attest
|
||||||
const signedVAAHex = useSelector(selectAttestSignedVAAHex);
|
const signedVAAHex = useSelector(selectAttestSignedVAAHex);
|
||||||
const canSwitch = sourceAsset && !signedVAAHex;
|
const canSwitch = originChain && originAsset && !signedVAAHex;
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
if (sourceAsset && canSwitch) {
|
const nativeAsset =
|
||||||
dispatch(setSourceChain(sourceChain));
|
originChain && hexToNativeString(originAsset, originChain);
|
||||||
dispatch(setSourceAsset(sourceAsset));
|
if (originChain && originAsset && nativeAsset && canSwitch) {
|
||||||
|
dispatch(setSourceChain(originChain));
|
||||||
|
dispatch(setSourceAsset(nativeAsset));
|
||||||
dispatch(setTargetChain(targetChain));
|
dispatch(setTargetChain(targetChain));
|
||||||
dispatch(setStep(2));
|
dispatch(setStep(2));
|
||||||
history.push("/register");
|
history.push("/register");
|
||||||
}
|
}
|
||||||
}, [dispatch, canSwitch, sourceChain, sourceAsset, targetChain, history]);
|
}, [dispatch, canSwitch, originChain, originAsset, targetChain, history]);
|
||||||
if (!canSwitch) return null;
|
if (!canSwitch) return null;
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const SolanaWalletProvider: FC = (props) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WalletProvider wallets={wallets} autoConnect>
|
<WalletProvider wallets={wallets}>
|
||||||
<WalletDialogProvider>{props.children}</WalletDialogProvider>
|
<WalletDialogProvider>{props.children}</WalletDialogProvider>
|
||||||
</WalletProvider>
|
</WalletProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,8 +10,6 @@ import {
|
||||||
selectTransferIsSourceAssetWormholeWrapped,
|
selectTransferIsSourceAssetWormholeWrapped,
|
||||||
selectTransferOriginAsset,
|
selectTransferOriginAsset,
|
||||||
selectTransferOriginChain,
|
selectTransferOriginChain,
|
||||||
selectTransferSourceAsset,
|
|
||||||
selectTransferSourceChain,
|
|
||||||
selectTransferTargetChain,
|
selectTransferTargetChain,
|
||||||
} from "../store/selectors";
|
} from "../store/selectors";
|
||||||
import { setTargetAsset } from "../store/transferSlice";
|
import { setTargetAsset } from "../store/transferSlice";
|
||||||
|
@ -24,8 +22,6 @@ import {
|
||||||
|
|
||||||
function useFetchTargetAsset() {
|
function useFetchTargetAsset() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const sourceChain = useSelector(selectTransferSourceChain);
|
|
||||||
const sourceAsset = useSelector(selectTransferSourceAsset);
|
|
||||||
const isSourceAssetWormholeWrapped = useSelector(
|
const isSourceAssetWormholeWrapped = useSelector(
|
||||||
selectTransferIsSourceAssetWormholeWrapped
|
selectTransferIsSourceAssetWormholeWrapped
|
||||||
);
|
);
|
||||||
|
@ -33,7 +29,6 @@ function useFetchTargetAsset() {
|
||||||
const originAsset = useSelector(selectTransferOriginAsset);
|
const originAsset = useSelector(selectTransferOriginAsset);
|
||||||
const targetChain = useSelector(selectTransferTargetChain);
|
const targetChain = useSelector(selectTransferTargetChain);
|
||||||
const { provider } = useEthereumProvider();
|
const { provider } = useEthereumProvider();
|
||||||
// TODO: this may not cover wrapped to wrapped, should always use origin?
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSourceAssetWormholeWrapped && originChain === targetChain) {
|
if (isSourceAssetWormholeWrapped && originChain === targetChain) {
|
||||||
dispatch(setTargetAsset(hexToNativeString(originAsset, originChain)));
|
dispatch(setTargetAsset(hexToNativeString(originAsset, originChain)));
|
||||||
|
@ -43,19 +38,24 @@ function useFetchTargetAsset() {
|
||||||
dispatch(setTargetAsset(undefined));
|
dispatch(setTargetAsset(undefined));
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
(async () => {
|
(async () => {
|
||||||
if (targetChain === CHAIN_ID_ETH && provider && sourceAsset) {
|
if (
|
||||||
|
targetChain === CHAIN_ID_ETH &&
|
||||||
|
provider &&
|
||||||
|
originChain &&
|
||||||
|
originAsset
|
||||||
|
) {
|
||||||
const asset = await getForeignAssetEth(
|
const asset = await getForeignAssetEth(
|
||||||
provider,
|
provider,
|
||||||
sourceChain,
|
originChain,
|
||||||
sourceAsset
|
originAsset
|
||||||
);
|
);
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
dispatch(setTargetAsset(asset));
|
dispatch(setTargetAsset(asset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targetChain === CHAIN_ID_SOLANA && sourceAsset) {
|
if (targetChain === CHAIN_ID_SOLANA && originChain && originAsset) {
|
||||||
try {
|
try {
|
||||||
const asset = await getForeignAssetSol(sourceChain, sourceAsset);
|
const asset = await getForeignAssetSol(originChain, originAsset);
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
dispatch(setTargetAsset(asset));
|
dispatch(setTargetAsset(asset));
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,9 @@ function useFetchTargetAsset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targetChain === CHAIN_ID_TERRA && sourceAsset) {
|
if (targetChain === CHAIN_ID_TERRA && originChain && originAsset) {
|
||||||
try {
|
try {
|
||||||
const asset = await getForeignAssetTerra(sourceChain, sourceAsset);
|
const asset = await getForeignAssetTerra(originChain, originAsset);
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
dispatch(setTargetAsset(asset));
|
dispatch(setTargetAsset(asset));
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,6 @@ function useFetchTargetAsset() {
|
||||||
originChain,
|
originChain,
|
||||||
originAsset,
|
originAsset,
|
||||||
targetChain,
|
targetChain,
|
||||||
sourceChain,
|
|
||||||
sourceAsset,
|
|
||||||
provider,
|
provider,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ export const transferSlice = createSlice({
|
||||||
state.targetAddressHex = undefined;
|
state.targetAddressHex = undefined;
|
||||||
// clear targetAsset so that components that fire before useFetchTargetAsset don't get stale data
|
// clear targetAsset so that components that fire before useFetchTargetAsset don't get stale data
|
||||||
state.targetAsset = undefined;
|
state.targetAsset = undefined;
|
||||||
|
state.targetParsedTokenAccount = undefined;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setSourceWormholeWrappedInfo: (
|
setSourceWormholeWrappedInfo: (
|
||||||
|
@ -158,6 +159,7 @@ export const transferSlice = createSlice({
|
||||||
state.targetAddressHex = undefined;
|
state.targetAddressHex = undefined;
|
||||||
// clear targetAsset so that components that fire before useFetchTargetAsset don't get stale data
|
// clear targetAsset so that components that fire before useFetchTargetAsset don't get stale data
|
||||||
state.targetAsset = undefined;
|
state.targetAsset = undefined;
|
||||||
|
state.targetParsedTokenAccount = undefined;
|
||||||
if (state.sourceChain === action.payload) {
|
if (state.sourceChain === action.payload) {
|
||||||
state.sourceChain = prevTargetChain;
|
state.sourceChain = prevTargetChain;
|
||||||
state.activeStep = 0;
|
state.activeStep = 0;
|
||||||
|
@ -196,6 +198,7 @@ export const transferSlice = createSlice({
|
||||||
},
|
},
|
||||||
setRedeemTx: (state, action: PayloadAction<Transaction>) => {
|
setRedeemTx: (state, action: PayloadAction<Transaction>) => {
|
||||||
state.redeemTx = action.payload;
|
state.redeemTx = action.payload;
|
||||||
|
state.isRedeeming = false;
|
||||||
},
|
},
|
||||||
reset: (state) => ({
|
reset: (state) => ({
|
||||||
...initialState,
|
...initialState,
|
||||||
|
|
|
@ -12,8 +12,9 @@ export const uint8ArrayToHex = (a: Uint8Array) =>
|
||||||
Buffer.from(a).toString("hex");
|
Buffer.from(a).toString("hex");
|
||||||
export const hexToUint8Array = (h: string) =>
|
export const hexToUint8Array = (h: string) =>
|
||||||
new Uint8Array(Buffer.from(h, "hex"));
|
new Uint8Array(Buffer.from(h, "hex"));
|
||||||
export const hexToNativeString = (h: string | undefined, c: ChainId) =>
|
export const hexToNativeString = (h: string | undefined, c: ChainId) => {
|
||||||
!h
|
try {
|
||||||
|
return !h
|
||||||
? undefined
|
? undefined
|
||||||
: c === CHAIN_ID_SOLANA
|
: c === CHAIN_ID_SOLANA
|
||||||
? new PublicKey(hexToUint8Array(h)).toString()
|
? new PublicKey(hexToUint8Array(h)).toString()
|
||||||
|
@ -22,3 +23,6 @@ export const hexToNativeString = (h: string | undefined, c: ChainId) =>
|
||||||
: c === CHAIN_ID_TERRA
|
: c === CHAIN_ID_TERRA
|
||||||
? humanAddress(hexToUint8Array(h.substr(24))) // terra expects 20 bytes, not 32
|
? humanAddress(hexToUint8Array(h.substr(24))) // terra expects 20 bytes, not 32
|
||||||
: h;
|
: h;
|
||||||
|
} catch (e) {}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import {
|
import {
|
||||||
ChainId,
|
ChainId,
|
||||||
CHAIN_ID_SOLANA,
|
|
||||||
getForeignAssetEth as getForeignAssetEthTx,
|
getForeignAssetEth as getForeignAssetEthTx,
|
||||||
getForeignAssetSolana as getForeignAssetSolanaTx,
|
getForeignAssetSolana as getForeignAssetSolanaTx,
|
||||||
getForeignAssetTerra as getForeignAssetTerraTx,
|
getForeignAssetTerra as getForeignAssetTerraTx,
|
||||||
} from "@certusone/wormhole-sdk";
|
} from "@certusone/wormhole-sdk";
|
||||||
import { Connection, PublicKey } from "@solana/web3.js";
|
import { Connection } from "@solana/web3.js";
|
||||||
import { ethers } from "ethers";
|
|
||||||
import { arrayify, isHexString, zeroPad } from "ethers/lib/utils";
|
|
||||||
import { LCDClient } from "@terra-money/terra.js";
|
import { LCDClient } from "@terra-money/terra.js";
|
||||||
|
import { ethers } from "ethers";
|
||||||
|
import { hexToUint8Array } from "./array";
|
||||||
import {
|
import {
|
||||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||||
SOLANA_HOST,
|
SOLANA_HOST,
|
||||||
TERRA_HOST,
|
|
||||||
SOL_TOKEN_BRIDGE_ADDRESS,
|
SOL_TOKEN_BRIDGE_ADDRESS,
|
||||||
|
TERRA_HOST,
|
||||||
TERRA_TOKEN_BRIDGE_ADDRESS,
|
TERRA_TOKEN_BRIDGE_ADDRESS,
|
||||||
} from "./consts";
|
} from "./consts";
|
||||||
|
|
||||||
|
@ -23,21 +22,14 @@ export async function getForeignAssetEth(
|
||||||
originAsset: string
|
originAsset: string
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
// TODO: address conversion may be more complex than this
|
|
||||||
const originAssetBytes = zeroPad(
|
|
||||||
originChain === CHAIN_ID_SOLANA
|
|
||||||
? new PublicKey(originAsset).toBytes()
|
|
||||||
: arrayify(originAsset),
|
|
||||||
32
|
|
||||||
);
|
|
||||||
return await getForeignAssetEthTx(
|
return await getForeignAssetEthTx(
|
||||||
ETH_TOKEN_BRIDGE_ADDRESS,
|
ETH_TOKEN_BRIDGE_ADDRESS,
|
||||||
provider,
|
provider,
|
||||||
originChain,
|
originChain,
|
||||||
originAssetBytes
|
hexToUint8Array(originAsset)
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ethers.constants.AddressZero;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,18 +37,12 @@ export async function getForeignAssetSol(
|
||||||
originChain: ChainId,
|
originChain: ChainId,
|
||||||
originAsset: string
|
originAsset: string
|
||||||
) {
|
) {
|
||||||
if (!isHexString(originAsset)) return null;
|
|
||||||
// TODO: address conversion may be more complex than this
|
|
||||||
const originAssetBytes = zeroPad(
|
|
||||||
arrayify(originAsset, { hexPad: "left" }),
|
|
||||||
32
|
|
||||||
);
|
|
||||||
const connection = new Connection(SOLANA_HOST, "confirmed");
|
const connection = new Connection(SOLANA_HOST, "confirmed");
|
||||||
return await getForeignAssetSolanaTx(
|
return await getForeignAssetSolanaTx(
|
||||||
connection,
|
connection,
|
||||||
SOL_TOKEN_BRIDGE_ADDRESS,
|
SOL_TOKEN_BRIDGE_ADDRESS,
|
||||||
originChain,
|
originChain,
|
||||||
originAssetBytes
|
hexToUint8Array(originAsset)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,21 +57,14 @@ export async function getForeignAssetTerra(
|
||||||
originAsset: string
|
originAsset: string
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const originAssetBytes = zeroPad(
|
|
||||||
originChain === CHAIN_ID_SOLANA
|
|
||||||
? new PublicKey(originAsset).toBytes()
|
|
||||||
: arrayify(originAsset),
|
|
||||||
32
|
|
||||||
);
|
|
||||||
const lcd = new LCDClient(TERRA_HOST);
|
const lcd = new LCDClient(TERRA_HOST);
|
||||||
return await getForeignAssetTerraTx(
|
return await getForeignAssetTerraTx(
|
||||||
TERRA_TOKEN_BRIDGE_ADDRESS,
|
TERRA_TOKEN_BRIDGE_ADDRESS,
|
||||||
lcd,
|
lcd,
|
||||||
originChain,
|
originChain,
|
||||||
originAssetBytes
|
hexToUint8Array(originAsset)
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: better return for this
|
return null;
|
||||||
return ethers.constants.AddressZero;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ export async function getForeignAssetEth(
|
||||||
try {
|
try {
|
||||||
return await tokenBridge.wrappedAsset(originChain, originAsset);
|
return await tokenBridge.wrappedAsset(originChain, originAsset);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return ethers.constants.AddressZero;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,13 +33,20 @@ export async function getForeignAssetTerra(
|
||||||
originChain: ChainId,
|
originChain: ChainId,
|
||||||
originAsset: Uint8Array
|
originAsset: Uint8Array
|
||||||
) {
|
) {
|
||||||
const result: { address: string } = await client.wasm.contractQuery(tokenBridgeAddress, {
|
try {
|
||||||
|
const result: { address: string } = await client.wasm.contractQuery(
|
||||||
|
tokenBridgeAddress,
|
||||||
|
{
|
||||||
wrapped_registry: {
|
wrapped_registry: {
|
||||||
chain: originChain,
|
chain: originChain,
|
||||||
address: fromUint8Array(originAsset),
|
address: fromUint8Array(originAsset),
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
);
|
||||||
return result.address;
|
return result.address;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,7 +51,7 @@ export async function getOriginalAssetEth(
|
||||||
return {
|
return {
|
||||||
isWrapped: false,
|
isWrapped: false,
|
||||||
chainId: CHAIN_ID_ETH,
|
chainId: CHAIN_ID_ETH,
|
||||||
assetAddress: arrayify(wrappedAddress),
|
assetAddress: zeroPad(arrayify(wrappedAddress), 32),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ export async function getOriginalAssetTerra(
|
||||||
client: LCDClient,
|
client: LCDClient,
|
||||||
wrappedAddress: string
|
wrappedAddress: string
|
||||||
): Promise<WormholeWrappedInfo> {
|
): Promise<WormholeWrappedInfo> {
|
||||||
|
try {
|
||||||
const result: {
|
const result: {
|
||||||
asset_address: string;
|
asset_address: string;
|
||||||
asset_chain: ChainId;
|
asset_chain: ChainId;
|
||||||
|
@ -70,9 +71,12 @@ export async function getOriginalAssetTerra(
|
||||||
return {
|
return {
|
||||||
isWrapped: true,
|
isWrapped: true,
|
||||||
chainId: result.asset_chain,
|
chainId: result.asset_chain,
|
||||||
assetAddress: new Uint8Array(Buffer.from(result.asset_address, "base64")),
|
assetAddress: new Uint8Array(
|
||||||
|
Buffer.from(result.asset_address, "base64")
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
} catch (e) {}
|
||||||
return {
|
return {
|
||||||
isWrapped: false,
|
isWrapped: false,
|
||||||
chainId: CHAIN_ID_TERRA,
|
chainId: CHAIN_ID_TERRA,
|
||||||
|
@ -114,6 +118,13 @@ export async function getOriginalAssetSol(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
isWrapped: false,
|
||||||
|
chainId: CHAIN_ID_SOLANA,
|
||||||
|
assetAddress: new PublicKey(mintAddress).toBytes(),
|
||||||
|
};
|
||||||
|
} catch (e) {}
|
||||||
return {
|
return {
|
||||||
isWrapped: false,
|
isWrapped: false,
|
||||||
chainId: CHAIN_ID_SOLANA,
|
chainId: CHAIN_ID_SOLANA,
|
||||||
|
|
Loading…
Reference in New Issue