diff --git a/packages/bridge/src/hooks/useLockedFundsAccounts.tsx b/packages/bridge/src/hooks/useLockedFundsAccounts.tsx index d940812..e804c87 100644 --- a/packages/bridge/src/hooks/useLockedFundsAccounts.tsx +++ b/packages/bridge/src/hooks/useLockedFundsAccounts.tsx @@ -1,61 +1,38 @@ -import {useEffect, useState} from "react"; -import {contexts} from "@oyster/common"; +import React, {useEffect, useState} from "react"; +import {contexts, TokenIcon, useConnectionConfig} from "@oyster/common"; import * as BufferLayout from 'buffer-layout' import {WORMHOLE_PROGRAM_ID} from "../utils/ids"; import BN from "bn.js"; import {ASSET_CHAIN, getAssetAmountInUSD, getAssetName, getAssetTokenSymbol} from "../utils/assets"; import { useEthereum } from "../contexts"; import { PublicKey } from "@solana/web3.js"; +import { models } from "@oyster/common"; + +const ParsedDataLayout = models.ParsedDataLayout const { useConnection } = contexts.Connection; -interface ParsedData { - amount: number, - rawAmount: string, - parsedAssetAddress: string, - parsedAccount: any, - assetDecimals: number, - name: string, - symbol: string, - sourceAddress: string, - targetAddress: string, - amountInUSD: number, -} - export const useLockedFundsAccounts = () => { const connection = useConnection(); const { tokenMap: ethTokens } = useEthereum(); + const {tokenMap: solanaTokens} = useConnectionConfig(); - const [lockedSolanaAccounts, setLockedSolanaAccounts] = useState([]); + const [lockedSolanaAccounts, setLockedSolanaAccounts] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const queryTxs = async () => { + if (!solanaTokens.size || !ethTokens.size) { + return [] + } setLoading(true); const programAccounts = await connection.getProgramAccounts( WORMHOLE_PROGRAM_ID ); - const dataLayout = BufferLayout.struct([ - BufferLayout.blob(32, 'amount'), - BufferLayout.u8('toChain'), - BufferLayout.blob(32, 'sourceAddress'), - BufferLayout.blob(32, 'targetAddress'), - BufferLayout.blob(32, 'assetAddress'), - BufferLayout.u8('assetChain'), - BufferLayout.u8('assetDecimals'), - BufferLayout.seq(BufferLayout.u8(), 1), // 4 byte alignment because a u32 is following - BufferLayout.u32('nonce'), - BufferLayout.blob(1001, 'vaa'), - BufferLayout.seq(BufferLayout.u8(), 3), // 4 byte alignment because a u32 is following - BufferLayout.u32('vaaTime'), - BufferLayout.u32('lockupTime'), - BufferLayout.u8('pokeCounter'), - BufferLayout.blob(32, 'signatureAccount'), - BufferLayout.u8('initialized'), - ]); - const filteredParsedAccounts: ParsedData[] = []; + + const filteredParsedAccounts: models.ParsedDataAccount[] = []; programAccounts.map(acc => { try { - const parsedAccount = dataLayout.decode(acc.account.data) + const parsedAccount = ParsedDataLayout.decode(acc.account.data) const chains = [ASSET_CHAIN.Solana, ASSET_CHAIN.Ethereum] if (chains.indexOf(parsedAccount.assetChain) >= 0 && chains.indexOf(parsedAccount.toChain) >= 0) { @@ -63,20 +40,24 @@ export const useLockedFundsAccounts = () => { const rawAmount = new BN(parsedAccount.amount, 2, "le") const amount = rawAmount.div(dec).toNumber(); const parsedAssetAddress: string = parsedAccount.assetChain === ASSET_CHAIN.Solana ? - new PublicKey(parsedAccount.targetAddress).toString() : + new PublicKey(parsedAccount.assetAddress).toString() : new Buffer(parsedAccount.assetAddress.slice(12)).toString("hex") - const parsedData: ParsedData = { + + const parsedData: models.ParsedDataAccount = { amount: amount, rawAmount: rawAmount.toString(), parsedAssetAddress: parsedAssetAddress, parsedAccount: parsedAccount, assetDecimals: parsedAccount.assetDecimals, + assetIcon: parsedAccount.assetChain === ASSET_CHAIN.Solana ? + : + , sourceAddress: new PublicKey(parsedAccount.sourceAddress).toString(), targetAddress: parsedAccount.toChain === ASSET_CHAIN.Solana ? new PublicKey(parsedAccount.targetAddress).toString() : new Buffer(parsedAccount.targetAddress.slice(12)).toString("hex"), - name: getAssetName(parsedAssetAddress, parsedAccount.assetChain), - symbol: getAssetTokenSymbol(parsedAssetAddress, parsedAccount.assetChain), + name: getAssetName(parsedAssetAddress, parsedAccount.assetChain, solanaTokens, ethTokens), + symbol: getAssetTokenSymbol(parsedAssetAddress, parsedAccount.assetChain, solanaTokens, ethTokens), amountInUSD: getAssetAmountInUSD(amount, parsedAssetAddress, parsedAccount.assetChain), }; filteredParsedAccounts.push(parsedData) @@ -91,7 +72,7 @@ export const useLockedFundsAccounts = () => { setLoading(false); setLockedSolanaAccounts(all[0]) }); - }, []); + }, [solanaTokens, ethTokens]); return { loading, lockedSolanaAccounts, diff --git a/packages/bridge/src/utils/assets.ts b/packages/bridge/src/utils/assets.ts index 5c303bb..400477e 100644 --- a/packages/bridge/src/utils/assets.ts +++ b/packages/bridge/src/utils/assets.ts @@ -1,15 +1,31 @@ +import { + getTokenName, + getVerboseTokenName, + KnownTokenMap, + TokenIcon, +} from '@oyster/common'; +import React from 'react'; + export const getAssetName = ( parsedAssetAddress: string, assetChain: number, + solanaTokens: KnownTokenMap, + ethTokens: KnownTokenMap, ) => { - return parsedAssetAddress.slice(0, 5); + if (assetChain === ASSET_CHAIN.Solana) + return getVerboseTokenName(solanaTokens, parsedAssetAddress); + else return getVerboseTokenName(ethTokens, `0x${parsedAssetAddress}`); }; export const getAssetTokenSymbol = ( parsedAssetAddress: string, assetChain: number, + solanaTokens: KnownTokenMap, + ethTokens: KnownTokenMap, ) => { - return parsedAssetAddress.slice(0, 5); + if (assetChain === ASSET_CHAIN.Solana) + return getTokenName(solanaTokens, parsedAssetAddress); + else return getTokenName(ethTokens, `0x${parsedAssetAddress}`); }; export const getAssetAmountInUSD = ( diff --git a/packages/bridge/src/views/home/index.tsx b/packages/bridge/src/views/home/index.tsx index e938876..004b5d7 100644 --- a/packages/bridge/src/views/home/index.tsx +++ b/packages/bridge/src/views/home/index.tsx @@ -2,7 +2,7 @@ import { MintInfo } from '@solana/spl-token'; import { Table, Tag, Space, Card, Col, Row, Statistic, Button } from 'antd'; import React, {useEffect, useMemo, useState} from 'react'; import { GUTTER, LABELS } from '../../constants'; -import {contexts, ExplorerLink, ParsedAccount, utils} from '@oyster/common'; +import {contexts, ExplorerLink, ParsedAccount, TokenIcon, utils} from '@oyster/common'; import { useMarkets } from '../../contexts/market'; import { LendingReserveItem } from './item'; @@ -86,13 +86,13 @@ export const HomeView = () => { return lockedSolanaAccounts.map((acc, index) => { return { key: index.toString(), - symbol: acc.symbol, + symbol:
{acc.assetIcon} {acc.symbol}
, name: acc.name, amount: acc.amountInUSD, assetAddress: acc.parsedAccount.assetChain === ASSET_CHAIN.Solana ? : , - sourceAddress: , + sourceAddress: , targetAddress: acc.parsedAccount.toChain === ASSET_CHAIN.Solana ? : , @@ -133,8 +133,6 @@ export const HomeView = () => { }, ]; - debugger; - return (
{ if (address && ref.current) { + try { + ref.current.innerHTML = ''; ref.current.className = className || ''; ref.current.appendChild( @@ -27,6 +29,10 @@ export const Identicon = (props: { parseInt(bs58.decode(address).toString('hex').slice(5, 15), 16), ), ); + + }catch (err) { + // TODO + } } }, [address, style, className]); diff --git a/packages/common/src/components/TokenIcon/index.tsx b/packages/common/src/components/TokenIcon/index.tsx index 357d5ce..21da7ec 100644 --- a/packages/common/src/components/TokenIcon/index.tsx +++ b/packages/common/src/components/TokenIcon/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { PublicKey } from '@solana/web3.js'; -import { getTokenIcon } from '../../utils'; +import {getTokenIcon, KnownTokenMap} from '../../utils'; import { useConnectionConfig } from '../../contexts/connection'; import { Identicon } from '../Identicon'; @@ -9,9 +9,15 @@ export const TokenIcon = (props: { style?: React.CSSProperties; size?: number; className?: string; + tokenMap?: KnownTokenMap, }) => { - const { tokenMap } = useConnectionConfig(); - const icon = getTokenIcon(tokenMap, props.mintAddress); + let icon: string | undefined = ''; + if (props.tokenMap) { + icon = getTokenIcon(props.tokenMap, props.mintAddress); + } else { + const { tokenMap } = useConnectionConfig(); + icon = getTokenIcon(tokenMap, props.mintAddress); + } const size = props.size || 20; @@ -35,7 +41,6 @@ export const TokenIcon = (props: { /> ); } - return (