UNPKG

@yoroi/swap

Version:
375 lines (373 loc) 12.6 kB
"use strict"; import { Portfolio, Swap } from '@yoroi/types'; import { Dex } from './types'; import { isDex } from './validators'; export const ptIdDh = '000000000000000000000000000000000000000000000000000000006c6f76656c616365'; export const toSwapSplit = ({ amount_in = 0, batcher_fee = 0, deposits = 0, dex, expected_output = 0, expected_output_without_slippage = 0, fee = 0, final_price = 0, initial_price = 0, pool_fee = 0, pool_id = '', price_distortion = 0, price_impact = 0 }) => ({ amountIn: amount_in, batcherFee: batcher_fee, deposits, protocol: toSwapProtocol(dex), expectedOutput: expected_output, expectedOutputWithoutSlippage: expected_output_without_slippage, fee, finalPrice: final_price, initialPrice: initial_price, poolFee: pool_fee, poolId: pool_id, priceDistortion: price_distortion, priceImpact: price_impact }); export const toPriceImpact = splits => { const totalAmountIn = splits.reduce((sum, split) => sum + (split.amount_in ?? 0), 0); if (totalAmountIn === 0) return 0; // Avoid division by zero const weightedPriceImpact = splits.reduce((sum, split) => sum + (split.price_impact ?? 0) * (split.amount_in ?? 0), 0); return weightedPriceImpact / totalAmountIn; }; export const transformersMaker = ({ primaryTokenInfo, address, isPrimaryToken }) => { const fromTokenId = tokenId => tokenId === ptIdDh ? primaryTokenInfo.id : `${tokenId.slice(0, 56)}.${tokenId.slice(56)}`; const toTokenId = tokenId => isPrimaryToken(tokenId) ? 'ADA' : tokenId.replace('.', ''); return { tokens: { fromId: fromTokenId, toId: toTokenId, response: res => res.map(({ token_id, is_verified, token_decimals = 0, token_ascii = '', ticker = '' }) => { if (token_id === ptIdDh) return primaryTokenInfo; return { id: fromTokenId(token_id), decimals: token_decimals, ticker: ticker, name: token_ascii, status: is_verified ? Portfolio.Token.Status.Valid : Portfolio.Token.Status.Invalid, type: Portfolio.Token.Type.FT, nature: Portfolio.Token.Nature.Secondary, application: Portfolio.Token.Application.General, symbol: '', tag: '', reference: '', fingerprint: '', description: '', website: '', originalImage: '' }; }) }, orders: { response: res => res.map(({ _id, dex, last_update, submission_time, output_index, actual_out_amount = 0, expected_out_amount = 0, amount_in = 0, is_dexhunter = false, status, token_id_in = '', token_id_out = '', tx_hash = '', update_tx_hash = '' }) => ({ status: { COMPLETE: 'matched', CANCELLED: 'canceled', PENDING: 'open' }[status], amountIn: amount_in, actualAmountOut: actual_out_amount, expectedAmountOut: expected_out_amount, txHash: tx_hash, outputIndex: output_index, updateTxHash: update_tx_hash, customId: _id, placedAt: submission_time ? new Date(submission_time).getTime() : undefined, lastUpdate: last_update ? new Date(last_update).getTime() : undefined, aggregator: is_dexhunter ? Swap.Aggregator.Dexhunter : Swap.Aggregator.Muesliswap, protocol: toSwapProtocol(dex), tokenIn: fromTokenId(token_id_in), tokenOut: fromTokenId(token_id_out) })) }, cancel: { request: ({ order }) => ({ address, order_id: order.customId }), response: ({ additional_cancellation_fee, cbor = '' }) => ({ cbor, additionalCancellationFee: additional_cancellation_fee }) }, estimate: { request: ({ amountIn, blockedProtocols, slippage, tokenIn, tokenOut }) => ({ slippage, amount_in: amountIn, blacklisted_dexes: blockedProtocols?.map(fromSwapProtocol).filter(isDex), token_in: toTokenId(tokenIn), token_out: toTokenId(tokenOut) }), response: ({ splits, batcher_fee = 0, deposits = 0, dexhunter_fee = 0, net_price = 0, net_price_reverse = 0, partner_fee = 0, total_output = 0, total_output_without_slippage = 0 }, reversed) => ({ deposits, splits: splits?.map(toSwapSplit) ?? [], totalOutputWithoutSlippage: total_output_without_slippage, totalInput: splits?.reduce((acc, cur) => acc + (cur.amount_in ?? 0), 0) ?? undefined, batcherFee: batcher_fee, aggregatorFee: dexhunter_fee, frontendFee: partner_fee, netPrice: reversed ? net_price_reverse : net_price, priceImpact: toPriceImpact(splits ?? []), totalFee: Number((batcher_fee + dexhunter_fee + partner_fee).toFixed(primaryTokenInfo.decimals)), totalOutput: total_output }) }, reverseEstimate: { request: ({ amountOut, blockedProtocols, slippage, tokenIn, tokenOut }) => ({ slippage, amount_out: amountOut, blacklisted_dexes: blockedProtocols?.map(fromSwapProtocol).filter(isDex), token_in: toTokenId(tokenIn), token_out: toTokenId(tokenOut) }), response: ({ batcher_fee = 0, deposits = 0, dexhunter_fee = 0, net_price = 0, net_price_reverse = 0, partner_fee = 0, splits, total_input = 0, total_output = 0 }, reversed) => ({ deposits, batcherFee: batcher_fee, aggregatorFee: dexhunter_fee, frontendFee: partner_fee, netPrice: reversed ? net_price_reverse : net_price, priceImpact: toPriceImpact(splits ?? []), totalFee: Number((batcher_fee + dexhunter_fee + partner_fee).toFixed(primaryTokenInfo.decimals)), totalOutput: total_output, totalOutputWithoutSlippage: total_output, splits: splits?.map(toSwapSplit) ?? [], totalInput: (total_input || splits?.reduce((acc, cur) => acc + (cur.amount_in ?? 0), 0)) ?? undefined }) }, limitEstimate: { request: ({ protocol = Swap.Protocol.Unsupported, multiples = 1, amountIn, blockedProtocols, tokenIn, tokenOut, wantedPrice }) => ({ multiples, amount_in: amountIn, wanted_price: isPrimaryToken(tokenIn) && wantedPrice !== undefined && wantedPrice !== 0 ? 1 / wantedPrice : wantedPrice, blacklisted_dexes: blockedProtocols?.map(fromSwapProtocol).filter(isDex), dex: fromSwapProtocol(protocol), token_in: toTokenId(tokenIn), token_out: toTokenId(tokenOut) }), response: ({ splits, batcher_fee = 0, deposits = 0, dexhunter_fee = 0, net_price = 0, partner_fee = 0, total_input = 0, total_output = 0 }, reversed) => ({ deposits, batcherFee: batcher_fee, aggregatorFee: dexhunter_fee, frontendFee: partner_fee, netPrice: reverse(reversed, net_price), priceImpact: toPriceImpact(splits ?? []), totalFee: Number((batcher_fee + dexhunter_fee + partner_fee).toFixed(primaryTokenInfo.decimals)), totalOutput: total_output, totalOutputWithoutSlippage: total_output, splits: splits?.map(toSwapSplit) ?? [], totalInput: (total_input || splits?.reduce((acc, cur) => acc + (cur.amount_in ?? 0), 0)) ?? undefined }) }, limitBuild: { request: ({ amountIn, blockedProtocols, protocol, multiples, tokenIn, tokenOut, wantedPrice }) => ({ multiples, buyer_address: address, amount_in: amountIn, wanted_price: isPrimaryToken(tokenIn) && wantedPrice !== undefined && wantedPrice !== 0 ? 1 / wantedPrice : wantedPrice, token_in: toTokenId(tokenIn), token_out: toTokenId(tokenOut), blacklisted_dexes: blockedProtocols?.map(fromSwapProtocol).filter(isDex), dex: protocol ? fromSwapProtocol(protocol) : undefined }), response: ({ cbor = '', batcher_fee = 0, deposits = 0, dexhunter_fee = 0, partner_fee = 0, splits, total_input = 0, total_output = 0 }, reversed) => ({ cbor, deposits, aggregator: Swap.Aggregator.Dexhunter, batcherFee: batcher_fee, aggregatorFee: dexhunter_fee, frontendFee: partner_fee / 10 ** primaryTokenInfo.decimals, netPrice: reverse(reversed, splits?.[0]?.initial_price ?? 0), totalOutput: total_output, totalOutputWithoutSlippage: total_output, priceImpact: toPriceImpact(splits ?? []), totalFee: Number((batcher_fee + dexhunter_fee + partner_fee / 10 ** primaryTokenInfo.decimals).toFixed(primaryTokenInfo.decimals)), splits: splits?.map(toSwapSplit) ?? [], totalInput: (total_input || splits?.reduce((acc, cur) => acc + (cur.amount_in ?? 0), 0)) ?? 0 }) }, build: { request: ({ slippage = 0, amountIn, blockedProtocols, tokenIn, tokenOut, inputs }) => ({ slippage, amount_in: amountIn, buyer_address: address, blacklisted_dexes: blockedProtocols?.map(fromSwapProtocol).filter(isDex), token_in: toTokenId(tokenIn), token_out: toTokenId(tokenOut), inputs }), response: ({ splits, cbor = '', batcher_fee = 0, deposits = 0, dexhunter_fee = 0, net_price = 0, net_price_reverse = 0, partner_fee = 0, total_input = 0, total_output = 0, total_output_without_slippage = 0 }, reversed) => ({ aggregator: Swap.Aggregator.Dexhunter, cbor, deposits, batcherFee: batcher_fee, aggregatorFee: dexhunter_fee, frontendFee: partner_fee, netPrice: (reversed ? net_price_reverse || reverse(true, splits?.[0]?.initial_price ?? 0) : net_price || splits?.[0]?.initial_price) ?? 0, // main net_price is coming as 0 :( priceImpact: toPriceImpact(splits ?? []), totalOutput: total_output, totalFee: Number((batcher_fee + dexhunter_fee + partner_fee).toFixed(primaryTokenInfo.decimals)), totalOutputWithoutSlippage: total_output_without_slippage, totalInput: (total_input || splits?.reduce((acc, cur) => acc + (cur.amount_in ?? 0), 0)) ?? 0, splits: splits?.map(toSwapSplit) ?? [] }) } }; }; export const toSwapProtocol = dex => ({ [Dex.Cswap]: Swap.Protocol.Cswap, [Dex.Minswap_v1]: Swap.Protocol.Minswap_v1, [Dex.Minswap_v2]: Swap.Protocol.Minswap_v2, [Dex.Wingriders_v1]: Swap.Protocol.Wingriders_v1, [Dex.Wingriders_v2]: Swap.Protocol.Wingriders_v2, [Dex.Vyfi_v1]: Swap.Protocol.Vyfi_v1, [Dex.Sundaeswap_v1]: Swap.Protocol.Sundaeswap_v1, [Dex.Sundaeswap_v3]: Swap.Protocol.Sundaeswap_v3, [Dex.Splash_v1]: Swap.Protocol.Splash_v1, [Dex.Muesliswap_clp]: Swap.Protocol.Muesliswap_clp, [Dex.Muesliswap_v2]: Swap.Protocol.Muesliswap_v2, [Dex.Unsupported]: Swap.Protocol.Unsupported })[dex] ?? Swap.Protocol.Unsupported; export const fromSwapProtocol = dex => ({ [Swap.Protocol.Cswap]: Dex.Cswap, [Swap.Protocol.Minswap_v1]: Dex.Minswap_v1, [Swap.Protocol.Minswap_v2]: Dex.Minswap_v2, [Swap.Protocol.Minswap_stable]: Dex.Unsupported, [Swap.Protocol.Wingriders_v1]: Dex.Wingriders_v1, [Swap.Protocol.Wingriders_v2]: Dex.Wingriders_v2, [Swap.Protocol.Vyfi_v1]: Dex.Vyfi_v1, [Swap.Protocol.Sundaeswap_v1]: Dex.Sundaeswap_v1, [Swap.Protocol.Sundaeswap_v3]: Dex.Sundaeswap_v3, [Swap.Protocol.Splash_v1]: Dex.Splash_v1, [Swap.Protocol.Teddy_v1]: Dex.Unsupported, [Swap.Protocol.Muesliswap_v2]: Dex.Muesliswap_v2, [Swap.Protocol.Muesliswap_clp]: Dex.Muesliswap_clp, [Swap.Protocol.Spectrum_v1]: Dex.Unsupported, [Swap.Protocol.Unsupported]: Dex.Unsupported })[dex] ?? Dex.Unsupported; export const DexhunterProtocols = Object.values(Dex).filter(p => p !== Dex.Unsupported).map(toSwapProtocol); export const reverse = (reversed, price) => !reversed || price === 0 || price === undefined ? price : 1 / price; //# sourceMappingURL=transformers.js.map