bridge_ui: solana price estimates in tvl
Change-Id: I041b36dc7efe1bb7e20376aace4e5181d6c35069
This commit is contained in:
parent
1a99ea1f85
commit
93a09e01aa
|
@ -13,6 +13,7 @@
|
|||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||
"@metamask/detect-provider": "^1.2.0",
|
||||
"@project-serum/serum": "^0.13.60",
|
||||
"@reduxjs/toolkit": "^1.6.1",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/spl-token-registry": "^0.2.216",
|
||||
|
@ -62,7 +63,7 @@
|
|||
},
|
||||
"../sdk/js": {
|
||||
"name": "@certusone/wormhole-sdk",
|
||||
"version": "0.0.5",
|
||||
"version": "0.0.8",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@improbable-eng/grpc-web": "^0.14.0",
|
||||
|
@ -5431,6 +5432,82 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@project-serum/anchor": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.11.1.tgz",
|
||||
"integrity": "sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA==",
|
||||
"dependencies": {
|
||||
"@project-serum/borsh": "^0.2.2",
|
||||
"@solana/web3.js": "^1.17.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"bn.js": "^5.1.2",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"camelcase": "^5.3.1",
|
||||
"crypto-hash": "^1.3.0",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"find": "^0.3.0",
|
||||
"js-sha256": "^0.9.0",
|
||||
"pako": "^2.0.3",
|
||||
"snake-case": "^3.0.4",
|
||||
"toml": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=11"
|
||||
}
|
||||
},
|
||||
"node_modules/@project-serum/anchor/node_modules/camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@project-serum/anchor/node_modules/pako": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz",
|
||||
"integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg=="
|
||||
},
|
||||
"node_modules/@project-serum/anchor/node_modules/snake-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
||||
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
|
||||
"dependencies": {
|
||||
"dot-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@project-serum/borsh": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/borsh/-/borsh-0.2.2.tgz",
|
||||
"integrity": "sha512-Ms+aWmGVW6bWd3b0+MWwoaYig2QD0F90h0uhr7AzY3dpCb5e2S6RsRW02vFTfa085pY2VLB7nTZNbFECQ1liTg==",
|
||||
"dependencies": {
|
||||
"bn.js": "^5.1.2",
|
||||
"buffer-layout": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@solana/web3.js": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@project-serum/serum": {
|
||||
"version": "0.13.60",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/serum/-/serum-0.13.60.tgz",
|
||||
"integrity": "sha512-fGsp9F0ZAS48YQ2HNy+6CNoifJESFXxVsOLPd9QK1XNV8CTuQoECOnVXxV6s5cKGre8pLNq5hrhi5J6aCGauEQ==",
|
||||
"dependencies": {
|
||||
"@project-serum/anchor": "^0.11.1",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/web3.js": "^1.21.0",
|
||||
"bn.js": "^5.1.2",
|
||||
"buffer-layout": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@project-serum/sol-wallet-adapter": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.5.tgz",
|
||||
|
@ -18816,6 +18893,14 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node_modules/find": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz",
|
||||
"integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==",
|
||||
"dependencies": {
|
||||
"traverse-chain": "~0.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/find-cache-dir": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
|
||||
|
@ -26199,6 +26284,11 @@
|
|||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.1.tgz",
|
||||
"integrity": "sha512-XyYXEUTP3ykPPnGPoesMr4yBygopit99iXW52yT1EWrkzwzvtAor/pbf+EBuDkwqSty7K10LeTjCkUn8c166aQ=="
|
||||
},
|
||||
"node_modules/js-sha256": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz",
|
||||
"integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
|
||||
},
|
||||
"node_modules/js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
|
@ -39823,6 +39913,11 @@
|
|||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/toml": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
|
||||
},
|
||||
"node_modules/tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
|
@ -39855,6 +39950,11 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/traverse-chain": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz",
|
||||
"integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE="
|
||||
},
|
||||
"node_modules/trim-right": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
||||
|
@ -48005,6 +48105,69 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@project-serum/anchor": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/anchor/-/anchor-0.11.1.tgz",
|
||||
"integrity": "sha512-oIdm4vTJkUy6GmE6JgqDAuQPKI7XM4TPJkjtoIzp69RZe0iAD9JP2XHx7lV1jLdYXeYHqDXfBt3zcq7W91K6PA==",
|
||||
"requires": {
|
||||
"@project-serum/borsh": "^0.2.2",
|
||||
"@solana/web3.js": "^1.17.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"bn.js": "^5.1.2",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer-layout": "^1.2.0",
|
||||
"camelcase": "^5.3.1",
|
||||
"crypto-hash": "^1.3.0",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"find": "^0.3.0",
|
||||
"js-sha256": "^0.9.0",
|
||||
"pako": "^2.0.3",
|
||||
"snake-case": "^3.0.4",
|
||||
"toml": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
||||
},
|
||||
"pako": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz",
|
||||
"integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg=="
|
||||
},
|
||||
"snake-case": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
|
||||
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
|
||||
"requires": {
|
||||
"dot-case": "^3.0.4",
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@project-serum/borsh": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/borsh/-/borsh-0.2.2.tgz",
|
||||
"integrity": "sha512-Ms+aWmGVW6bWd3b0+MWwoaYig2QD0F90h0uhr7AzY3dpCb5e2S6RsRW02vFTfa085pY2VLB7nTZNbFECQ1liTg==",
|
||||
"requires": {
|
||||
"bn.js": "^5.1.2",
|
||||
"buffer-layout": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@project-serum/serum": {
|
||||
"version": "0.13.60",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/serum/-/serum-0.13.60.tgz",
|
||||
"integrity": "sha512-fGsp9F0ZAS48YQ2HNy+6CNoifJESFXxVsOLPd9QK1XNV8CTuQoECOnVXxV6s5cKGre8pLNq5hrhi5J6aCGauEQ==",
|
||||
"requires": {
|
||||
"@project-serum/anchor": "^0.11.1",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/web3.js": "^1.21.0",
|
||||
"bn.js": "^5.1.2",
|
||||
"buffer-layout": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"@project-serum/sol-wallet-adapter": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@project-serum/sol-wallet-adapter/-/sol-wallet-adapter-0.2.5.tgz",
|
||||
|
@ -59297,6 +59460,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"find": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/find/-/find-0.3.0.tgz",
|
||||
"integrity": "sha512-iSd+O4OEYV/I36Zl8MdYJO0xD82wH528SaCieTVHhclgiYNe9y+yPKSwK+A7/WsmHL1EZ+pYUJBXWTL5qofksw==",
|
||||
"requires": {
|
||||
"traverse-chain": "~0.1.0"
|
||||
}
|
||||
},
|
||||
"find-cache-dir": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
|
||||
|
@ -65073,6 +65244,11 @@
|
|||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.1.tgz",
|
||||
"integrity": "sha512-XyYXEUTP3ykPPnGPoesMr4yBygopit99iXW52yT1EWrkzwzvtAor/pbf+EBuDkwqSty7K10LeTjCkUn8c166aQ=="
|
||||
},
|
||||
"js-sha256": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz",
|
||||
"integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
|
||||
},
|
||||
"js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
|
@ -76353,6 +76529,11 @@
|
|||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"toml": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
|
||||
|
@ -76378,6 +76559,11 @@
|
|||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"traverse-chain": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/traverse-chain/-/traverse-chain-0.1.0.tgz",
|
||||
"integrity": "sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE="
|
||||
},
|
||||
"trim-right": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||
"@metamask/detect-provider": "^1.2.0",
|
||||
"@project-serum/serum": "^0.13.60",
|
||||
"@reduxjs/toolkit": "^1.6.1",
|
||||
"@solana/spl-token": "^0.1.6",
|
||||
"@solana/spl-token-registry": "^0.2.216",
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
} from "@certusone/wormhole-sdk";
|
||||
import { formatUnits } from "@ethersproject/units";
|
||||
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
||||
import { TokenInfo } from "@solana/spl-token-registry";
|
||||
import {
|
||||
AccountInfo,
|
||||
Connection,
|
||||
|
@ -26,12 +27,14 @@ import {
|
|||
TERRA_SWAPRATE_URL,
|
||||
TERRA_TOKEN_BRIDGE_ADDRESS,
|
||||
} from "../utils/consts";
|
||||
import { priceStore, serumMarkets } from "../utils/SolanaPriceStore";
|
||||
import {
|
||||
formatNativeDenom,
|
||||
getNativeTerraIcon,
|
||||
NATIVE_TERRA_DECIMALS,
|
||||
} from "../utils/terra";
|
||||
import useMetadata, { GenericMetadata } from "./useMetadata";
|
||||
import useSolanaTokenMap from "./useSolanaTokenMap";
|
||||
import useTerraNativeBalances from "./useTerraNativeBalances";
|
||||
|
||||
export type TVL = {
|
||||
|
@ -74,7 +77,8 @@ const calcSolanaTVL = (
|
|||
accounts:
|
||||
| { pubkey: PublicKey; account: AccountInfo<ParsedAccountData> }[]
|
||||
| undefined,
|
||||
metaData: DataWrapper<Map<string, GenericMetadata>>
|
||||
metaData: DataWrapper<Map<string, GenericMetadata>>,
|
||||
solanaPrices: DataWrapper<Map<string, number | undefined>>
|
||||
) => {
|
||||
const output: TVL[] = [];
|
||||
if (
|
||||
|
@ -82,7 +86,9 @@ const calcSolanaTVL = (
|
|||
!accounts.length ||
|
||||
metaData.isFetching ||
|
||||
metaData.error ||
|
||||
!metaData.data
|
||||
!metaData.data ||
|
||||
solanaPrices.isFetching ||
|
||||
!solanaPrices.data
|
||||
) {
|
||||
return output;
|
||||
}
|
||||
|
@ -91,14 +97,20 @@ const calcSolanaTVL = (
|
|||
const genericMetadata = metaData.data?.get(
|
||||
item.account.data.parsed?.info?.mint?.toString()
|
||||
);
|
||||
const mint = item.account.data.parsed?.info?.mint?.toString();
|
||||
const price = solanaPrices?.data?.get(mint);
|
||||
output.push({
|
||||
logo: genericMetadata?.logo || undefined,
|
||||
symbol: genericMetadata?.symbol || undefined,
|
||||
name: genericMetadata?.tokenName || undefined,
|
||||
amount: item.account.data.parsed?.info?.tokenAmount?.uiAmount || "0", //Should always be defined.
|
||||
totalValue: undefined,
|
||||
quotePrice: undefined,
|
||||
assetAddress: item.account.data.parsed?.info?.mint?.toString(),
|
||||
totalValue: price
|
||||
? parseFloat(
|
||||
item.account.data.parsed?.info?.tokenAmount?.uiAmount || "0"
|
||||
) * price
|
||||
: undefined,
|
||||
quotePrice: price,
|
||||
assetAddress: mint,
|
||||
originChainId: CHAIN_ID_SOLANA,
|
||||
originChain: "Solana",
|
||||
});
|
||||
|
@ -175,6 +187,82 @@ const useTerraTVL = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const useSolanaPrices = (
|
||||
mintAddresses: string[],
|
||||
tokenMap: DataWrapper<TokenInfo[]>
|
||||
) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [priceMap, setPriceMap] = useState<Map<
|
||||
string,
|
||||
number | undefined
|
||||
> | null>(null);
|
||||
const [error] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
if (!mintAddresses || !mintAddresses.length || !tokenMap.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relevantMarkets: {
|
||||
publicKey?: PublicKey;
|
||||
name: string;
|
||||
deprecated?: boolean;
|
||||
mintAddress: string;
|
||||
}[] = [];
|
||||
mintAddresses.forEach((address) => {
|
||||
const tokenInfo = tokenMap.data?.find((x) => x.address === address);
|
||||
const relevantMarket = tokenInfo && serumMarkets[tokenInfo.symbol];
|
||||
if (relevantMarket) {
|
||||
relevantMarkets.push({ ...relevantMarket, mintAddress: address });
|
||||
}
|
||||
});
|
||||
|
||||
setIsLoading(true);
|
||||
const priceMap: Map<string, number | undefined> = new Map();
|
||||
const connection = new Connection(SOLANA_HOST);
|
||||
const promises: Promise<void>[] = [];
|
||||
//Load all the revelevant markets into the priceMap
|
||||
relevantMarkets.forEach((market) => {
|
||||
const marketName: string = market.name;
|
||||
promises.push(
|
||||
priceStore
|
||||
.getPrice(connection, marketName)
|
||||
.then((result) => {
|
||||
priceMap.set(market.mintAddress, result);
|
||||
})
|
||||
.catch((e) => {
|
||||
//Do nothing, we just won't load this price.
|
||||
return Promise.resolve();
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
//By this point all the relevant markets are loaded.
|
||||
if (!cancelled) {
|
||||
setPriceMap(priceMap);
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
return;
|
||||
};
|
||||
}, [mintAddresses, tokenMap.data]);
|
||||
|
||||
return useMemo(() => {
|
||||
return {
|
||||
isFetching: isLoading,
|
||||
data: priceMap || null,
|
||||
error: error,
|
||||
receivedAt: null,
|
||||
};
|
||||
}, [error, priceMap, isLoading]);
|
||||
};
|
||||
|
||||
const useTVL = (): DataWrapper<TVL[]> => {
|
||||
const [ethCovalentData, setEthCovalentData] = useState(undefined);
|
||||
const [ethCovalentIsLoading, setEthCovalentIsLoading] = useState(false);
|
||||
|
@ -202,12 +290,14 @@ const useTVL = (): DataWrapper<TVL[]> => {
|
|||
}, [solanaCustodyTokens]);
|
||||
|
||||
const solanaMetadata = useMetadata(CHAIN_ID_SOLANA, mintAddresses);
|
||||
const solanaTokenMap = useSolanaTokenMap();
|
||||
const solanaPrices = useSolanaPrices(mintAddresses, solanaTokenMap);
|
||||
|
||||
const { isLoading: isTerraLoading, terraTVL } = useTerraTVL();
|
||||
|
||||
const solanaTVL = useMemo(
|
||||
() => calcSolanaTVL(solanaCustodyTokens, solanaMetadata),
|
||||
[solanaCustodyTokens, solanaMetadata]
|
||||
() => calcSolanaTVL(solanaCustodyTokens, solanaMetadata, solanaPrices),
|
||||
[solanaCustodyTokens, solanaMetadata, solanaPrices]
|
||||
);
|
||||
const ethTVL = useMemo(
|
||||
() => calcEvmTVL(ethCovalentData, CHAIN_ID_ETH),
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
import { MARKETS } from "@project-serum/serum";
|
||||
import { Connection, PublicKey } from "@solana/web3.js";
|
||||
|
||||
export interface Markets {
|
||||
[coin: string]: {
|
||||
publicKey?: PublicKey;
|
||||
name: string;
|
||||
deprecated?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const serumMarkets = (() => {
|
||||
const m: Markets = {};
|
||||
MARKETS.forEach((market) => {
|
||||
const coin = market.name.split("/")[0];
|
||||
if (m[coin]) {
|
||||
// Only override a market if it's not deprecated .
|
||||
if (!m.deprecated) {
|
||||
m[coin] = {
|
||||
publicKey: market.address,
|
||||
name: market.name.split("/").join(""),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
m[coin] = {
|
||||
publicKey: market.address,
|
||||
name: market.name.split("/").join(""),
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
m["USDC"] = m["USDT"];
|
||||
|
||||
return m;
|
||||
})();
|
||||
|
||||
// Create a cached API wrapper to avoid rate limits.
|
||||
class PriceStore {
|
||||
cache: Map<String, number | undefined>;
|
||||
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
||||
async getPrice(
|
||||
connection: Connection,
|
||||
marketName: string
|
||||
): Promise<number | undefined> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.cache.get(marketName) === undefined) {
|
||||
fetch(`https://serum-api.bonfida.com/orderbooks/${marketName}`).then(
|
||||
(resp) => {
|
||||
resp.json().then((resp) => {
|
||||
if (resp.data.asks === null || resp.data.bids === null) {
|
||||
resolve(undefined);
|
||||
} else if (
|
||||
resp.data.asks.length === 0 &&
|
||||
resp.data.bids.length === 0
|
||||
) {
|
||||
resolve(undefined);
|
||||
} else if (resp.data.asks.length === 0) {
|
||||
resolve(resp.data.bids[0].price);
|
||||
} else if (resp.data.bids.length === 0) {
|
||||
resolve(resp.data.asks[0].price);
|
||||
} else {
|
||||
const mid =
|
||||
(resp.data.asks[0].price + resp.data.bids[0].price) / 2.0;
|
||||
this.cache.set(marketName, mid);
|
||||
resolve(this.cache.get(marketName));
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return resolve(this.cache.get(marketName));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const priceStore = new PriceStore();
|
Loading…
Reference in New Issue