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(); }); }); });