From f7eef7c3b6e8442961d72c75eafcde1de8447f93 Mon Sep 17 00:00:00 2001
From: bartosz-lipinski <264380+bartosz-lipinski@users.noreply.github.com>
Date: Tue, 9 Mar 2021 13:06:19 -0600
Subject: [PATCH] fix: icons
---
.../src/components/TokenDisplay/index.tsx | 5 +-
.../src/components/TokenDisplay/style.less | 11 +-
packages/bridge/src/contexts/ethereum.tsx | 1 -
.../bridge/src/hooks/useWormholeAccounts.tsx | 114 ++++++++++++------
packages/bridge/src/views/home/index.tsx | 8 +-
packages/common/src/contexts/accounts.tsx | 47 +-------
6 files changed, 90 insertions(+), 96 deletions(-)
diff --git a/packages/bridge/src/components/TokenDisplay/index.tsx b/packages/bridge/src/components/TokenDisplay/index.tsx
index ab55bc7..3d13d2e 100644
--- a/packages/bridge/src/components/TokenDisplay/index.tsx
+++ b/packages/bridge/src/components/TokenDisplay/index.tsx
@@ -6,10 +6,9 @@ import { useEthereum } from '../../contexts';
import { ASSET_CHAIN } from "../../models/bridge/constants";
import './style.less';
-export const TokenDisplay = ({ asset, chain, token }: { asset?: string, chain?: ASSET_CHAIN, token?: TokenInfo }) => {
-
+export const TokenDisplay = ({ asset, chain, token, logo }: { asset?: string, chain?: ASSET_CHAIN, token?: TokenInfo, logo?: string }) => {
return
;
}
diff --git a/packages/bridge/src/components/TokenDisplay/style.less b/packages/bridge/src/components/TokenDisplay/style.less
index 8e11e91..d9bed6e 100644
--- a/packages/bridge/src/components/TokenDisplay/style.less
+++ b/packages/bridge/src/components/TokenDisplay/style.less
@@ -1,5 +1,8 @@
.token-chain-logo {
- position: relative
+ position: relative;
+ width: 60px;
+ height: 60px;
+ display: flex;
}
.token-logo {
@@ -11,12 +14,12 @@
}
.chain-logo {
- order: 1px solid hsla(0, 0%, 50.2%, 0.5);
+ border: 1px solid hsla(0, 0%, 50.2%, 0.5);
border-radius: 20px;
position: absolute;
background: #fff;
width: 30px;
height: 30px;
- bottom: 9px;
- right: -5px;
+ bottom: 3px;
+ right: 3px;
}
diff --git a/packages/bridge/src/contexts/ethereum.tsx b/packages/bridge/src/contexts/ethereum.tsx
index 45f8e82..e737fc3 100644
--- a/packages/bridge/src/contexts/ethereum.tsx
+++ b/packages/bridge/src/contexts/ethereum.tsx
@@ -79,7 +79,6 @@ export const EthereumProvider: FunctionComponent = ({children}) => {
const signer = provider.getSigner();
signer.getAddress().then(account => setAccounts([account]));
-
setProvider(provider);
}
}, [connected])
diff --git a/packages/bridge/src/hooks/useWormholeAccounts.tsx b/packages/bridge/src/hooks/useWormholeAccounts.tsx
index f5325ec..a5c4a4a 100644
--- a/packages/bridge/src/hooks/useWormholeAccounts.tsx
+++ b/packages/bridge/src/hooks/useWormholeAccounts.tsx
@@ -1,11 +1,11 @@
import {useCallback, useEffect, useRef, useState} from "react";
-import { useConnection, useConnectionConfig, MintParser, cache, getMultipleAccounts, ParsedAccount, TokenAccountParser, programIds} from "@oyster/common";
+import { useConnection, useConnectionConfig, MintParser, cache, getMultipleAccounts, ParsedAccount, TokenAccountParser, programIds, formatTokenAmount, fromLamports} from "@oyster/common";
import {WORMHOLE_PROGRAM_ID} from "../utils/ids";
import {ASSET_CHAIN} from "../utils/assets";
import { useEthereum } from "../contexts";
import { Connection, PublicKey } from "@solana/web3.js";
import { models } from "@oyster/common";
-import { MintInfo } from "@solana/spl-token";
+import { AccountInfo, MintInfo } from "@solana/spl-token";
import { bridgeAuthorityKey, wrappedAssetMintKey, WrappedMetaLayout } from './../models/bridge';
import bs58 from "bs58";
@@ -30,11 +30,11 @@ type WrappedAssetMeta = {
const queryWrappedMetaAccounts = async (
+ authorityKey: PublicKey,
connection: Connection,
setExternalAssets: (arr: WrappedAssetMeta[]) => void
) => {
- // authority -> query for token accounts to get locked assets
- let authorityKey = await bridgeAuthorityKey(programIds().wormhole.pubkey);
+
const filters = [
{
@@ -81,6 +81,8 @@ const queryWrappedMetaAccounts = async (
mintKey: '',
amount: 0,
amountInUSD: 0,
+ // TODO: customize per chain
+ explorer: `https://etherscan.io/address/0x${assetAddress}`
});
}
}
@@ -124,6 +126,7 @@ const queryWrappedMetaAccounts = async (
return;
}
asset.mint = cache.get(key);
+ asset.wrappedExplorer = `https://explorer.solana.com/address/${asset.mintKey}`;
if(asset.mint) {
@@ -139,17 +142,48 @@ const queryWrappedMetaAccounts = async (
asset.mint = cache.get(key);
asset.amount = asset.mint?.info.supply.toNumber() || 0;
- setExternalAssets([...assets.values()]
- .sort((a, b) => a?.symbol?.localeCompare(b.symbol || '') || 0));
+ setExternalAssets([...assets.values()]);
});
}
- setExternalAssets([...assets.values()]
- .sort((a, b) => a?.symbol?.localeCompare(b.symbol || '') || 0));
+ setExternalAssets([...assets.values()]);
});
};
+const queryCustodyAccounts = async (authorityKey: PublicKey, connection: Connection) => {
+ debugger;
+ const tokenAccounts = await connection.getTokenAccountsByOwner(
+ authorityKey,
+ {
+ programId: programIds().token,
+ }).then(acc => acc.value.map(a => cache.add(a.pubkey, a.account, TokenAccountParser) as ParsedAccount));
+ // query for mints
+ await getMultipleAccounts(connection, tokenAccounts.map(a => a.info.mint.toBase58()), 'single').then(({ keys, array }) => {
+ keys.forEach((key, index) => {
+ if(!array[index]) {
+ return;
+ }
+
+ return cache.add(key, array[index], MintParser);
+ })
+ });
+
+ return tokenAccounts.map(token => {
+ const mint = cache.get(token.info.mint) as ParsedAccount;
+ const asset = mint.pubkey.toBase58()
+ return {
+ address: asset,
+ chain: ASSET_CHAIN.Solana,
+ amount: fromLamports(token, mint.info),
+ mintKey: asset,
+ mint,
+ decimals: 9,
+ amountInUSD: 0,
+ explorer: `https://explorer.solana.com/address/${asset}`,
+ } as WrappedAssetMeta;
+ })
+};
export const useWormholeAccounts = () => {
const connection = useConnection();
@@ -163,33 +197,35 @@ export const useWormholeAccounts = () => {
const [externalAssets, setExternalAssets] = useState([]);
const [amountInUSD, setAmountInUSD] = useState(0);
- /// TODO:
- /// assets that left Solana
- // 1. getTokenAccountsByOwner with bridge PDA
- // 2. get prices from serum ?
- // 3. multiply account balances by
-
- /// assets locked from ETH
- // 1. get asset address from proposal [x]
- // 2. find the asset in the coingecko list or call abi? []
- // 3. build mint address using PDA [x]
- // 4. query all mints [x]
- // 5. multiply mint supply by asset price from coingecko [x]
- // 6. aggregate all assets [x]
- // 7. subscribe to program accounts
useEffect(() => {
setLoading(true);
- queryWrappedMetaAccounts(connection, setExternalAssets).then(() => setLoading(false));
+ let wormholeSubId = 0;
+ (async () => {
+ // authority -> query for token accounts to get locked assets
+ let authorityKey = await bridgeAuthorityKey(programIds().wormhole.pubkey);
- const subId = connection.onProgramAccountChange(WORMHOLE_PROGRAM_ID, (info) => {
- if (info.accountInfo.data.length === WrappedMetaLayout.span) {
- // TODO: check if new account and update external assets
- }
- });
+ // get all accounts that moved assets from solana to other chains
+ const custodyAccounts = await queryCustodyAccounts(authorityKey, connection);
+
+ // query wrapped assets that were imported to solana from other chains
+ queryWrappedMetaAccounts(authorityKey, connection, (assets) => {
+ setExternalAssets([...custodyAccounts, ...assets]
+ .sort((a, b) => a?.symbol?.localeCompare(b.symbol || '') || 0))
+ }).then(() => setLoading(false));
+
+ // TODO: listen to solana accounts for updates
+
+ wormholeSubId = connection.onProgramAccountChange(WORMHOLE_PROGRAM_ID, (info) => {
+ if (info.accountInfo.data.length === WrappedMetaLayout.span) {
+ // TODO: check if new account and update external assets
+ }
+ });
+
+ })();
return () => {
- connection.removeProgramAccountChangeListener(subId);
+ connection.removeProgramAccountChangeListener(wormholeSubId);
};
}, [connection, setExternalAssets]);
@@ -200,14 +236,13 @@ export const useWormholeAccounts = () => {
}
const addressToId = new Map();
- const idToAsset = new Map();
+ const idToAsset = new Map();
const assetsToQueryNames: WrappedAssetMeta[] = [];
const ids = externalAssets.map(asset => {
// TODO: add different nets/clusters
- asset.explorer = `https://etherscan.io/address/0x${asset.address}`;
- asset.wrappedExplorer = `https://explorer.solana.com/address/${asset.mintKey}`;
+
let knownToken = tokenMap.get(asset.mintKey);
if (knownToken) {
@@ -227,7 +262,7 @@ export const useWormholeAccounts = () => {
let coinInfo = coinList.get(asset.symbol.toLowerCase());
if(coinInfo) {
- idToAsset.set(coinInfo.id, asset);
+ idToAsset.set(coinInfo.id, [...(idToAsset.get(coinInfo.id) || []), asset]);
addressToId.set(asset.address, coinInfo.id);
return coinInfo.id;
}
@@ -248,14 +283,17 @@ export const useWormholeAccounts = () => {
let totalInUSD = 0;
Object.keys(data).forEach(key => {
- let asset = idToAsset.get(key);
- if(!asset) {
+ let assets = idToAsset.get(key);
+
+ if(!assets) {
return;
}
- asset.price = data[key]?.usd || 1;
- asset.amountInUSD = Math.round(asset.amount * (asset.price || 1) * 100) / 100;
- totalInUSD += asset.amountInUSD;
+ assets.forEach(asset => {
+ asset.price = data[key]?.usd || 1;
+ asset.amountInUSD = Math.round(asset.amount * (asset.price || 1) * 100) / 100;
+ totalInUSD += asset.amountInUSD;
+ });
});
setAmountInUSD(totalInUSD);
diff --git a/packages/bridge/src/views/home/index.tsx b/packages/bridge/src/views/home/index.tsx
index 9305ea0..ab6001f 100644
--- a/packages/bridge/src/views/home/index.tsx
+++ b/packages/bridge/src/views/home/index.tsx
@@ -1,11 +1,12 @@
import { Table, Col, Row, Statistic, Button } from 'antd';
import React from 'react';
-import { GUTTER, LABELS } from '../../constants';
-import { formatNumber, formatTokenAmount, formatUSD, shortenAddress} from '@oyster/common';
+import { GUTTER } from '../../constants';
+import { formatNumber, formatUSD, shortenAddress} from '@oyster/common';
import './itemStyle.less';
import { Link } from 'react-router-dom';
import {useWormholeAccounts} from "../../hooks/useWormholeAccounts";
+import { TokenDisplay } from '../../components/TokenDisplay';
export const HomeView = () => {
const {
@@ -14,7 +15,6 @@ export const HomeView = () => {
totalInUSD
} = useWormholeAccounts();
-
const columns = [
{
title: 'Symbol',
@@ -26,7 +26,7 @@ export const HomeView = () => {
style: {},
},
children: (
- {record.logo && } {record.symbol}
+ {record.logo && } {record.symbol}
),
};
},
diff --git a/packages/common/src/contexts/accounts.tsx b/packages/common/src/contexts/accounts.tsx
index 92f1dee..1aee897 100644
--- a/packages/common/src/contexts/accounts.tsx
+++ b/packages/common/src/contexts/accounts.tsx
@@ -187,52 +187,7 @@ export const cache = {
}
return pubkey;
- },
- queryMint: async (connection: Connection, pubKey: string | PublicKey) => {
- let id: PublicKey;
- if (typeof pubKey === 'string') {
- id = new PublicKey(pubKey);
- } else {
- id = pubKey;
- }
-
- const address = id.toBase58();
- let mint = mintCache.get(address);
- if (mint) {
- return mint;
- }
-
- let query = pendingMintCalls.get(address);
- if (query) {
- return query;
- }
-
- query = getMintInfo(connection, id).then((data) => {
- pendingMintCalls.delete(address);
-
- mintCache.set(address, data);
- return data;
- }) as Promise;
- pendingMintCalls.set(address, query as any);
-
- return query;
- },
- getMint: (pubKey: string | PublicKey) => {
- let key: string;
- if (typeof pubKey !== 'string') {
- key = pubKey.toBase58();
- } else {
- key = pubKey;
- }
-
- return mintCache.get(key);
- },
- addMint: (pubKey: PublicKey, obj: AccountInfo) => {
- const mint = deserializeMint(obj.data);
- const id = pubKey.toBase58();
- mintCache.set(id, mint);
- return mint;
- },
+ }
};
export const useAccountsContext = () => {