Skip to content

Commit

Permalink
fix: token store race cond, broken fiat estimates on projects view & …
Browse files Browse the repository at this point in the history
…claim project flow
  • Loading branch information
efstajas committed Sep 18, 2023
1 parent af7bca7 commit a0035c1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
const connected = tokensStore.connected;
$: {
if ($connected && amounts) {
if ($connected && amounts && $connected) {
const prices = $priceStore;
includesUnknownPrice = false;
Expand All @@ -41,7 +41,14 @@
fiatEstimateCents = 'pending';
} else {
fiatEstimateCents = amounts.reduce((sum, { tokenAddress, amount }) => {
const res = fiatEstimates.convert({ amount, tokenAddress });
const token = tokensStore.getByAddress(tokenAddress);
if (!token) {
includesUnknownPrice = true;
return sum;
}
const res = fiatEstimates.convert({ amount, tokenAddress }, token.info.decimals);
if (res === 'unsupported') {
includesUnknownPrice = true;
Expand Down
36 changes: 27 additions & 9 deletions src/lib/components/token-amounts-table/token-amounts-table.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import addCustomTokenFlowSteps from '$lib/flows/add-custom-token/add-custom-token-flow-steps';
import modal from '$lib/stores/modal';
import tokensStore, { type TokenInfoWrapper } from '$lib/stores/tokens/tokens.store';
import tokensStore from '$lib/stores/tokens/tokens.store';
import fiatEstimatesStore from '$lib/utils/fiat-estimates/fiat-estimates';
import formatTokenAmount from '$lib/utils/format-token-amount';
import unreachable from '$lib/utils/unreachable';
Expand All @@ -20,22 +20,40 @@
}
export let amounts: Amount[];
$: tokenAddresses = amounts.map((a) => a.tokenAddress);
$: tokens = tokenAddresses.map((a) => tokensStore.getByAddress(a));
$: tokens =
($tokensStore && amounts.map((amount) => tokensStore.getByAddress(amount.tokenAddress))) ?? [];
$: knownTokens = tokens.filter((token): token is TokenInfoWrapper => token !== undefined);
$: knownSymbols = knownTokens.map((token) => token.info.symbol);
$: priceStore = fiatEstimatesStore.price(tokenAddresses ?? []);
$: priceStore = fiatEstimatesStore.price(knownSymbols);
const fiatEstimatesStarted = fiatEstimatesStore.started;
$: {
if ($fiatEstimatesStarted && tokenAddresses && tokenAddresses.length > 0) {
fiatEstimatesStore.track(tokenAddresses);
}
}
let fiatEstimates: (number | 'pending' | 'unsupported' | undefined)[] = [];
const connected = tokensStore.connected;
$: {
$priceStore;
amounts.forEach(({ tokenAddress, amount }, index) => {
fiatEstimates[index] = fiatEstimatesStore.convert({ amount, tokenAddress });
});
if ($connected) {
amounts.forEach(({ tokenAddress, amount }, index) => {
const token = tokensStore.getByAddress(tokenAddress);
if (!token) {
fiatEstimates[index] = 'unsupported';
return;
}
fiatEstimates[index] = fiatEstimatesStore.convert(
{ amount, tokenAddress },
token.info.decimals,
);
});
}
fiatEstimates = fiatEstimates;
}
Expand Down
23 changes: 12 additions & 11 deletions src/lib/utils/fiat-estimates/fiat-estimates.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { derived, writable, get } from 'svelte/store';
import assert from '$lib/utils/assert';
import deduplicateReadable from '../deduplicate-readable';
import tokensStore from '$lib/stores/tokens/tokens.store';
import { z } from 'zod';
import { formatUnits } from 'ethers/lib/utils';
import { utils } from 'ethers';
Expand Down Expand Up @@ -122,23 +121,22 @@ export async function track(addresses: TokenAddress[]) {
/**
* Convert the given amount to USD.
* @param amount The amount to convert.
* @param tokenDecimals The amount of decimals for the token the amount is in.
* @returns A float representing the amount in USD, `undefined` if the asset
* isnʼt currently tracked, `pending` if we're waiting for Binance to report
* the price for the first time, or `unsupported` if Binance doesnʼt provide
* isnʼt currently tracked, `pending` if we're waiting for the data provider to
* report the price for the first time, or `unsupported` if it can't provide
* a price for the given asset.
*/
export function convert(amount: Amount) {
const { tokenAddress } = amount;
export function convert(amount: Amount, tokenDecimals: number) {
let { tokenAddress } = amount;
tokenAddress = utils.getAddress(tokenAddress);

const price = get(prices)[tokenAddress];

if (!price) return undefined;
if (typeof price === 'string') return price;

const token = tokensStore.getByAddress(tokenAddress);
assert(token, 'Token info not found for tracked token');

const tokenAmount = parseFloat(formatUnits(amount.amount, token.info.decimals));
const tokenAmount = parseFloat(formatUnits(amount.amount, tokenDecimals));

return tokenAmount * price;
}
Expand All @@ -148,15 +146,18 @@ export function convert(amount: Amount) {
* tokenAddresses changes.
* @param tokenAddresses The tokens to subscribe to.
*/
const price = (tokenAddresses: TokenAddress[]) =>
deduplicateReadable(
const price = (tokenAddresses: TokenAddress[]) => {
tokenAddresses = tokenAddresses.map((address) => utils.getAddress(address));

return deduplicateReadable(
derived(prices, ($prices) => {
// Return an object of all the prices for the given symbols.
return Object.fromEntries(
tokenAddresses.map((tokenAddress) => [tokenAddress, $prices[tokenAddress] || 'pending']),
);
}),
);
};

export default {
start,
Expand Down

0 comments on commit a0035c1

Please sign in to comment.