Skip to content

Commit

Permalink
Merge pull request #2449 from tallycash/fix-price-impact-issue
Browse files Browse the repository at this point in the history
Price impact warning not working properly
  • Loading branch information
Gergő Nagy authored Oct 18, 2022
2 parents b3bc3e5 + e6a4465 commit b4b437c
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 32 deletions.
25 changes: 25 additions & 0 deletions background/lib/prices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import {
FiatCurrency,
FungibleAsset,
PricePoint,
SmartContractFungibleAsset,
UnitPricePoint,
} from "../assets"

import { toFixedPoint } from "./fixed-point"
import { isValidCoinGeckoPriceResponse } from "./validate"
import { EVMNetwork } from "../networks"
import { USD } from "../constants"

const COINGECKO_API_ROOT = "https://api.coingecko.com/api/v3"

Expand Down Expand Up @@ -162,3 +164,26 @@ export async function getTokenPrices(
}
return prices
}

/*
* Get a Price Point for asset to USD.
*/
export function getPricePoint(
asset: SmartContractFungibleAsset | FungibleAsset,
unitPricePoint: UnitPricePoint<FungibleAsset>
): PricePoint {
return {
pair: [asset, USD],
amounts: [
1n * 10n ** BigInt(asset.decimals),
BigInt(
Math.trunc(
(Number(unitPricePoint.unitPrice.amount) /
10 ** (unitPricePoint.unitPrice.asset as FungibleAsset).decimals) *
10 ** USD.decimals
)
),
],
time: unitPricePoint.time,
}
}
2 changes: 1 addition & 1 deletion background/redux-slices/0x-swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ export const fetchSwapPrice = createBackgroundAsyncThunk(

dispatch(setLatestQuoteRequest(quoteRequest))

const priceDetails = calculatePriceDetails(
const priceDetails = await calculatePriceDetails(
quoteRequest,
assets,
quote.sellAmount,
Expand Down
2 changes: 1 addition & 1 deletion background/redux-slices/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ERC20_INTERFACE } from "../lib/erc20"
import logger from "../lib/logger"
import { BASE_ASSETS_BY_SYMBOL, FIAT_CURRENCIES_SYMBOL } from "../constants"

type SingleAssetState = AnyAsset & {
export type SingleAssetState = AnyAsset & {
recentPrices: {
[assetSymbol: string]: PricePoint
}
Expand Down
63 changes: 50 additions & 13 deletions background/redux-slices/utils/0x-swap-utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { FungibleAsset, SmartContractFungibleAsset } from "../../assets"
import {
FungibleAsset,
PricePoint,
SmartContractFungibleAsset,
} from "../../assets"
import { USD } from "../../constants"
import {
convertFixedPointNumber,
fixedPointNumberToString,
parseToFixedPointNumber,
} from "../../lib/fixed-point"
import { getPricePoint, getTokenPrices } from "../../lib/prices"
import { EVMNetwork } from "../../networks"
import { AssetsState, selectAssetPricePoint } from "../assets"
import { AssetsState, selectAssetPricePoint, SingleAssetState } from "../assets"
import {
AssetMainCurrencyAmount,
enrichAssetAmountWithMainCurrencyValues,
Expand Down Expand Up @@ -38,16 +44,44 @@ export type PriceDetails = {
sellCurrencyAmount: string | undefined
}

export function getAssetAmount(
export async function getAssetPricePoint(
asset: SmartContractFungibleAsset | FungibleAsset,
assets: AssetsState,
network: EVMNetwork
): Promise<PricePoint> {
const assetPricesNetworks = assets
.filter(
(assetItem) =>
"contractAddress" in assetItem &&
assetItem.contractAddress &&
assetItem.symbol === asset.symbol
)
.map((assetItem) => {
const { contractAddress } = assetItem as SingleAssetState & {
contractAddress: string
}
return contractAddress
})

const unitPricePoint = Object.values(
await getTokenPrices(assetPricesNetworks, USD, network)
)[0]

return getPricePoint(asset, unitPricePoint)
}

export async function getAssetAmount(
assets: AssetsState,
asset: SmartContractFungibleAsset | FungibleAsset,
amount: string
):
amount: string,
network: EVMNetwork
): Promise<
| ({
asset: FungibleAsset | SmartContractFungibleAsset
amount: bigint
} & AssetMainCurrencyAmount)
| undefined {
| undefined
> {
const mainCurrencySymbol = "USD"

const fixedPointAmount = parseToFixedPointNumber(amount.toString())
Expand All @@ -64,12 +98,13 @@ export function getAssetAmount(
asset?.symbol,
mainCurrencySymbol
)

return enrichAssetAmountWithMainCurrencyValues(
{
asset,
amount: decimalMatched.amount,
},
assetPricePoint,
assetPricePoint ?? (await getAssetPricePoint(asset, assets, network)),
2
)
}
Expand All @@ -84,28 +119,30 @@ export function getPriceImpact(
return undefined
}

export function calculatePriceDetails(
export async function calculatePriceDetails(
quoteRequest: SwapQuoteRequest,
assets: AssetsState,
sellAmount: string,
buyAmount: string
): PriceDetails {
const assetSellAmount = getAssetAmount(
): Promise<PriceDetails> {
const assetSellAmount = await getAssetAmount(
assets,
quoteRequest.assets.sellAsset,
fixedPointNumberToString({
amount: BigInt(sellAmount),
decimals: quoteRequest.assets.sellAsset.decimals,
})
}),
quoteRequest.network
)

const assetBuyAmount = getAssetAmount(
const assetBuyAmount = await getAssetAmount(
assets,
quoteRequest.assets.buyAsset,
fixedPointNumberToString({
amount: BigInt(buyAmount),
decimals: quoteRequest.assets.buyAsset.decimals,
})
}),
quoteRequest.network
)

const priceImpact = getPriceImpact(
Expand Down
19 changes: 2 additions & 17 deletions background/services/indexing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
NETWORK_BY_CHAIN_ID,
USD,
} from "../../constants"
import { getPrices, getTokenPrices } from "../../lib/prices"
import { getPrices, getTokenPrices, getPricePoint } from "../../lib/prices"
import {
fetchAndValidateTokenList,
mergeAssets,
Expand Down Expand Up @@ -656,22 +656,7 @@ export default class IndexingService extends BaseService<Events> {
allActiveAssetsByAddress[contractAddress.toLowerCase()]
if (asset) {
// TODO look up fiat currency
const pricePoint = {
pair: [asset, USD],
amounts: [
1n * 10n ** BigInt(asset.decimals),
BigInt(
Math.trunc(
(Number(unitPricePoint.unitPrice.amount) /
10 **
(unitPricePoint.unitPrice.asset as FungibleAsset)
.decimals) *
10 ** USD.decimals
)
),
], // TODO not a big fan of this lost precision
time: unitPricePoint.time,
} as PricePoint
const pricePoint = getPricePoint(asset, unitPricePoint)
this.emitter.emit("price", pricePoint)
// TODO move the "coingecko" data source elsewhere
this.db
Expand Down

0 comments on commit b4b437c

Please sign in to comment.