import { BigNumber } from '@0x/utils'; import { Integrator } from '../../src/config'; import { ONE_MINUTE_MS, ONE_SECOND_MS } from '../../src/core/constants'; import { QuoteContext } from '../../src/services/types'; import { RfqtV2Price } from '../../src/core/types'; import { getRfqtV2FillableAmounts, validateV2Prices } from '../../src/utils/RfqtQuoteValidator'; describe('Rfqt Quote Validator', () => { const chainId = 1337; const integrator: Integrator = { allowedChainIds: [chainId], apiKeys: [], integratorId: 'integrator-id', label: 'test integrator', rfqm: false, }; const quoteContext: QuoteContext = { isFirm: false, workflow: 'rfqt', isUnwrap: false, originalMakerToken: '0x1', takerTokenDecimals: 18, makerTokenDecimals: 18, feeModelVersion: 1, assetFillAmount: new BigNumber(111), chainId, integrator, makerToken: '0x1', isSelling: false, takerAddress: '0x0', takerToken: '0x2', txOrigin: '0xtakeraddress', }; const nowTimeS = new BigNumber(Date.now()).div(ONE_SECOND_MS); const validPrices: RfqtV2Price[] = [ { expiry: nowTimeS.plus(75), makerAddress: '0xmaker1', makerAmount: new BigNumber(111), makerId: 'uuid-maker1', makerToken: '0x1', makerUri: 'maker1.xyz', takerAmount: new BigNumber(111), takerToken: '0x2', }, { expiry: nowTimeS.plus(75), makerAddress: '0xmaker2', makerAmount: new BigNumber(111), makerId: 'uuid-maker2', makerToken: '0x1', makerUri: 'maker2.xyz', takerAmount: new BigNumber(111), takerToken: '0x2', }, ]; const validityWindowMs = ONE_MINUTE_MS; describe('validateV2Prices', () => { it('filters fetched prices for the wrong pair', () => { const prices: RfqtV2Price[] = [ ...validPrices, { expiry: nowTimeS.plus(75), makerAddress: '0xmaker3', makerAmount: new BigNumber(111), makerId: 'uuid-maker3', makerToken: '0x1', makerUri: 'maker3.xyz', takerAmount: new BigNumber(111), takerToken: '0x3', }, ]; const validatedPrices = validateV2Prices(prices, quoteContext, validityWindowMs, chainId); expect(validatedPrices).toEqual(validPrices); }); it('filters fetched prices with tight expiration windows', () => { const prices: RfqtV2Price[] = [ ...validPrices, { expiry: nowTimeS.plus(59), makerAddress: '0xmaker3', makerAmount: new BigNumber(111), makerId: 'uuid-maker3', makerToken: '0x1', makerUri: 'maker3.xyz', takerAmount: new BigNumber(111), takerToken: '0x2', }, ]; const validatedPrices = validateV2Prices(prices, quoteContext, validityWindowMs, chainId); expect(validatedPrices).toEqual(validPrices); }); it('returns an empty array from empty prices', () => { const emptyPrices = validateV2Prices([], quoteContext, validityWindowMs, chainId); expect(emptyPrices).toEqual([]); }); }); describe('getRfqtV2FillableAmounts', () => { it('returns full amounts for fully fillable orders', () => { const quotedMakerBalances = [new BigNumber(1000), new BigNumber(1000)]; const fillableAmounts = getRfqtV2FillableAmounts(validPrices, chainId, quotedMakerBalances); expect(fillableAmounts).toEqual([ { fillableMakerAmount: new BigNumber(111), fillableTakerAmount: new BigNumber(111) }, { fillableMakerAmount: new BigNumber(111), fillableTakerAmount: new BigNumber(111) }, ]); }); it('returns full amounts if maker balances are not present', () => { const fillableAmounts = getRfqtV2FillableAmounts(validPrices, chainId); expect(fillableAmounts).toEqual([ { fillableMakerAmount: new BigNumber(111), fillableTakerAmount: new BigNumber(111) }, { fillableMakerAmount: new BigNumber(111), fillableTakerAmount: new BigNumber(111) }, ]); }); it('returns partial amounts if a maker does not have enough balance', () => { const quotedMakerBalances = [new BigNumber(1000), new BigNumber(10)]; const fillableAmounts = getRfqtV2FillableAmounts(validPrices, chainId, quotedMakerBalances); expect(fillableAmounts).toEqual([ { fillableMakerAmount: new BigNumber(111), fillableTakerAmount: new BigNumber(111) }, { fillableMakerAmount: new BigNumber(10), fillableTakerAmount: new BigNumber(10) }, ]); }); it('returns zero amounts if a maker has zero balance', () => { const quotedMakerBalances = [new BigNumber(1000), new BigNumber(0)]; const fillableAmounts = getRfqtV2FillableAmounts(validPrices, chainId, quotedMakerBalances); expect(fillableAmounts).toEqual([ { fillableMakerAmount: new BigNumber(111), fillableTakerAmount: new BigNumber(111) }, { fillableMakerAmount: new BigNumber(0), fillableTakerAmount: new BigNumber(0) }, ]); }); it('returns zero amounts if supplied maker amount is zero', () => { const prices = [ { expiry: nowTimeS.plus(75), makerAddress: '0xmaker3', makerAmount: new BigNumber(0), makerId: 'uuid-maker3', makerToken: '0x1', makerUri: 'maker3.xyz', takerAmount: new BigNumber(111), takerToken: '0x2', }, ]; const quotedMakerBalances = [new BigNumber(1000)]; const fillableAmounts = getRfqtV2FillableAmounts(prices, chainId, quotedMakerBalances); expect(fillableAmounts).toEqual([ { fillableMakerAmount: new BigNumber(0), fillableTakerAmount: new BigNumber(0) }, ]); }); }); });