bridge_ui: set target address in state
Change-Id: Ie2f87582ffdc8da53ccc0f34721c3985d7807933
This commit is contained in:
parent
1f214029f5
commit
c33f3c0cb9
|
@ -29,6 +29,7 @@
|
|||
"@solana/wallet-base": "^0.0.1",
|
||||
"@solana/web3.js": "^1.22.0",
|
||||
"@terra-money/wallet-provider": "^1.4.0-alpha.1",
|
||||
"bech32": "^1.1.4",
|
||||
"ethers": "^5.4.1",
|
||||
"js-base64": "^3.6.1",
|
||||
"notistack": "^1.0.10",
|
||||
|
@ -57,6 +58,9 @@
|
|||
"@improbable-eng/grpc-web": "^0.14.0",
|
||||
"@solana/spl-token": "^0.1.8",
|
||||
"@solana/web3.js": "^1.24.0",
|
||||
"@terra-money/terra.js": "^1.8.10",
|
||||
"@terra-money/wallet-provider": "^1.2.4",
|
||||
"js-base64": "^3.6.1",
|
||||
"protobufjs": "^6.11.2",
|
||||
"rxjs": "^7.3.0"
|
||||
},
|
||||
|
@ -65,6 +69,7 @@
|
|||
"@typechain/ethers-v5": "^7.0.1",
|
||||
"@types/long": "^4.0.1",
|
||||
"@types/node": "^16.6.1",
|
||||
"@types/react": "^17.0.19",
|
||||
"copy-dir": "^1.3.0",
|
||||
"ethers": "^5.4.4",
|
||||
"prettier": "^2.3.2",
|
||||
|
@ -36739,6 +36744,7 @@
|
|||
"resolved": "https://registry.npmjs.org/wasm-dce/-/wasm-dce-1.0.2.tgz",
|
||||
"integrity": "sha512-Fq1+nu43ybsjSnBquLrW/cULmKs61qbv9k8ep13QUe0nABBezMoNAA+j6QY66MW0/eoDVDp1rjXDqQ2VKyS/Xg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.0.0-beta.39",
|
||||
"@babel/traverse": "^7.0.0-beta.39",
|
||||
|
@ -36752,6 +36758,7 @@
|
|||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz",
|
||||
"integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"babylon": "bin/babylon.js"
|
||||
},
|
||||
|
@ -37587,6 +37594,7 @@
|
|||
"resolved": "https://registry.npmjs.org/webassembly-floating-point-hex-parser/-/webassembly-floating-point-hex-parser-0.1.2.tgz",
|
||||
"integrity": "sha512-TUf1H++8U10+stJbFydnvrpG5Sznz5Rilez/oZlV5zI0C/e4cSxd8rALAJ8VpTvjVWxLmL3SVSJUK6Ap9AoiNg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
|
@ -37596,6 +37604,7 @@
|
|||
"resolved": "https://registry.npmjs.org/webassembly-interpreter/-/webassembly-interpreter-0.0.30.tgz",
|
||||
"integrity": "sha512-+Jdy2piEvz9T5j751mOE8+rBO12p+nNW6Fg4kJZ+zP1oUfsm+151sbAbM8AFxWTURmWCGP+r8Lxwfv3pzN1bCQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0-beta.36",
|
||||
"long": "^3.2.0",
|
||||
|
@ -37615,6 +37624,7 @@
|
|||
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
|
||||
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
|
@ -41022,11 +41032,15 @@
|
|||
"@openzeppelin/contracts": "^4.2.0",
|
||||
"@solana/spl-token": "^0.1.8",
|
||||
"@solana/web3.js": "^1.24.0",
|
||||
"@terra-money/terra.js": "^1.8.10",
|
||||
"@terra-money/wallet-provider": "^1.2.4",
|
||||
"@typechain/ethers-v5": "^7.0.1",
|
||||
"@types/long": "^4.0.1",
|
||||
"@types/node": "^16.6.1",
|
||||
"@types/react": "^17.0.19",
|
||||
"copy-dir": "^1.3.0",
|
||||
"ethers": "^5.4.4",
|
||||
"js-base64": "^3.6.1",
|
||||
"prettier": "^2.3.2",
|
||||
"protobufjs": "^6.11.2",
|
||||
"rxjs": "^7.3.0",
|
||||
|
@ -48382,7 +48396,6 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"bitcore-lib": "^8.25.10",
|
||||
"unorm": "^1.4.1"
|
||||
}
|
||||
},
|
||||
|
@ -69246,6 +69259,7 @@
|
|||
"resolved": "https://registry.npmjs.org/wasm-dce/-/wasm-dce-1.0.2.tgz",
|
||||
"integrity": "sha512-Fq1+nu43ybsjSnBquLrW/cULmKs61qbv9k8ep13QUe0nABBezMoNAA+j6QY66MW0/eoDVDp1rjXDqQ2VKyS/Xg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/core": "^7.0.0-beta.39",
|
||||
"@babel/traverse": "^7.0.0-beta.39",
|
||||
|
@ -69258,7 +69272,8 @@
|
|||
"version": "7.0.0-beta.47",
|
||||
"resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz",
|
||||
"integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -69268,8 +69283,7 @@
|
|||
"integrity": "sha512-R4s75XH+o8qM+WaRrAU9S2rbAMDzob18/S3V8R9ZoFpZkPWLAohWWlzWAp1ybeTkOuuku/X1zJtxiV0pBYxZww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.1.0",
|
||||
"wasm-dce": "^1.0.0"
|
||||
"loader-utils": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
|
@ -69991,13 +70005,15 @@
|
|||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/webassembly-floating-point-hex-parser/-/webassembly-floating-point-hex-parser-0.1.2.tgz",
|
||||
"integrity": "sha512-TUf1H++8U10+stJbFydnvrpG5Sznz5Rilez/oZlV5zI0C/e4cSxd8rALAJ8VpTvjVWxLmL3SVSJUK6Ap9AoiNg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"webassembly-interpreter": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/webassembly-interpreter/-/webassembly-interpreter-0.0.30.tgz",
|
||||
"integrity": "sha512-+Jdy2piEvz9T5j751mOE8+rBO12p+nNW6Fg4kJZ+zP1oUfsm+151sbAbM8AFxWTURmWCGP+r8Lxwfv3pzN1bCQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.0.0-beta.36",
|
||||
"long": "^3.2.0",
|
||||
|
@ -70008,7 +70024,8 @@
|
|||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
|
||||
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"@solana/wallet-base": "^0.0.1",
|
||||
"@solana/web3.js": "^1.22.0",
|
||||
"@terra-money/wallet-provider": "^1.4.0-alpha.1",
|
||||
"bech32": "^1.1.4",
|
||||
"ethers": "^5.4.1",
|
||||
"js-base64": "^3.6.1",
|
||||
"notistack": "^1.0.10",
|
||||
|
|
|
@ -63,7 +63,7 @@ function Source() {
|
|||
</TextField>
|
||||
<KeyAndBalance chainId={sourceChain} />
|
||||
<TextField
|
||||
placeholder="Asset"
|
||||
label="Asset"
|
||||
fullWidth
|
||||
className={classes.transferField}
|
||||
value={sourceAsset}
|
||||
|
|
|
@ -75,7 +75,7 @@ function Source() {
|
|||
<KeyAndBalance chainId={sourceChain} balance={uiAmountString} />
|
||||
{/* TODO: token list for eth, check own */}
|
||||
<TextField
|
||||
placeholder="Asset"
|
||||
label="Asset"
|
||||
fullWidth
|
||||
className={classes.transferField}
|
||||
value={sourceAsset}
|
||||
|
@ -83,7 +83,7 @@ function Source() {
|
|||
disabled={shouldLockFields}
|
||||
/>
|
||||
<TextField
|
||||
placeholder="Amount"
|
||||
label="Amount"
|
||||
type="number"
|
||||
fullWidth
|
||||
className={classes.transferField}
|
||||
|
|
|
@ -3,11 +3,13 @@ import { Button, makeStyles, MenuItem, TextField } from "@material-ui/core";
|
|||
import { PublicKey } from "@solana/web3.js";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import useSyncTargetAddress from "../../hooks/useSyncTargetAddress";
|
||||
import {
|
||||
selectTransferIsSourceAssetWormholeWrapped,
|
||||
selectTransferIsTargetComplete,
|
||||
selectTransferShouldLockFields,
|
||||
selectTransferSourceChain,
|
||||
selectTransferTargetAddressHex,
|
||||
selectTransferTargetAsset,
|
||||
selectTransferTargetBalanceString,
|
||||
selectTransferTargetChain,
|
||||
|
@ -32,6 +34,7 @@ function Target() {
|
|||
[sourceChain]
|
||||
);
|
||||
const targetChain = useSelector(selectTransferTargetChain);
|
||||
const targetAddressHex = useSelector(selectTransferTargetAddressHex); // TODO: make readable
|
||||
const targetAsset = useSelector(selectTransferTargetAsset);
|
||||
const isSourceAssetWormholeWrapped = useSelector(
|
||||
selectTransferIsSourceAssetWormholeWrapped
|
||||
|
@ -47,6 +50,7 @@ function Target() {
|
|||
const uiAmountString = useSelector(selectTransferTargetBalanceString);
|
||||
const isTargetComplete = useSelector(selectTransferIsTargetComplete);
|
||||
const shouldLockFields = useSelector(selectTransferShouldLockFields);
|
||||
useSyncTargetAddress(!shouldLockFields);
|
||||
const handleTargetChange = useCallback(
|
||||
(event) => {
|
||||
dispatch(setTargetChain(event.target.value));
|
||||
|
@ -76,7 +80,14 @@ function Target() {
|
|||
</TextField>
|
||||
<KeyAndBalance chainId={targetChain} balance={uiAmountString} />
|
||||
<TextField
|
||||
placeholder="Asset"
|
||||
label="Address"
|
||||
fullWidth
|
||||
className={classes.transferField}
|
||||
value={targetAddressHex || ""}
|
||||
disabled={true}
|
||||
/>
|
||||
<TextField
|
||||
label="Asset"
|
||||
fullWidth
|
||||
className={classes.transferField}
|
||||
value={readableTargetAsset}
|
||||
|
|
|
@ -11,22 +11,17 @@ import {
|
|||
transferFromEth,
|
||||
transferFromSolana,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import {
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
Token,
|
||||
TOKEN_PROGRAM_ID,
|
||||
} from "@solana/spl-token";
|
||||
import { WalletContextState } from "@solana/wallet-adapter-react";
|
||||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
import { Connection } from "@solana/web3.js";
|
||||
import { MsgExecuteContract } from "@terra-money/terra.js";
|
||||
import {
|
||||
ConnectedWallet,
|
||||
useConnectedWallet,
|
||||
} from "@terra-money/wallet-provider";
|
||||
import { Signer } from "ethers";
|
||||
import { arrayify, parseUnits, zeroPad } from "ethers/lib/utils";
|
||||
import { parseUnits, zeroPad } from "ethers/lib/utils";
|
||||
import { useSnackbar } from "notistack";
|
||||
import { useCallback, useEffect, useMemo, useRef } from "react";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useEthereumProvider } from "../contexts/EthereumProviderContext";
|
||||
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
||||
|
@ -40,9 +35,7 @@ import {
|
|||
selectTransferSourceAsset,
|
||||
selectTransferSourceChain,
|
||||
selectTransferSourceParsedTokenAccount,
|
||||
selectTransferTargetAsset,
|
||||
selectTransferTargetChain,
|
||||
selectTransferTargetParsedTokenAccount,
|
||||
} from "../store/selectors";
|
||||
import { setIsSending, setSignedVAAHex } from "../store/transferSlice";
|
||||
import { hexToUint8Array, uint8ArrayToHex } from "../utils/array";
|
||||
|
@ -56,6 +49,7 @@ import {
|
|||
} from "../utils/consts";
|
||||
import { getSignedVAAWithRetry } from "../utils/getSignedVAAWithRetry";
|
||||
import { signSendAndConfirm } from "../utils/solana";
|
||||
import useTransferTargetAddressHex from "./useTransferTargetAddress";
|
||||
|
||||
async function eth(
|
||||
dispatch: any,
|
||||
|
@ -104,8 +98,8 @@ async function solana(
|
|||
mintAddress: string,
|
||||
amount: string,
|
||||
decimals: number,
|
||||
targetAddressStr: string,
|
||||
targetChain: ChainId,
|
||||
targetAddress: Uint8Array,
|
||||
originAddressStr?: string,
|
||||
originChain?: ChainId
|
||||
) {
|
||||
|
@ -114,7 +108,6 @@ async function solana(
|
|||
//TODO: check if token attestation exists on the target chain
|
||||
// TODO: share connection in context?
|
||||
const connection = new Connection(SOLANA_HOST, "confirmed");
|
||||
const targetAddress = zeroPad(arrayify(targetAddressStr), 32);
|
||||
const amountParsed = parseUnits(amount, decimals).toBigInt();
|
||||
const originAddress = originAddressStr
|
||||
? zeroPad(hexToUint8Array(originAddressStr), 32)
|
||||
|
@ -164,8 +157,8 @@ async function terra(
|
|||
wallet: ConnectedWallet,
|
||||
asset: string,
|
||||
amount: string,
|
||||
targetAddressStr: string,
|
||||
targetChain: ChainId
|
||||
targetChain: ChainId,
|
||||
targetAddress: Uint8Array
|
||||
) {
|
||||
dispatch(setIsSending(true));
|
||||
try {
|
||||
|
@ -180,7 +173,7 @@ async function terra(
|
|||
asset: asset,
|
||||
amount: amount,
|
||||
recipient_chain: targetChain,
|
||||
recipient: targetAddressStr,
|
||||
recipient: targetAddress,
|
||||
fee: 1000,
|
||||
nonce: 0,
|
||||
},
|
||||
|
@ -221,11 +214,11 @@ export function useHandleTransfer() {
|
|||
const originAsset = useSelector(selectTransferOriginAsset);
|
||||
const amount = useSelector(selectTransferAmount);
|
||||
const targetChain = useSelector(selectTransferTargetChain);
|
||||
const targetAsset = useSelector(selectTransferTargetAsset);
|
||||
const targetAddress = useTransferTargetAddressHex();
|
||||
const isTargetComplete = useSelector(selectTransferIsTargetComplete);
|
||||
const isSending = useSelector(selectTransferIsSending);
|
||||
const isSendComplete = useSelector(selectTransferIsSendComplete);
|
||||
const { signer, signerAddress } = useEthereumProvider();
|
||||
const { signer } = useEthereumProvider();
|
||||
const solanaWallet = useSolanaWallet();
|
||||
const solPK = solanaWallet?.publicKey;
|
||||
const terraWallet = useConnectedWallet();
|
||||
|
@ -234,37 +227,7 @@ export function useHandleTransfer() {
|
|||
);
|
||||
const sourceTokenPublicKey = sourceParsedTokenAccount?.publicKey;
|
||||
const decimals = sourceParsedTokenAccount?.decimals;
|
||||
const targetParsedTokenAccount = useSelector(
|
||||
selectTransferTargetParsedTokenAccount
|
||||
);
|
||||
const disabled = !isTargetComplete || isSending || isSendComplete;
|
||||
// TODO: we probably shouldn't get here if we don't have this public key
|
||||
// TODO: also this is just for solana... send help(ers)
|
||||
const targetTokenAccountPublicKey = targetParsedTokenAccount?.publicKey;
|
||||
// TODO: AVOID THIS DANGEROUS CACOPHONY
|
||||
const tpkRef = useRef<undefined | Uint8Array>(undefined);
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (targetChain === CHAIN_ID_SOLANA) {
|
||||
tpkRef.current = targetTokenAccountPublicKey
|
||||
? zeroPad(new PublicKey(targetTokenAccountPublicKey).toBytes(), 32) // use the target's TokenAccount if it exists
|
||||
: solPK && targetAsset // otherwise, use the associated token account (which we create in the case it doesn't exist)
|
||||
? zeroPad(
|
||||
(
|
||||
await Token.getAssociatedTokenAddress(
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
TOKEN_PROGRAM_ID,
|
||||
new PublicKey(targetAsset),
|
||||
solPK
|
||||
)
|
||||
).toBytes(),
|
||||
32
|
||||
)
|
||||
: undefined;
|
||||
} else tpkRef.current = undefined;
|
||||
})();
|
||||
}, [targetChain, solPK, targetAsset, targetTokenAccountPublicKey]);
|
||||
// TODO: dynamically get "to" wallet
|
||||
const handleTransferClick = useCallback(() => {
|
||||
// TODO: we should separate state for transaction vs fetching vaa
|
||||
// TODO: more generic way of calling these
|
||||
|
@ -272,7 +235,7 @@ export function useHandleTransfer() {
|
|||
sourceChain === CHAIN_ID_ETH &&
|
||||
!!signer &&
|
||||
decimals !== undefined &&
|
||||
!!tpkRef.current
|
||||
!!targetAddress
|
||||
) {
|
||||
eth(
|
||||
dispatch,
|
||||
|
@ -282,14 +245,14 @@ export function useHandleTransfer() {
|
|||
decimals,
|
||||
amount,
|
||||
targetChain,
|
||||
tpkRef.current
|
||||
targetAddress
|
||||
);
|
||||
} else if (
|
||||
sourceChain === CHAIN_ID_SOLANA &&
|
||||
!!solanaWallet &&
|
||||
!!solPK &&
|
||||
!!sourceTokenPublicKey &&
|
||||
!!signerAddress &&
|
||||
!!targetAddress &&
|
||||
decimals !== undefined
|
||||
) {
|
||||
solana(
|
||||
|
@ -299,10 +262,10 @@ export function useHandleTransfer() {
|
|||
solPK.toString(),
|
||||
sourceTokenPublicKey,
|
||||
sourceAsset,
|
||||
amount, //TODO: avoid decimals, pass in parsed amount
|
||||
amount,
|
||||
decimals,
|
||||
signerAddress,
|
||||
targetChain,
|
||||
targetAddress,
|
||||
originAsset,
|
||||
originChain
|
||||
);
|
||||
|
@ -310,7 +273,7 @@ export function useHandleTransfer() {
|
|||
sourceChain === CHAIN_ID_TERRA &&
|
||||
!!terraWallet &&
|
||||
decimals !== undefined &&
|
||||
!!signerAddress
|
||||
!!targetAddress
|
||||
) {
|
||||
terra(
|
||||
dispatch,
|
||||
|
@ -318,8 +281,8 @@ export function useHandleTransfer() {
|
|||
terraWallet,
|
||||
sourceAsset,
|
||||
amount,
|
||||
signerAddress, // TODO: only works for Eth
|
||||
targetChain
|
||||
targetChain,
|
||||
targetAddress
|
||||
);
|
||||
} else {
|
||||
// enqueueSnackbar("Transfers from this chain are not yet supported", {
|
||||
|
@ -331,7 +294,6 @@ export function useHandleTransfer() {
|
|||
enqueueSnackbar,
|
||||
sourceChain,
|
||||
signer,
|
||||
signerAddress,
|
||||
solanaWallet,
|
||||
solPK,
|
||||
terraWallet,
|
||||
|
@ -340,6 +302,7 @@ export function useHandleTransfer() {
|
|||
amount,
|
||||
decimals,
|
||||
targetChain,
|
||||
targetAddress,
|
||||
originAsset,
|
||||
originChain,
|
||||
]);
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
import {
|
||||
CHAIN_ID_ETH,
|
||||
CHAIN_ID_SOLANA,
|
||||
CHAIN_ID_TERRA,
|
||||
} from "@certusone/wormhole-sdk";
|
||||
import { arrayify, zeroPad } from "@ethersproject/bytes";
|
||||
import {
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
Token,
|
||||
TOKEN_PROGRAM_ID,
|
||||
} from "@solana/spl-token";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { useConnectedWallet } from "@terra-money/wallet-provider";
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useEthereumProvider } from "../contexts/EthereumProviderContext";
|
||||
import { useSolanaWallet } from "../contexts/SolanaWalletContext";
|
||||
import {
|
||||
selectTransferTargetAsset,
|
||||
selectTransferTargetChain,
|
||||
selectTransferTargetParsedTokenAccount,
|
||||
} from "../store/selectors";
|
||||
import { setTargetAddressHex } from "../store/transferSlice";
|
||||
import { uint8ArrayToHex } from "../utils/array";
|
||||
import bech32 from "bech32";
|
||||
|
||||
function useSyncTargetAddress(shouldFire: boolean) {
|
||||
const dispatch = useDispatch();
|
||||
const targetChain = useSelector(selectTransferTargetChain);
|
||||
const { signerAddress } = useEthereumProvider();
|
||||
const solanaWallet = useSolanaWallet();
|
||||
const solPK = solanaWallet?.publicKey;
|
||||
const targetAsset = useSelector(selectTransferTargetAsset);
|
||||
const targetParsedTokenAccount = useSelector(
|
||||
selectTransferTargetParsedTokenAccount
|
||||
);
|
||||
const targetTokenAccountPublicKey = targetParsedTokenAccount?.publicKey;
|
||||
const terraWallet = useConnectedWallet();
|
||||
useEffect(() => {
|
||||
if (shouldFire) {
|
||||
let cancelled = false;
|
||||
if (targetChain === CHAIN_ID_ETH && signerAddress) {
|
||||
dispatch(
|
||||
setTargetAddressHex(
|
||||
uint8ArrayToHex(zeroPad(arrayify(signerAddress), 32))
|
||||
)
|
||||
);
|
||||
}
|
||||
// TODO: have the user explicitly select an account on solana
|
||||
else if (targetChain === CHAIN_ID_SOLANA && targetTokenAccountPublicKey) {
|
||||
// use the target's TokenAccount if it exists
|
||||
dispatch(
|
||||
setTargetAddressHex(
|
||||
uint8ArrayToHex(
|
||||
zeroPad(new PublicKey(targetTokenAccountPublicKey).toBytes(), 32)
|
||||
)
|
||||
)
|
||||
);
|
||||
} else if (targetChain === CHAIN_ID_SOLANA && solPK && targetAsset) {
|
||||
// otherwise, use the associated token account (which we create in the case it doesn't exist)
|
||||
(async () => {
|
||||
const associatedTokenAccount = await Token.getAssociatedTokenAddress(
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
TOKEN_PROGRAM_ID,
|
||||
new PublicKey(targetAsset),
|
||||
solPK
|
||||
);
|
||||
if (!cancelled) {
|
||||
dispatch(
|
||||
setTargetAddressHex(
|
||||
uint8ArrayToHex(zeroPad(associatedTokenAccount.toBytes(), 32))
|
||||
)
|
||||
);
|
||||
}
|
||||
})();
|
||||
} else if (
|
||||
targetChain === CHAIN_ID_TERRA &&
|
||||
terraWallet &&
|
||||
terraWallet.walletAddress
|
||||
) {
|
||||
dispatch(
|
||||
setTargetAddressHex(
|
||||
uint8ArrayToHex(
|
||||
zeroPad(
|
||||
new Uint8Array(bech32.decode(terraWallet.walletAddress).words),
|
||||
32
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
dispatch(setTargetAddressHex(undefined));
|
||||
}
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
}, [
|
||||
dispatch,
|
||||
shouldFire,
|
||||
targetChain,
|
||||
signerAddress,
|
||||
solPK,
|
||||
targetAsset,
|
||||
targetTokenAccountPublicKey,
|
||||
terraWallet,
|
||||
]);
|
||||
}
|
||||
|
||||
export default useSyncTargetAddress;
|
|
@ -0,0 +1,13 @@
|
|||
import { useMemo } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectTransferTargetAddressHex } from "../store/selectors";
|
||||
import { hexToUint8Array } from "../utils/array";
|
||||
|
||||
export default function useTransferTargetAddressHex() {
|
||||
const targetAddressHex = useSelector(selectTransferTargetAddressHex);
|
||||
const targetAddress = useMemo(
|
||||
() => (targetAddressHex ? hexToUint8Array(targetAddressHex) : undefined),
|
||||
[targetAddressHex]
|
||||
);
|
||||
return targetAddress;
|
||||
}
|
|
@ -57,6 +57,8 @@ export const selectTransferSourceBalanceString = (state: RootState) =>
|
|||
export const selectTransferAmount = (state: RootState) => state.transfer.amount;
|
||||
export const selectTransferTargetChain = (state: RootState) =>
|
||||
state.transfer.targetChain;
|
||||
export const selectTransferTargetAddressHex = (state: RootState) =>
|
||||
state.transfer.targetAddressHex;
|
||||
export const selectTransferTargetAsset = (state: RootState) =>
|
||||
state.transfer.targetAsset;
|
||||
export const selectTransferTargetParsedTokenAccount = (state: RootState) =>
|
||||
|
@ -96,11 +98,8 @@ export const selectTransferIsTargetComplete = (state: RootState) =>
|
|||
!!state.transfer.targetChain &&
|
||||
!!state.transfer.targetAsset &&
|
||||
(state.transfer.targetChain !== CHAIN_ID_ETH ||
|
||||
state.transfer.targetAsset !== ethers.constants.AddressZero); //&&
|
||||
// Associated Token Account exists
|
||||
// (state.transfer.targetChain !== CHAIN_ID_SOLANA ||
|
||||
// (!!state.transfer.targetParsedTokenAccount &&
|
||||
// !!state.transfer.targetParsedTokenAccount.publicKey));
|
||||
state.transfer.targetAsset !== ethers.constants.AddressZero) &&
|
||||
!!state.transfer.targetAddressHex;
|
||||
export const selectTransferIsSendComplete = (state: RootState) =>
|
||||
!!selectTransferSignedVAAHex(state);
|
||||
export const selectTransferShouldLockFields = (state: RootState) =>
|
||||
|
|
|
@ -34,6 +34,7 @@ export interface TransferState {
|
|||
sourceParsedTokenAccount: ParsedTokenAccount | undefined;
|
||||
amount: string;
|
||||
targetChain: ChainId;
|
||||
targetAddressHex: string | undefined;
|
||||
targetAsset: string | null | undefined;
|
||||
targetParsedTokenAccount: ParsedTokenAccount | undefined;
|
||||
signedVAAHex: string | undefined;
|
||||
|
@ -51,6 +52,7 @@ const initialState: TransferState = {
|
|||
originAsset: undefined,
|
||||
amount: "",
|
||||
targetChain: CHAIN_ID_ETH,
|
||||
targetAddressHex: undefined,
|
||||
targetAsset: undefined,
|
||||
targetParsedTokenAccount: undefined,
|
||||
signedVAAHex: undefined,
|
||||
|
@ -86,6 +88,7 @@ export const transferSlice = createSlice({
|
|||
}
|
||||
if (state.targetChain === action.payload) {
|
||||
state.targetChain = prevSourceChain;
|
||||
state.targetAddressHex = undefined;
|
||||
}
|
||||
},
|
||||
setSourceAsset: (state, action: PayloadAction<string>) => {
|
||||
|
@ -117,6 +120,8 @@ export const transferSlice = createSlice({
|
|||
setTargetChain: (state, action: PayloadAction<ChainId>) => {
|
||||
const prevTargetChain = state.targetChain;
|
||||
state.targetChain = action.payload;
|
||||
state.targetAddressHex = undefined;
|
||||
// targetAsset is handled by useFetchTargetAsset
|
||||
if (state.sourceChain === action.payload) {
|
||||
state.sourceChain = prevTargetChain;
|
||||
state.activeStep = 0;
|
||||
|
@ -132,6 +137,9 @@ export const transferSlice = createSlice({
|
|||
}
|
||||
}
|
||||
},
|
||||
setTargetAddressHex: (state, action: PayloadAction<string | undefined>) => {
|
||||
state.targetAddressHex = action.payload;
|
||||
},
|
||||
setTargetAsset: (
|
||||
state,
|
||||
action: PayloadAction<string | null | undefined>
|
||||
|
@ -169,6 +177,7 @@ export const {
|
|||
setSourceParsedTokenAccount,
|
||||
setAmount,
|
||||
setTargetChain,
|
||||
setTargetAddressHex,
|
||||
setTargetAsset,
|
||||
setTargetParsedTokenAccount,
|
||||
setSignedVAAHex,
|
||||
|
|
Loading…
Reference in New Issue