Files
protocol/apps-node/rfq-api/test/utils/MetaTransactionClient.test.ts

891 lines
73 KiB
TypeScript

import { ValidationError } from '@0x/api-utils';
import { BigNumber } from '@0x/utils';
import Axios, { AxiosInstance } from 'axios';
import AxiosMockAdapter from 'axios-mock-adapter';
import { BAD_REQUEST, NOT_ACCEPTABLE, OK } from 'http-status-codes';
import { APIErrorCodes, apiErrorCodesToReasons } from '../../src/core/errors';
import { getV1QuoteAsync, getV2QuoteAsync } from '../../src/utils/MetaTransactionClient';
import { GaslessTypes } from '../../src/core/types';
let axiosClient: AxiosInstance;
let axiosMock: AxiosMockAdapter;
describe('MetaTransactionClient', () => {
const integratorAddress = '0x4ea754349ace5303c82f0d1d491041e042f2ad22';
const zeroExAddress = '0x4ea754349ace5303c82f0d1d491041e042f2ad22';
beforeAll(() => {
axiosClient = Axios.create();
axiosMock = new AxiosMockAdapter(axiosClient);
});
describe('getV1QuoteAsync', () => {
it('should get a metatransaction quote', async () => {
const exampleSuccessfulResponse = {
allowanceTarget: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
buyAmount: '1800054805473',
buyTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
buyTokenToEthRate: '0.851202',
chainId: 137,
estimatedGas: '1043459',
estimatedPriceImpact: '1.6301',
gas: '1043459',
gasPrice: '115200000000',
minimumProtocolFee: '0',
metaTransaction: {
callData:
'0x415565b00000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000019eeab6030b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000002517569636b5377617000000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003f47a215c5000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000002517569636b53776170000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f2c6f738e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000b446f646f5632000000000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f811895a7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000005333eb1e32522f1893b7c9fea3c263807a02d561000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000012556e697377617056330000000000000000000000000000000000000000000000000000000000001d30a7ac56da56396a000000000000000000000000000000000000000000000000000000e10b7768e500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012556e6973776170563300000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003fea147b29000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000427ceb23fd6bc0add59e62ac25578270cff1b9f6190001f41bfd67037b42cf73acf2047067bd4f2c47d9bfd6000bb82791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f619000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000008c611defbd838a13de3a5923693c58a7c1807c630000000000000000000000000000000000000000000000f789bac21b62fed5ef',
domain: {
chainId: 137,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
},
expirationTimeSeconds: '1660868679',
feeAmount: '0',
feeToken: '0x0000000000000000000000000000000000000000',
maxGasPrice: '4294967296',
minGasPrice: '1',
salt: '32606650794224189614795510724011106220035660490560169776986607186708081701146',
sender: '0x0000000000000000000000000000000000000000',
signer: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
value: '0',
},
metaTransactionHash: '0x16688406783c0e721a69e5c9f2727e2d30f24a0669522c1fb6937460348b4095',
price: '1800.054805',
protocolFee: '0',
sellAmount: '1000000000000000000000',
sellTokenAddress: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
sellTokenToEthRate: '0.000465167371348443',
sources: [
{
name: 'SushiSwap',
proportion: '0',
},
{
name: 'QuickSwap',
proportion: '0.2308',
},
{
name: 'DODO_V2',
proportion: '0.07692',
},
{
name: 'Uniswap_V3',
proportion: '0.6923',
},
],
value: '0',
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onGet(url.toString()).replyOnce(OK, exampleSuccessfulResponse);
const response = await getV1QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: 'WETH',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
});
expect(response?.trade.kind).toEqual(GaslessTypes.MetaTransaction);
expect(response?.trade.metaTransaction.getHash()).toEqual(exampleSuccessfulResponse.metaTransactionHash);
expect(response?.price).toEqual({
buyAmount: new BigNumber(exampleSuccessfulResponse.buyAmount),
buyTokenAddress: exampleSuccessfulResponse.buyTokenAddress,
gas: new BigNumber(exampleSuccessfulResponse.gas),
price: new BigNumber(exampleSuccessfulResponse.price),
sellAmount: new BigNumber(exampleSuccessfulResponse.sellAmount),
sellTokenAddress: exampleSuccessfulResponse.sellTokenAddress,
});
});
it('should return `null` when no liquidity is available', async () => {
const exampleNoLiquidityResponse = {
code: 100,
reason: 'Validation Failed',
validationErrors: [
{
field: 'sellAmount',
code: 1004,
reason: 'INSUFFICIENT_ASSET_LIQUIDITY',
},
],
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onGet(url.toString()).replyOnce(BAD_REQUEST, exampleNoLiquidityResponse);
const response = await getV1QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
slippagePercentage: new BigNumber(0.2),
});
expect(response).toBeNull();
});
it('should throw validation error when meta-transaction server returns the insufficient fund error', async () => {
const exampleInsufficientFundErrorResponse = {
code: APIErrorCodes.InsufficientFundsError,
reason: apiErrorCodesToReasons[APIErrorCodes.InsufficientFundsError],
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onGet(url.toString()).reply(BAD_REQUEST, exampleInsufficientFundErrorResponse);
await expect(() =>
getV1QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
slippagePercentage: new BigNumber(0.2),
}),
).rejects.toThrow(ValidationError);
});
it("should throw an error if the response doesn't match the no liquidity response + the insufficient fund error", async () => {
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onGet(url.toString()).replyOnce(NOT_ACCEPTABLE);
await expect(() =>
getV1QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
}),
).rejects.toThrow();
});
it('should throw if computed meta-transaction hash is different from the hash in response', async () => {
const exampleSuccessfulResponse = {
allowanceTarget: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
buyAmount: '1800054805473',
buyTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
buyTokenToEthRate: '0.851202',
chainId: 137,
estimatedGas: '1043459',
estimatedPriceImpact: '1.6301',
gas: '1043459',
gasPrice: '115200000000',
minimumProtocolFee: '0',
metaTransaction: {
callData:
'0x415565b00000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000019eeab6030b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000002517569636b5377617000000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003f47a215c5000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000002517569636b53776170000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f2c6f738e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000b446f646f5632000000000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f811895a7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000005333eb1e32522f1893b7c9fea3c263807a02d561000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000012556e697377617056330000000000000000000000000000000000000000000000000000000000001d30a7ac56da56396a000000000000000000000000000000000000000000000000000000e10b7768e500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012556e6973776170563300000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003fea147b29000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000427ceb23fd6bc0add59e62ac25578270cff1b9f6190001f41bfd67037b42cf73acf2047067bd4f2c47d9bfd6000bb82791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f619000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000008c611defbd838a13de3a5923693c58a7c1807c630000000000000000000000000000000000000000000000f789bac21b62fed5ef',
domain: {
chainId: 137,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
},
expirationTimeSeconds: '1660868679',
feeAmount: '0',
feeToken: '0x0000000000000000000000000000000000000000',
maxGasPrice: '4294967296',
minGasPrice: '1',
salt: '32606650794224189614795510724011106220035660490560169776986607186708081701146',
sender: '0x0000000000000000000000000000000000000000',
signer: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
value: '0',
},
metaTransactionHash: '0x16688406783c0e721a69e5c9f2727e2d30f24a0669522c1fb6937460348b4094',
price: '1800.054805',
protocolFee: '0',
sellAmount: '1000000000000000000000',
sellTokenAddress: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
sellTokenToEthRate: '0.000465167371348443',
sources: [
{
name: 'SushiSwap',
proportion: '0',
},
{
name: 'QuickSwap',
proportion: '0.2308',
},
{
name: 'DODO_V2',
proportion: '0.07692',
},
{
name: 'Uniswap_V3',
proportion: '0.6923',
},
],
value: '0',
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onGet(url.toString()).replyOnce(OK, exampleSuccessfulResponse);
await expect(() =>
getV1QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: 'WETH',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
}),
).rejects.toThrow();
});
});
describe('getV2QuoteAsync', () => {
it('should get a metatransaction quote when requested meta-transaction version is v1', async () => {
const exampleSuccessfulResponse = {
allowanceTarget: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
buyAmount: '1800054805473',
buyTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
buyTokenToEthRate: '0.851202',
chainId: 137,
estimatedGas: '1043459',
estimatedPriceImpact: '1.6301',
gas: '1043459',
gasPrice: '115200000000',
minimumProtocolFee: '0',
trade: {
kind: 'metatransaction',
hash: '0x16688406783c0e721a69e5c9f2727e2d30f24a0669522c1fb6937460348b4095',
metaTransaction: {
callData:
'0x415565b00000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000019eeab6030b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000002517569636b5377617000000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003f47a215c5000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000002517569636b53776170000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f2c6f738e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000b446f646f5632000000000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f811895a7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000005333eb1e32522f1893b7c9fea3c263807a02d561000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000012556e697377617056330000000000000000000000000000000000000000000000000000000000001d30a7ac56da56396a000000000000000000000000000000000000000000000000000000e10b7768e500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012556e6973776170563300000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003fea147b29000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000427ceb23fd6bc0add59e62ac25578270cff1b9f6190001f41bfd67037b42cf73acf2047067bd4f2c47d9bfd6000bb82791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f619000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000008c611defbd838a13de3a5923693c58a7c1807c630000000000000000000000000000000000000000000000f789bac21b62fed5ef',
chainId: 137,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
expirationTimeSeconds: '1660868679',
feeAmount: '0',
feeToken: '0x0000000000000000000000000000000000000000',
maxGasPrice: '4294967296',
minGasPrice: '1',
salt: '32606650794224189614795510724011106220035660490560169776986607186708081701146',
sender: '0x0000000000000000000000000000000000000000',
signer: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
value: '0',
},
},
price: '1800.054805',
protocolFee: '0',
sellAmount: '1000000000000000000000',
sellTokenAddress: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
sellTokenToEthRate: '0.000465167371348443',
sources: [
{
name: 'SushiSwap',
proportion: '0',
},
{
name: 'QuickSwap',
proportion: '0.2308',
},
{
name: '"Aave_V2',
proportion: '0',
},
{
name: 'DODO_V2',
proportion: '0.07692',
},
{
name: 'Uniswap_V3',
proportion: '0.6923',
},
],
value: '0',
fees: {
integratorFee: {
type: 'volume',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '1000000000000000000',
feeRecipient: integratorAddress,
volumePercentage: '0.1',
billingType: 'on-chain',
},
zeroExFee: {
type: 'integrator_share',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '1000000000000000',
feeRecipient: zeroExAddress,
integratorSharePercentage: '0.1',
billingType: 'on-chain',
},
gasFee: {
type: 'gas',
gasPrice: '115200000000',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '10000000',
feeRecipient: null,
estimatedGas: '1043459',
feeTokenAmountPerWei: '0.001',
billingType: 'off-chain',
},
},
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).replyOnce(OK, exampleSuccessfulResponse);
const response = await getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
priceImpactProtectionPercentage: new BigNumber(0.5),
sellToken: 'WETH',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
metaTransactionVersion: 'v1',
});
expect(response?.trade.kind).toEqual(GaslessTypes.MetaTransaction);
expect(response?.trade.metaTransaction.getHash()).toEqual(exampleSuccessfulResponse.trade.hash);
expect(response?.price).toEqual({
buyAmount: new BigNumber(exampleSuccessfulResponse.buyAmount),
buyTokenAddress: exampleSuccessfulResponse.buyTokenAddress,
gas: undefined,
estimatedPriceImpact: new BigNumber(exampleSuccessfulResponse.estimatedPriceImpact),
price: new BigNumber(exampleSuccessfulResponse.price),
sellAmount: new BigNumber(exampleSuccessfulResponse.sellAmount),
sellTokenAddress: exampleSuccessfulResponse.sellTokenAddress,
});
expect(response?.sources).toEqual([
{
name: 'QuickSwap',
proportion: new BigNumber('0.2308'),
},
{
name: 'DODO_V2',
proportion: new BigNumber('0.07692'),
},
{
name: 'Uniswap_V3',
proportion: new BigNumber('0.6923'),
},
]);
expect(response?.fees).toEqual({
integratorFee: {
type: 'volume',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: new BigNumber(1000000000000000000),
feeRecipient: integratorAddress,
volumePercentage: new BigNumber(0.1),
billingType: 'on-chain',
},
zeroExFee: {
type: 'integrator_share',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: new BigNumber(1000000000000000),
feeRecipient: zeroExAddress,
integratorSharePercentage: new BigNumber(0.1),
billingType: 'on-chain',
},
gasFee: {
type: 'gas',
gasPrice: new BigNumber(115200000000),
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: new BigNumber(10000000),
feeRecipient: null,
estimatedGas: new BigNumber(1043459),
feeTokenAmountPerWei: new BigNumber(0.001),
billingType: 'off-chain',
},
});
});
it('should get a metatransaction quote when requested meta-transaction version is v2', async () => {
const exampleSuccessfulResponse = {
allowanceTarget: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
buyAmount: '1800054805473',
buyTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
buyTokenToEthRate: '0.851202',
chainId: 137,
estimatedGas: '1043459',
estimatedPriceImpact: '1.6301',
gas: '1043459',
gasPrice: '115200000000',
minimumProtocolFee: '0',
trade: {
kind: 'metatransaction_v2',
hash: '0x3655b708dad87eb79dee866651b7179b1256caa98840e98335fd7e153c21f9a0',
metaTransaction: {
callData:
'0x415565b00000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000019eeab6030b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000002517569636b5377617000000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003f47a215c5000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000002517569636b53776170000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f2c6f738e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000b446f646f5632000000000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f811895a7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000005333eb1e32522f1893b7c9fea3c263807a02d561000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000012556e697377617056330000000000000000000000000000000000000000000000000000000000001d30a7ac56da56396a000000000000000000000000000000000000000000000000000000e10b7768e500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012556e6973776170563300000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003fea147b29000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000427ceb23fd6bc0add59e62ac25578270cff1b9f6190001f41bfd67037b42cf73acf2047067bd4f2c47d9bfd6000bb82791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f619000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000008c611defbd838a13de3a5923693c58a7c1807c630000000000000000000000000000000000000000000000f789bac21b62fed5ef',
chainId: 137,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
expirationTimeSeconds: '1660868679',
feeToken: '0x0000000000000000000000000000000000000000',
fees: [
{
recipient: integratorAddress,
amount: '999000000000000000',
},
{
recipient: zeroExAddress,
amount: '1000000000000000',
},
],
salt: '32606650794224189614795510724011106220035660490560169776986607186708081701146',
sender: '0x0000000000000000000000000000000000000000',
signer: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
},
},
price: '1800.054805',
protocolFee: '0',
sellAmount: '1000000000000000000000',
sellTokenAddress: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
sellTokenToEthRate: '0.000465167371348443',
sources: [
{
name: 'SushiSwap',
proportion: '0',
},
{
name: 'QuickSwap',
proportion: '0.2308',
},
{
name: '"Aave_V2',
proportion: '0',
},
{
name: 'DODO_V2',
proportion: '0.07692',
},
{
name: 'Uniswap_V3',
proportion: '0.6923',
},
],
value: '0',
fees: {
integratorFee: {
type: 'volume',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '999000000000000000',
feeRecipient: integratorAddress,
volumePercentage: '0.1',
billingType: 'on-chain',
},
zeroExFee: {
type: 'integrator_share',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '1000000000000000',
feeRecipient: zeroExAddress,
integratorSharePercentage: '0.1',
billingType: 'on-chain',
},
gasFee: {
type: 'gas',
gasPrice: '115200000000',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '10000000',
feeRecipient: null,
estimatedGas: '1043459',
feeTokenAmountPerWei: '0.001',
billingType: 'off-chain',
},
},
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).replyOnce(OK, exampleSuccessfulResponse);
const response = await getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
priceImpactProtectionPercentage: new BigNumber(0.5),
sellToken: 'WETH',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
metaTransactionVersion: 'v2',
});
expect(response?.trade.kind).toEqual(GaslessTypes.MetaTransactionV2);
expect(response?.trade.metaTransaction.getHash()).toEqual(exampleSuccessfulResponse.trade.hash);
expect(response?.price).toEqual({
buyAmount: new BigNumber(exampleSuccessfulResponse.buyAmount),
buyTokenAddress: exampleSuccessfulResponse.buyTokenAddress,
gas: undefined,
estimatedPriceImpact: new BigNumber(exampleSuccessfulResponse.estimatedPriceImpact),
price: new BigNumber(exampleSuccessfulResponse.price),
sellAmount: new BigNumber(exampleSuccessfulResponse.sellAmount),
sellTokenAddress: exampleSuccessfulResponse.sellTokenAddress,
});
expect(response?.sources).toEqual([
{
name: 'QuickSwap',
proportion: new BigNumber('0.2308'),
},
{
name: 'DODO_V2',
proportion: new BigNumber('0.07692'),
},
{
name: 'Uniswap_V3',
proportion: new BigNumber('0.6923'),
},
]);
expect(response?.fees).toEqual({
integratorFee: {
type: 'volume',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: new BigNumber(999000000000000000),
feeRecipient: integratorAddress,
volumePercentage: new BigNumber(0.1),
billingType: 'on-chain',
},
zeroExFee: {
type: 'integrator_share',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: new BigNumber(1000000000000000),
feeRecipient: zeroExAddress,
integratorSharePercentage: new BigNumber(0.1),
billingType: 'on-chain',
},
gasFee: {
type: 'gas',
gasPrice: new BigNumber(115200000000),
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: new BigNumber(10000000),
feeRecipient: null,
estimatedGas: new BigNumber(1043459),
feeTokenAmountPerWei: new BigNumber(0.001),
billingType: 'off-chain',
},
});
});
it('should return `null` when no liquidity is available', async () => {
const exampleNoLiquidityResponse = {
code: 100,
reason: 'Validation Failed',
validationErrors: [
{
field: 'sellAmount',
code: 1004,
reason: 'INSUFFICIENT_ASSET_LIQUIDITY',
},
],
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).replyOnce(BAD_REQUEST, exampleNoLiquidityResponse);
const response = await getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
slippagePercentage: new BigNumber(0.2),
});
expect(response).toBeNull();
});
it('should throw validation error when meta-transaction server returns the insufficient fund error', async () => {
const exampleInsufficientFundErrorResponse = {
code: APIErrorCodes.InsufficientFundsError,
reason: apiErrorCodesToReasons[APIErrorCodes.InsufficientFundsError],
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).reply(BAD_REQUEST, exampleInsufficientFundErrorResponse);
await expect(() =>
getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
priceImpactProtectionPercentage: new BigNumber(0.5),
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
slippagePercentage: new BigNumber(0.2),
}),
).rejects.toThrow(ValidationError);
});
it('should throw validation error when meta-transaction server returns the price impact too high error', async () => {
const examplePriceImpactTooHighErrorResponse = {
code: 100,
reason: 'Validation Failed',
validationErrors: [
{
field: 'priceImpactProtectionPercentage',
code: 1004,
reason: 'PRICE_IMPACT_TOO_HIGH',
description:
'estimated price impact of 0.9215 is greater than priceImpactProtectionPercentage 0.5',
},
],
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).reply(BAD_REQUEST, examplePriceImpactTooHighErrorResponse);
await expect(() =>
getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
priceImpactProtectionPercentage: new BigNumber(0.5),
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
slippagePercentage: new BigNumber(0.2),
}),
).rejects.toThrow(ValidationError);
});
it("should throw an error if the response doesn't match the no liquidity response + the insufficient fund error", async () => {
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).replyOnce(NOT_ACCEPTABLE);
await expect(() =>
getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
}),
).rejects.toThrow();
});
it('should throw if computed meta-transaction hash is different from the hash in response when requested meta-transaction version is v1', async () => {
const exampleSuccessfulResponse = {
allowanceTarget: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
buyAmount: '1800054805473',
buyTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
buyTokenToEthRate: '0.851202',
chainId: 137,
estimatedGas: '1043459',
estimatedPriceImpact: '1.6301',
gas: '1043459',
gasPrice: '115200000000',
minimumProtocolFee: '0',
trade: {
kind: 'metatransaction',
hash: '0x16688406783c0e721a69e5c9f2727e2d30f24a0669522c1fb6937460348b4094',
metaTransaction: {
callData:
'0x415565b00000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000019eeab6030b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000002517569636b5377617000000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003f47a215c5000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000002517569636b53776170000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f2c6f738e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000b446f646f5632000000000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f811895a7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000005333eb1e32522f1893b7c9fea3c263807a02d561000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000012556e697377617056330000000000000000000000000000000000000000000000000000000000001d30a7ac56da56396a000000000000000000000000000000000000000000000000000000e10b7768e500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012556e6973776170563300000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003fea147b29000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000427ceb23fd6bc0add59e62ac25578270cff1b9f6190001f41bfd67037b42cf73acf2047067bd4f2c47d9bfd6000bb82791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f619000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000008c611defbd838a13de3a5923693c58a7c1807c630000000000000000000000000000000000000000000000f789bac21b62fed5ef',
chainId: 137,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
expirationTimeSeconds: '1660868679',
feeAmount: '0',
feeToken: '0x0000000000000000000000000000000000000000',
maxGasPrice: '4294967296',
minGasPrice: '1',
salt: '32606650794224189614795510724011106220035660490560169776986607186708081701146',
sender: '0x0000000000000000000000000000000000000000',
signer: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
value: '0',
},
},
price: '1800.054805',
protocolFee: '0',
sellAmount: '1000000000000000000000',
sellTokenAddress: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
sellTokenToEthRate: '0.000465167371348443',
sources: [
{
name: 'SushiSwap',
proportion: '0',
},
{
name: 'QuickSwap',
proportion: '0.2308',
},
{
name: '"Aave_V2',
proportion: '0',
},
{
name: 'DODO_V2',
proportion: '0.07692',
},
{
name: 'Uniswap_V3',
proportion: '0.6923',
},
],
value: '0',
fees: {
integratorFee: {
type: 'volume',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '1000000000000000000',
feeRecipient: integratorAddress,
volumePercentage: '0.1',
},
zeroExFee: {
type: 'integrator_share',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '1000000000000000',
feeRecipient: zeroExAddress,
integratorSharePercentage: '0.1',
},
gasFee: {
type: 'gas',
gasPrice: '115200000000',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '10000000',
feeRecipient: null,
estimatedGas: '1043459',
feeTokenAmountPerWei: '0.001',
},
},
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).replyOnce(OK, exampleSuccessfulResponse);
await expect(() =>
getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
metaTransactionVersion: 'v1',
}),
).rejects.toThrow();
});
it('should throw if computed meta-transaction hash is different from the hash in response when requested meta-transaction version is v1', async () => {
const exampleSuccessfulResponse = {
allowanceTarget: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
buyAmount: '1800054805473',
buyTokenAddress: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
buyTokenToEthRate: '0.851202',
chainId: 137,
estimatedGas: '1043459',
estimatedPriceImpact: '1.6301',
gas: '1043459',
gasPrice: '115200000000',
minimumProtocolFee: '0',
trade: {
kind: 'metatransaction_v2',
hash: '0x3655b708dad87eb79dee866651b7179b1256caa98840e98335fd7e153c21f9a1',
metaTransaction: {
callData:
'0x415565b00000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000019eeab6030b00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000860000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000007c000000000000000000000000000000000000000000000003635c9adc5dea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000002517569636b5377617000000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003f47a215c5000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000002517569636b53776170000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f2c6f738e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000a5e0829caced8ffdd4de3c43696c57f7d7a678ff000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f6190000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000b446f646f5632000000000000000000000000000000000000000000000000000000000000000000042b85aae7d60c4bc40000000000000000000000000000000000000000000000000000001f811895a7000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000000000005333eb1e32522f1893b7c9fea3c263807a02d561000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000012556e697377617056330000000000000000000000000000000000000000000000000000000000001d30a7ac56da56396a000000000000000000000000000000000000000000000000000000e10b7768e500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000060000000000000000000000000e592427a0aece92de3edee1f18e0157c058615640000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012556e6973776170563300000000000000000000000000000000000000000000000000000000000008570b55cfac1897880000000000000000000000000000000000000000000000000000003fea147b29000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000427ceb23fd6bc0add59e62ac25578270cff1b9f6190001f41bfd67037b42cf73acf2047067bd4f2c47d9bfd6000bb82791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007ceb23fd6bc0add59e62ac25578270cff1b9f619000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000000000000000000000869584cd0000000000000000000000008c611defbd838a13de3a5923693c58a7c1807c630000000000000000000000000000000000000000000000f789bac21b62fed5ef',
chainId: 137,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff',
expirationTimeSeconds: '1660868679',
feeToken: '0x0000000000000000000000000000000000000000',
fees: [
{
recipient: integratorAddress,
amount: '999000000000000000',
},
{
recipient: zeroExAddress,
amount: '1000000000000000',
},
],
salt: '32606650794224189614795510724011106220035660490560169776986607186708081701146',
sender: '0x0000000000000000000000000000000000000000',
signer: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
},
},
price: '1800.054805',
protocolFee: '0',
sellAmount: '1000000000000000000000',
sellTokenAddress: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
sellTokenToEthRate: '0.000465167371348443',
sources: [
{
name: 'SushiSwap',
proportion: '0',
},
{
name: 'QuickSwap',
proportion: '0.2308',
},
{
name: '"Aave_V2',
proportion: '0',
},
{
name: 'DODO_V2',
proportion: '0.07692',
},
{
name: 'Uniswap_V3',
proportion: '0.6923',
},
],
value: '0',
fees: {
integratorFee: {
type: 'volume',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '999000000000000000',
feeRecipient: integratorAddress,
volumePercentage: '0.1',
billingType: 'on-chain',
},
zeroExFee: {
type: 'integrator_share',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '1000000000000000',
feeRecipient: zeroExAddress,
integratorSharePercentage: '0.1',
billingType: 'on-chain',
},
gasFee: {
type: 'gas',
gasPrice: '115200000000',
feeToken: '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
feeAmount: '10000000',
feeRecipient: null,
estimatedGas: '1043459',
feeTokenAmountPerWei: '0.001',
billingType: 'off-chain',
},
},
};
const url = new URL('https://quoteserver.pizza/quote');
axiosMock.onPost(url.toString()).replyOnce(OK, exampleSuccessfulResponse);
await expect(() =>
getV2QuoteAsync(axiosClient, url, {
buyToken: 'USDC',
chainId: 137,
integratorId: 'integrator-id',
sellToken: '0x0000000000000000000000000000000000000000',
sellAmount: new BigNumber(1000000000000000000000),
takerAddress: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
metaTransactionVersion: 'v1',
}),
).rejects.toThrow();
});
});
});