@yoroi/swap
Version:
The Swap package of Yoroi SDK
839 lines (838 loc) • 36.2 kB
JavaScript
"use strict";
import { Chain, Swap } from '@yoroi/types';
import { isPrimaryToken } from '@yoroi/portfolio';
import { fromSwapProtocol, ptIdDh, reverse, toSwapProtocol, toSwapSplit, transformersMaker } from './transformers';
import { api, primaryTokenInfo } from './api.mocks';
import { Dex } from './types';
const address = 'addr1q9qhyvkm5fytm5ckgshny0zz08a3urhhh7ckdqxcm27av40eafn3v5lr2w2n2er9uj7c743mt42gpe8tgek6394z9t7qn4yjzl';
const network = Chain.Network.Mainnet;
const transformers = transformersMaker({
primaryTokenInfo,
address,
network,
isPrimaryToken
});
describe('transformers', () => {
describe('tokens', () => {
test('should correctly transform the tokens response', () => {
expect(transformers.tokens.response([...api.responses.tokens, {
token_id: '000000000000000000000000000000000000000000000000000000006c6f76656c616365',
token_policy: '00000000000000000000000000000000000000000000000000000000',
is_verified: true,
supply: 45_000_000_000,
creation_date: '0001-01-01T00:00:00Z',
price: 0
}])).toEqual([...api.results.tokens, {
application: 'coin',
decimals: 6,
description: '',
fingerprint: '',
id: '.',
name: 'Cardano',
nature: 'primary',
originalImage: '',
reference: '',
status: 'valid',
symbol: 'ADA',
tag: '',
ticker: 'ADA',
type: 'ft',
website: ''
}]);
});
test('should correctly transform the token id', () => {
expect(transformers.tokens.fromId(ptIdDh)).toBe(primaryTokenInfo.id);
expect(transformers.tokens.toId(primaryTokenInfo.id)).toBe('ADA');
});
});
describe('orders', () => {
test('should correctly transform the orders response', () => {
expect(transformers.orders.response([...api.responses.orders, {
_id: '66cf043794579f05fc204f72',
dex: 'SUNDAESWAP',
user_address: 'addr1q9qhyvkm5fytm5ckgshny0zz08a3urhhh7ckdqxcm27av40eafn3v5lr2w2n2er9uj7c743mt42gpe8tgek6394z9t7qn4yjzl',
user_stake: 'stake1u8u75eck203489f4v3j7f0v02ca464yqun45vmdgj63z4lqm9pu9k',
submission_time: undefined,
last_update: undefined,
output_index: 0,
is_stop_loss: false,
is_oor: false,
batcher_fee: 2.5,
deposit: 2,
status: 'PENDING'
}])).toEqual([...api.results.orders, {
actualAmountOut: 0,
aggregator: 'muesliswap',
amountIn: 0,
customId: '66cf043794579f05fc204f72',
expectedAmountOut: 0,
lastUpdate: undefined,
placedAt: undefined,
outputIndex: 0,
protocol: 'sundaeswap-v1',
status: 'open',
tokenIn: '.',
tokenOut: '.',
txHash: '',
updateTxHash: ''
}]);
});
});
describe('cancel', () => {
test('should correctly transform the cancel request', () => {
expect(transformers.cancel.request(api.inputs.cancel)).toEqual(api.requests.cancel(address));
});
test('should correctly transform the cancel request to default', () => {
expect(transformers.cancel.request(api.inputs.cancel)).toEqual(api.requests.cancel(address));
});
test('should correctly transform the cancel response to default', () => {
expect(transformers.cancel.response({
additional_cancellation_fee: 2_000_000
})).toEqual({
cbor: '',
additionalCancellationFee: 2_000_000
});
});
test('should correctly transform the cancel response', () => {
expect(transformers.cancel.response(api.responses.cancel)).toEqual(api.results.cancel);
});
});
describe('estimate', () => {
test('should correctly transform the estimate request', () => {
expect(transformers.estimate.request(api.inputs.estimate)).toEqual(api.requests.estimate);
});
test('should correctly transform the estimate response', () => {
expect(transformers.estimate.response(api.responses.estimate)).toEqual(api.results.estimate);
});
test('should correctly transform the estimate response 2', () => {
expect(transformers.estimate.response({
splits: [{
expected_output: 9223372036854.775,
expected_output_without_slippage: 9223372036854.775,
fee: 4,
dex: 'VYFI',
price_impact: 843546.4933049141,
initial_price: 0.00011853462095991185,
final_price: 1.0000131730805681,
pool_id: '000000000000000000000000000000000000000000000000000000006c6f76656c616365af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950VYFIaddr1wx6vzxyapfw4f4ragkvqtk3y473wj4sul3fr98xhguvazlse88lan',
batcher_fee: 2,
deposits: 2,
price_distortion: 841015.5508249996,
pool_fee: 0.003
}],
total_fee: 4,
total_output: 0,
deposits: 2,
batcher_fee: 2,
total_input: 1000000000000000,
possible_routes: {},
net_price: 0,
net_price_reverse: 0,
dexhunter_fee: 1,
blacklisted_dexes: null,
partner: '',
partner_fee: 0
}, true)).toEqual({
aggregatorFee: 1,
batcherFee: 2,
deposits: 2,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [{
amountIn: 0,
batcherFee: 2,
deposits: 2,
expectedOutput: 9223372036854.775,
expectedOutputWithoutSlippage: 9223372036854.775,
fee: 4,
finalPrice: 1.0000131730805681,
initialPrice: 0.00011853462095991185,
poolFee: 0.003,
poolId: '000000000000000000000000000000000000000000000000000000006c6f76656c616365af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950VYFIaddr1wx6vzxyapfw4f4ragkvqtk3y473wj4sul3fr98xhguvazlse88lan',
priceDistortion: 841015.5508249996,
priceImpact: 843546.4933049141,
protocol: 'vyfi-v1'
}],
totalFee: 3,
totalInput: 0,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
test('should correctly transform the estimate response to defaults', () => {
expect(transformers.estimate.response({
total_input: 1000000000000000,
possible_routes: {},
blacklisted_dexes: null,
partner: ''
})).toEqual({
aggregatorFee: 0,
batcherFee: 0,
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [],
totalFee: 0,
totalInput: undefined,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
});
describe('reverseEstimate', () => {
test('should correctly transform the reverse estimate request', () => {
expect(transformers.reverseEstimate.request(api.inputs.reverseEstimate)).toEqual(api.requests.reverseEstimate);
});
test('should correctly transform the reverse estimate response', () => {
expect(transformers.reverseEstimate.response(api.responses.reverseEstimate)).toEqual(api.results.reverseEstimate);
});
test('should correctly transform the reverse estimate response to default', () => {
expect(transformers.reverseEstimate.response({
possible_routes: {},
total_input_without_slippage: 0.0045599187141238265
}, true)).toEqual({
aggregatorFee: 0,
batcherFee: 0,
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [],
totalFee: 0,
totalInput: undefined,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
test('should correctly transform the reverse estimate response to default with speacial splits', () => {
expect(transformers.reverseEstimate.response({
splits: [{
expected_output: 35.288684,
expected_output_without_slippage: 37.145984,
fee: 4,
dex: 'MINSWAP',
price_impact: 0.0013874760358920197,
initial_price: 0.00012238115855095046,
final_price: 0.0001223828565601978,
pool_id: '000000000000000000000000000000000000000000000000000000006c6f76656c616365af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950MINSWAPc1245066d133f864ff9220aabb1388bb801986e6da6754b8234ce8fc3c6029f6',
batcher_fee: 2,
deposits: 2,
price_distortion: 0.30161668639221895,
pool_fee: 0.003
}],
possible_routes: {},
total_input_without_slippage: 0.0045599187141238265,
net_price_reverse: 122.75670807707843
})).toEqual({
aggregatorFee: 0,
batcherFee: 0,
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [{
amountIn: 0,
batcherFee: 2,
deposits: 2,
expectedOutput: 35.288684,
expectedOutputWithoutSlippage: 37.145984,
fee: 4,
finalPrice: 0.0001223828565601978,
initialPrice: 0.00012238115855095046,
poolFee: 0.003,
poolId: '000000000000000000000000000000000000000000000000000000006c6f76656c616365af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950MINSWAPc1245066d133f864ff9220aabb1388bb801986e6da6754b8234ce8fc3c6029f6',
priceDistortion: 0.30161668639221895,
priceImpact: 0.0013874760358920197,
protocol: 'minswap-v1'
}],
totalInput: 0,
totalFee: 0,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
});
describe('limitEstimate', () => {
test('should correctly transform the limit estimate request', () => {
expect(transformers.limitEstimate.request(api.inputs.limitEstimate)).toEqual(api.requests.limitEstimate);
});
test('should correctly transform the limit estimate request to default', () => {
expect(transformers.limitEstimate.request({
tokenIn: '.',
tokenOut: 'af2e27f580f7f08e93190a81f72462f153026d06450924726645891b.44524950',
amountIn: 38,
protocol: undefined,
blockedProtocols: ['wingriders-v1'],
amountOut: undefined,
multiples: undefined,
wantedPrice: 1,
slippage: 0
})).toEqual({
amount_in: 38,
blacklisted_dexes: ['WINGRIDER'],
dex: 'UNSUPPORTED',
multiples: 1,
token_in: 'ADA',
token_out: 'af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950',
wanted_price: 1
});
});
test('should correctly transform the limit estimate response to default', () => {
expect(transformers.limitEstimate.response({
total_fee: undefined,
total_output: undefined,
deposits: undefined,
batcher_fee: undefined,
total_input: undefined,
possible_routes: {},
net_price: undefined,
dexhunter_fee: undefined,
blacklisted_dexes: null,
partner: '',
partner_fee: undefined
}, false)).toEqual({
aggregatorFee: 0,
batcherFee: 0,
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [],
totalFee: 0,
totalInput: undefined,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
test('should correctly transform the limit estimate response to default with special split case', () => {
expect(transformers.limitEstimate.response({
total_fee: undefined,
total_output: undefined,
deposits: undefined,
batcher_fee: undefined,
total_input: undefined,
possible_routes: {},
net_price: undefined,
dexhunter_fee: undefined,
blacklisted_dexes: null,
partner: '',
partner_fee: undefined,
splits: [{
expected_output: 9223372036854.775,
expected_output_without_slippage: 9223372036854.775,
fee: 4,
dex: 'VYFI',
price_impact: 874011.5392608035,
initial_price: 0.00011440337320702896,
final_price: 1.0000130865062424,
pool_id: '000000000000000000000000000000000000000000000000000000006c6f76656c616365af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950VYFIaddr1wx6vzxyapfw4f4ragkvqtk3y473wj4sul3fr98xhguvazlse88lan',
batcher_fee: 2,
deposits: 2,
price_distortion: 871389.201643021,
pool_fee: 0.003
}]
}, false)).toEqual({
aggregatorFee: 0,
batcherFee: 0,
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
totalFee: 0,
totalInput: 0,
totalOutput: 0,
totalOutputWithoutSlippage: 0,
splits: [{
amountIn: 0,
batcherFee: 2,
deposits: 2,
expectedOutput: 9223372036854.775,
expectedOutputWithoutSlippage: 9223372036854.775,
fee: 4,
finalPrice: 1.0000130865062424,
initialPrice: 0.00011440337320702896,
poolFee: 0.003,
poolId: '000000000000000000000000000000000000000000000000000000006c6f76656c616365af2e27f580f7f08e93190a81f72462f153026d06450924726645891b44524950VYFIaddr1wx6vzxyapfw4f4ragkvqtk3y473wj4sul3fr98xhguvazlse88lan',
priceDistortion: 871389.201643021,
priceImpact: 874011.5392608035,
protocol: 'vyfi-v1'
}]
});
});
test('should correctly transform the limit estimate response', () => {
expect(transformers.limitEstimate.response(api.responses.limitEstimate, false)).toEqual(api.results.limitEstimate);
});
});
describe('limitBuild', () => {
test('should correctly transform the limit build request to default', () => {
expect(transformers.limitBuild.request(api.inputs.create[0])).toEqual(api.requests.limitBuild);
});
test('should correctly transform the limit build request', () => {
expect(transformers.limitBuild.request({
...api.inputs.create[0],
protocol: 'minswap-v1',
amountIn: 1,
tokenIn: '.',
tokenOut: 'abc.cbr'
})).toEqual({
...api.requests.limitBuild,
dex: 'MINSWAP',
token_out: 'abccbr'
});
});
test('should correctly transform the limit build request alt', () => {
expect(transformers.limitBuild.request({
...api.inputs.create[2],
protocol: 'minswap-v1',
amountIn: 1,
tokenIn: '.',
tokenOut: 'abc.cbr'
})).toEqual({
...api.requests.limitBuild,
dex: 'MINSWAP',
token_out: 'abccbr',
wanted_price: 1
});
});
test('should correctly transform the limit build response', () => {
expect(transformers.limitBuild.response(api.responses.limitBuild, false)).toEqual({
aggregator: 'dexhunter',
aggregatorFee: 0,
batcherFee: 0,
cbor: '84a500838258203976997901257e283cc9da856b9e50174c4eb9dfd8ce55b5be9fbe2f9289577500825820475ffb1f1820eee1790729d86ced473e9f7724ddcd7bf59b477e3293415f16bf03825820e22c3b1fd8e77643612bb2611e8fb74238ba540867dd9d4ecaec1590c613566400018283583911a65ca58a4e9c755fa830173d2a5caed458ac0c73f97db7faae2e7e3b52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c21a004c4b40582079aaea3504c39973f6bd387a2250e3553220722f429ffddbf6dae7f3c7bfb61c825839014747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aecf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdc821a005a5946ac581c2441ab3351c3b80213a98f4e09ddcf7dabe4879c3c94cc4e7205cb63a144464952451909e3581c279c909f348e533da5808898f87f9a14bb2c3dfbbacccd631d927a3fa144534e454b18cc581c4cb48d60d1f7823d1307c61b9ecf472ff78cf22d1ccc5786d59461f8a1474144414d4f4f4e1a004c3d2e581c8654e8b350e298c80d2451beb5ed80fc9eee9f38ce6b039fb8706bc3a1474c4f42535445521a0010f66f581ca0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235a145484f534b591a06e8f5c4581cafbe91c0b44b3040e360057bf8354ead8c49c4979ae6ab7c4fbdc9eba1464d494c4b76321a00424fe1581cb788fbee71a32d2efc5ee7d151f3917d99160f78fb1e41a1bbf80d8fa1494c454146544f4b454e1b0000000536f5613f581cc5609c4800c05e82c4219ccf14c7fdf5212e11f83dbbb57ac716e98ea145666c756666186f581cc898c986b97e7ac5b33e999bc11b054a9987f48ec4459f8c1ea0c32ba148435245414d5049451a06a21941581ccdaaee586376139ee8c3cc4061623968810d177ca5c300afb890b48aa144434153541911bd581ce0c4c2d7c4a0ed2cf786753fd845dee82c45512cee03e92adfd3fb8da14d6a6176696275656e6f2e61646101581cf0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9aa14d000de1406a6176696275656e6f01021a0003388d0758203ee91922e55ac83b91cdce3d7aa8fb01085e26622a6da92bad3908c29cbffca00b582067cbc9782dbb59e371f3dbc4eeba0b20cdeb91e1b7f53efaccd58f78975a50fba10481d8799fd8799fd8799f581c4747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aeffd8799fd8799fd8799f581ccf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdcffffffffd8799fd8799f581c4747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aeffd8799fd8799fd8799f581ccf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdcffffffffd87a80d8799fd8799f581ccdaaee586376139ee8c3cc4061623968810d177ca5c300afb890b48a4443415354ff19046aff1a001e84801a001e8480fff5a11902a2783b7b276d7367273a205b274d7565736c69537761702041676772656761746f7220506c61636520437573746f6d204c696d6974204f72646572275d7d',
deposits: 2,
frontendFee: 0,
netPrice: 0.04252918925670425,
splits: [{
amountIn: 1,
batcherFee: 2,
deposits: 2,
expectedOutput: 1130,
expectedOutputWithoutSlippage: 1130,
fee: 0.3,
finalPrice: 0.041994,
initialPrice: 0.04252918925670425,
poolFee: 0.3,
poolId: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
priceDistortion: 1.258404559451805,
priceImpact: 1.258404559451805,
protocol: 'minswap-v1'
}],
priceImpact: 1.258404559451805,
totalFee: 0,
totalInput: 1,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
test('should correctly transform the limit build response (speacial case)', () => {
expect(transformers.limitBuild.response({
cbor: '84a500838258203976997901257e283cc9da856b9e50174c4eb9dfd8ce55b5be9fbe2f9289577500825820475ffb1f1820eee1790729d86ced473e9f7724ddcd7bf59b477e3293415f16bf03825820e22c3b1fd8e77643612bb2611e8fb74238ba540867dd9d4ecaec1590c613566400018283583911a65ca58a4e9c755fa830173d2a5caed458ac0c73f97db7faae2e7e3b52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c21a004c4b40582079aaea3504c39973f6bd387a2250e3553220722f429ffddbf6dae7f3c7bfb61c825839014747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aecf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdc821a005a5946ac581c2441ab3351c3b80213a98f4e09ddcf7dabe4879c3c94cc4e7205cb63a144464952451909e3581c279c909f348e533da5808898f87f9a14bb2c3dfbbacccd631d927a3fa144534e454b18cc581c4cb48d60d1f7823d1307c61b9ecf472ff78cf22d1ccc5786d59461f8a1474144414d4f4f4e1a004c3d2e581c8654e8b350e298c80d2451beb5ed80fc9eee9f38ce6b039fb8706bc3a1474c4f42535445521a0010f66f581ca0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235a145484f534b591a06e8f5c4581cafbe91c0b44b3040e360057bf8354ead8c49c4979ae6ab7c4fbdc9eba1464d494c4b76321a00424fe1581cb788fbee71a32d2efc5ee7d151f3917d99160f78fb1e41a1bbf80d8fa1494c454146544f4b454e1b0000000536f5613f581cc5609c4800c05e82c4219ccf14c7fdf5212e11f83dbbb57ac716e98ea145666c756666186f581cc898c986b97e7ac5b33e999bc11b054a9987f48ec4459f8c1ea0c32ba148435245414d5049451a06a21941581ccdaaee586376139ee8c3cc4061623968810d177ca5c300afb890b48aa144434153541911bd581ce0c4c2d7c4a0ed2cf786753fd845dee82c45512cee03e92adfd3fb8da14d6a6176696275656e6f2e61646101581cf0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9aa14d000de1406a6176696275656e6f01021a0003388d0758203ee91922e55ac83b91cdce3d7aa8fb01085e26622a6da92bad3908c29cbffca00b582067cbc9782dbb59e371f3dbc4eeba0b20cdeb91e1b7f53efaccd58f78975a50fba10481d8799fd8799fd8799f581c4747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aeffd8799fd8799fd8799f581ccf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdcffffffffd8799fd8799f581c4747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aeffd8799fd8799fd8799f581ccf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdcffffffffd87a80d8799fd8799f581ccdaaee586376139ee8c3cc4061623968810d177ca5c300afb890b48a4443415354ff19046aff1a001e84801a001e8480fff5a11902a2783b7b276d7367273a205b274d7565736c69537761702041676772656761746f7220506c61636520437573746f6d204c696d6974204f72646572275d7d',
deposits: 2,
splits: [{
batcher_fee: 2,
deposits: 2,
expected_output: 1130,
expected_output_without_slippage: 1130,
fee: 0.3,
final_price: 0.041994,
initial_price: 0.04252918925670425,
pool_fee: 0.3,
pool_id: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
price_distortion: 1.258404559451805,
price_impact: 1.258404559451805,
dex: 'MINSWAP'
}],
totalFee: 4
}, false)).toEqual({
aggregator: 'dexhunter',
aggregatorFee: 0,
batcherFee: 0,
cbor: '84a500838258203976997901257e283cc9da856b9e50174c4eb9dfd8ce55b5be9fbe2f9289577500825820475ffb1f1820eee1790729d86ced473e9f7724ddcd7bf59b477e3293415f16bf03825820e22c3b1fd8e77643612bb2611e8fb74238ba540867dd9d4ecaec1590c613566400018283583911a65ca58a4e9c755fa830173d2a5caed458ac0c73f97db7faae2e7e3b52563c5410bff6a0d43ccebb7c37e1f69f5eb260552521adff33b9c21a004c4b40582079aaea3504c39973f6bd387a2250e3553220722f429ffddbf6dae7f3c7bfb61c825839014747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aecf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdc821a005a5946ac581c2441ab3351c3b80213a98f4e09ddcf7dabe4879c3c94cc4e7205cb63a144464952451909e3581c279c909f348e533da5808898f87f9a14bb2c3dfbbacccd631d927a3fa144534e454b18cc581c4cb48d60d1f7823d1307c61b9ecf472ff78cf22d1ccc5786d59461f8a1474144414d4f4f4e1a004c3d2e581c8654e8b350e298c80d2451beb5ed80fc9eee9f38ce6b039fb8706bc3a1474c4f42535445521a0010f66f581ca0028f350aaabe0545fdcb56b039bfb08e4bb4d8c4d7c3c7d481c235a145484f534b591a06e8f5c4581cafbe91c0b44b3040e360057bf8354ead8c49c4979ae6ab7c4fbdc9eba1464d494c4b76321a00424fe1581cb788fbee71a32d2efc5ee7d151f3917d99160f78fb1e41a1bbf80d8fa1494c454146544f4b454e1b0000000536f5613f581cc5609c4800c05e82c4219ccf14c7fdf5212e11f83dbbb57ac716e98ea145666c756666186f581cc898c986b97e7ac5b33e999bc11b054a9987f48ec4459f8c1ea0c32ba148435245414d5049451a06a21941581ccdaaee586376139ee8c3cc4061623968810d177ca5c300afb890b48aa144434153541911bd581ce0c4c2d7c4a0ed2cf786753fd845dee82c45512cee03e92adfd3fb8da14d6a6176696275656e6f2e61646101581cf0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9aa14d000de1406a6176696275656e6f01021a0003388d0758203ee91922e55ac83b91cdce3d7aa8fb01085e26622a6da92bad3908c29cbffca00b582067cbc9782dbb59e371f3dbc4eeba0b20cdeb91e1b7f53efaccd58f78975a50fba10481d8799fd8799fd8799f581c4747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aeffd8799fd8799fd8799f581ccf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdcffffffffd8799fd8799f581c4747a9606da0c06ef08fddf31a89a604fc15584ac00ff1bf88dfc1aeffd8799fd8799fd8799f581ccf085cc39aa4ff52de1ea606ee581aac1dab8166d6830e7a9b6cecdcffffffffd87a80d8799fd8799f581ccdaaee586376139ee8c3cc4061623968810d177ca5c300afb890b48a4443415354ff19046aff1a001e84801a001e8480fff5a11902a2783b7b276d7367273a205b274d7565736c69537761702041676772656761746f7220506c61636520437573746f6d204c696d6974204f72646572275d7d',
deposits: 2,
frontendFee: 0,
priceImpact: 0,
netPrice: 0.04252918925670425,
splits: [{
amountIn: 0,
batcherFee: 2,
deposits: 2,
expectedOutput: 1130,
expectedOutputWithoutSlippage: 1130,
fee: 0.3,
finalPrice: 0.041994,
initialPrice: 0.04252918925670425,
poolFee: 0.3,
poolId: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
priceDistortion: 1.258404559451805,
priceImpact: 1.258404559451805,
protocol: 'minswap-v1'
}],
totalFee: 0,
totalInput: 0,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
});
describe('build', () => {
test('should correctly transform the build request', async () => {
expect(transformers.build.request(api.inputs.create[1])).toEqual(api.requests.build);
});
test('should correctly transform the build request to default', async () => {
expect(transformers.build.request(api.inputs.create[0])).toEqual({
...api.requests.build,
slippage: 0
});
});
test('should correctly transform the build response', async () => {
expect(transformers.build.response(api.responses.build)).toEqual({
aggregator: 'dexhunter',
aggregatorFee: 0.002,
batcherFee: 0.001,
cbor: 'a1b2c3d4e5f6',
deposits: 1000,
frontendFee: 0.003,
netPrice: 1.23,
priceImpact: 1.258404559451805,
splits: [{
amountIn: 1,
batcherFee: 2,
deposits: 2,
expectedOutput: 1130,
expectedOutputWithoutSlippage: 1130,
fee: 0.3,
finalPrice: 0.041994,
initialPrice: 0.04252918925670425,
poolFee: 0.3,
poolId: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
priceDistortion: 1.258404559451805,
priceImpact: 1.258404559451805,
protocol: 'minswap-v1'
}],
totalFee: 0.006,
totalInput: 500,
totalOutput: 495,
totalOutputWithoutSlippage: 500
});
});
test('should correctly transform the build response to defaults', async () => {
expect(transformers.build.response({
average_price: 1.234,
communications: ['Success', 'Transaction confirmed'],
net_price_reverse: 0.812,
partner_code: 'PartnerX',
possible_routes: {
route1: 0.5,
route2: 0.3,
route3: 0.2
},
splits: [{
amount_in: 1,
batcher_fee: 2,
deposits: 2,
expected_output: 1130,
expected_output_without_slippage: 1130,
fee: 0.3,
final_price: 0.041994,
initial_price: 0.04252918925670425,
pool_fee: 0.3,
pool_id: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
price_distortion: 1.258404559451805,
price_impact: 1.258404559451805,
dex: 'MINSWAP'
}],
total_input_without_slippage: 505
})).toEqual({
aggregator: 'dexhunter',
aggregatorFee: 0,
batcherFee: 0,
cbor: '',
deposits: 0,
frontendFee: 0,
netPrice: 0.04252918925670425,
priceImpact: 1.258404559451805,
splits: [{
amountIn: 1,
batcherFee: 2,
deposits: 2,
expectedOutput: 1130,
expectedOutputWithoutSlippage: 1130,
fee: 0.3,
finalPrice: 0.041994,
initialPrice: 0.04252918925670425,
poolFee: 0.3,
poolId: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
priceDistortion: 1.258404559451805,
priceImpact: 1.258404559451805,
protocol: 'minswap-v1'
}],
totalFee: 0,
totalInput: 1,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
test('should correctly transform the build response to defaults (special case)', async () => {
expect(transformers.build.response({
average_price: 1.234,
communications: ['Success', 'Transaction confirmed'],
net_price_reverse: 0,
partner_code: 'PartnerX',
possible_routes: {
route1: 0.5,
route2: 0.3,
route3: 0.2
},
splits: [{
batcher_fee: 2,
deposits: 2,
expected_output: 1130,
expected_output_without_slippage: 1130,
fee: 0.3,
final_price: 0.041994,
initial_price: undefined,
pool_fee: 0.3,
pool_id: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
price_distortion: 1.258404559451805,
price_impact: 1.258404559451805,
dex: 'MINSWAP'
}],
total_input_without_slippage: 505
}, true)).toEqual({
aggregator: 'dexhunter',
aggregatorFee: 0,
batcherFee: 0,
cbor: '',
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [{
amountIn: 0,
batcherFee: 2,
deposits: 2,
expectedOutput: 1130,
expectedOutputWithoutSlippage: 1130,
fee: 0.3,
finalPrice: 0.041994,
initialPrice: 0,
poolFee: 0.3,
poolId: '0be55d262b29f564998ff81efe21bdc0022621c12f15af08d0f2ddb1.3513ef4f9724b1bdbedd1f606ed93368f0442b236f3ff201bb28532cdf2a53a9',
priceDistortion: 1.258404559451805,
priceImpact: 1.258404559451805,
protocol: 'minswap-v1'
}],
totalFee: 0,
totalInput: 0,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
test('should correctly transform the build response to defaults (special case 2)', async () => {
expect(transformers.build.response({
average_price: 1.234,
communications: ['Success', 'Transaction confirmed'],
net_price_reverse: 0.812,
partner_code: 'PartnerX',
possible_routes: {
route1: 0.5,
route2: 0.3,
route3: 0.2
},
total_input_without_slippage: 505
})).toEqual({
aggregator: 'dexhunter',
aggregatorFee: 0,
batcherFee: 0,
cbor: '',
deposits: 0,
frontendFee: 0,
netPrice: 0,
priceImpact: 0,
splits: [],
totalFee: 0,
totalInput: 0,
totalOutput: 0,
totalOutputWithoutSlippage: 0
});
});
});
});
describe('toSwapSplit', () => {
it('should convert input object to Swap.Split format with defaults', () => {
const input = {};
const expectedOutput = {
amountIn: 0,
batcherFee: 0,
deposits: 0,
protocol: 'unsupported',
expectedOutput: 0,
expectedOutputWithoutSlippage: 0,
fee: 0,
finalPrice: 0,
initialPrice: 0,
poolFee: 0,
poolId: '',
priceDistortion: 0,
priceImpact: 0
};
expect(toSwapSplit(input)).toEqual(expectedOutput);
});
it('should correctly map input values to output structure', () => {
const input = {
amount_in: 100,
batcher_fee: 2,
deposits: 50,
dex: 'MINSWAP',
expected_output: 95,
expected_output_without_slippage: 98,
fee: 1,
final_price: 1.1,
initial_price: 1.0,
pool_fee: 0.3,
pool_id: 'pool-123',
price_distortion: 0.05,
price_impact: 0.02
};
const expectedOutput = {
amountIn: 100,
batcherFee: 2,
deposits: 50,
protocol: 'minswap-v1',
expectedOutput: 95,
expectedOutputWithoutSlippage: 98,
fee: 1,
finalPrice: 1.1,
initialPrice: 1.0,
poolFee: 0.3,
poolId: 'pool-123',
priceDistortion: 0.05,
priceImpact: 0.02
};
expect(toSwapSplit(input)).toEqual(expectedOutput);
});
});
import { toPriceImpact } from './transformers';
describe('toPriceImpact', () => {
it('should calculate the weighted average price impact correctly', () => {
const splits = [{
amount_in: 100,
price_impact: 0.02
}, {
amount_in: 200,
price_impact: 0.03
}, {
amount_in: 300,
price_impact: 0.01
}];
const result = toPriceImpact(splits);
expect(result).toBeCloseTo(0.018333333, 5); // Weighted average is 0.02
});
it('should return 0 if total amount_in is 0', () => {
const splits = [{
amount_in: 0,
price_impact: 0.02
}, {
amount_in: 0,
price_impact: 0.03
}];
const result = toPriceImpact(splits);
expect(result).toBe(0);
});
it('should handle missing price_impact or amount_in gracefully', () => {
const splits = [{
amount_in: 100,
price_impact: undefined
}, {
amount_in: undefined,
price_impact: 0.03
}, {
amount_in: 300,
price_impact: 0.01
}];
const result = toPriceImpact(splits);
expect(result).toBeCloseTo(0.0075, 5); // Weighted average is (300 * 0.01) / 400
});
it('should return 0 for an empty array', () => {
const splits = [];
const result = toPriceImpact(splits);
expect(result).toBe(0);
});
});
describe('toSwapProtocol', () => {
it.each`
dex | protocol
${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_v2} | ${Swap.Protocol.Muesliswap_v2}
${Dex.Muesliswap_clp} | ${Swap.Protocol.Muesliswap_clp}
${Dex.Unsupported} | ${Swap.Protocol.Unsupported}
${'new-protocol'} | ${Swap.Protocol.Unsupported}
`('should map $dex to $protocol', ({
dex,
protocol
}) => {
expect(toSwapProtocol(dex)).toBe(protocol);
});
});
describe('fromSwapProtocol', () => {
it.each`
protocol | dex
${Swap.Protocol.Minswap_v1} | ${Dex.Minswap_v1}
${Swap.Protocol.Minswap_v2} | ${Dex.Minswap_v2}
${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.Muesliswap_v2} | ${Dex.Muesliswap_v2}
${Swap.Protocol.Muesliswap_clp} | ${Dex.Muesliswap_clp}
${Swap.Protocol.Teddy_v1} | ${Dex.Unsupported}
${Swap.Protocol.Minswap_stable} | ${Dex.Unsupported}
${Swap.Protocol.Spectrum_v1} | ${Dex.Unsupported}
${Swap.Protocol.Unsupported} | ${Dex.Unsupported}
${'new-protocol'} | ${Dex.Unsupported}
`('should map $protocol to $dex', ({
protocol,
dex
}) => {
expect(fromSwapProtocol(protocol)).toBe(dex);
});
});
describe('reverse', () => {
it('should return the same price if reversed is false', () => {
const result = reverse(false, 100);
expect(result).toBe(100);
});
it('should return the same price if price is 0', () => {
const result = reverse(true, 0);
expect(result).toBe(0);
});
it('should return the same price if price is undefined', () => {
const result = reverse(true, undefined);
expect(result).toBe(undefined);
});
it('should return the reciprocal of the price if reversed is true and price is valid', () => {
const result = reverse(true, 100);
expect(result).toBe(1 / 100);
});
it('should handle edge cases for very small prices', () => {
const result = reverse(true, 0.0001);
expect(result).toBeCloseTo(10000, 5);
});
it('should handle edge cases for very large prices', () => {
const result = reverse(true, 1000000);
expect(result).toBeCloseTo(0.000001, 6);
});
});
//# sourceMappingURL=transformers.test.js.map