* v4 FillQuoteTransformer (#104) * Update FQT to support v4 orders * `@0x/contracts-zero-ex`: Tweak FQT `@0x/contracts-zero-ex`: Drop `ERC20BridgeTransfer` event and add `PartialQuoteFill` event. * `@0x/contracts-utils`: Add `LibSafeMathV06.downcastToUint128()` * `@0x/protocol-utils`: Update transformer utils for V4 FQT * `@0x/contracts-zero-ex`: Fixing FQT tests... * `@0x/contracts-zero-ex`: rename FQT bridge event * `@0x/contracts-zero-ex`: Un-`only` tests * `@0x/migrations`: Update `BridgeAdapter` deployment * `@0x/contracts-integrations`: Delete `mtx_tests` * `@0x/protocol-utils`: Address review comments * `@0x/contracts-zero-ex`: Address review comments * `@0x/migrations`: Update migrations Co-authored-by: Michael Zhu <mchl.zhu.96@gmail.com> Co-authored-by: Lawrence Forman <me@merklejerk.com> * v4: Asset-swapper (main branch) (#113) * refactor quote_requestor * WIP v4/asset-swapper: Clean up SwapQuoter and remove @0x/orderbook * Start replacing SignedOrder everywhere * wip: new order type * wip * remove order-utils from most places * hack: Play around with VerboseX types (#119) * hack: Play around with VerboseX types * More hacks * Fix up the bridgeData encodings * Rework Orderbook return type * feat: Don't charge a protocol fee for RFQ orders WIP (#121) * fix simple build errors * simplify types a little * remove SwapQuoteCalculator: unnecessary abstraction * Fix all ./src build errors; make types consistent * export more types for use in 0x API; modify Orderbook interface * stop overriding APIOrder * feat: RFQ v4 + consolidated bridge encoders (#125) * feat: check if taker address is contract * Rework bridge data * Worst case adjustments * RFQT v4 * Future/v4 validate orders (#126) * RFQT v4 * v4 validate native orders * use default invalid signature * refactor rfqt validations in swap quoter * fix types * fix RFQT unlisted api key * remove priceAwareRFQFlag * adjust maker/taker amounts * update JSON schemas * filter zero fillable orders Co-authored-by: xianny <xianny@gmail.com> * fix type export Co-authored-by: xianny <xianny@gmail.com> * remove order-utils as much as possible * work on tests compile * Comment out quote reporter test * updated tests * restore order-utils accidental changes * some lints * Remove old fill_test * ts lint disable for now * update quote report * Re-enable quote report tests * make fill data required field * fix lint * type guards * force fillData as required * fix lint * fix naming * exports * adjust MultiBridge by slippage * cleanups (checkpoint 1) * cleanup types (checkpoint #2) * remove unused deps * `@0x/contract-addresses`: Deploy new FQT (#129) Co-authored-by: Lawrence Forman <me@merklejerk.com> * commit bump to republish * DRY up the rfqt mocker * fix: Balancer load top pools (#131) * fix: Balancer load top 250 pools * refetch top pools on an interval Co-authored-by: Jacob Evans <jacob@dekz.net> Co-authored-by: Kim Persson <kimpers@users.noreply.github.com> Co-authored-by: Lawrence Forman <lawrence@0xproject.com> Co-authored-by: Lawrence Forman <me@merklejerk.com> * Update post rebase * prettier * Remove test helpers exported in asset-swapper * Clean up from review comments * prettier * lint * recreate rfqt mocker * change merge and INVALID_SIGNATURE Co-authored-by: Lawrence Forman <lawrence@0xproject.com> Co-authored-by: Michael Zhu <mchl.zhu.96@gmail.com> Co-authored-by: Lawrence Forman <me@merklejerk.com> Co-authored-by: Xianny <8582774+xianny@users.noreply.github.com> Co-authored-by: Kim Persson <kimpers@users.noreply.github.com>
275 lines
9.2 KiB
TypeScript
275 lines
9.2 KiB
TypeScript
import { ContractTxFunctionObj } from '@0x/base-contract';
|
|
import { constants } from '@0x/contracts-test-utils';
|
|
import { LimitOrderFields, Signature } from '@0x/protocol-utils';
|
|
import { BigNumber, hexUtils } from '@0x/utils';
|
|
|
|
import { SamplerCallResult } from '../../src/types';
|
|
import { ERC20BridgeSamplerContract } from '../../src/wrappers';
|
|
|
|
export type GetOrderFillableAssetAmountResult = BigNumber[];
|
|
export type GetOrderFillableAssetAmountHandler = (
|
|
orders: LimitOrderFields[],
|
|
signatures: Signature[],
|
|
devUtilsAddress: string,
|
|
) => GetOrderFillableAssetAmountResult;
|
|
|
|
export type SampleResults = BigNumber[];
|
|
export type SampleSellsHandler = (
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerTokenAmounts: BigNumber[],
|
|
) => SampleResults;
|
|
export type SampleBuysHandler = (
|
|
takerToken: string,
|
|
makerToken: string,
|
|
makerTokenAmounts: BigNumber[],
|
|
) => SampleResults;
|
|
export type SampleSellsKyberHandler = (
|
|
reserveOffset: BigNumber,
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerTokenAmounts: BigNumber[],
|
|
) => [string, string, SampleResults];
|
|
export type SampleBuysKyberHandler = (
|
|
reserveId: string,
|
|
takerToken: string,
|
|
makerToken: string,
|
|
makerTokenAmounts: BigNumber[],
|
|
) => [string, SampleResults];
|
|
export type SampleUniswapV2Handler = (router: string, path: string[], assetAmounts: BigNumber[]) => SampleResults;
|
|
export type SampleBuysMultihopHandler = (path: string[], takerTokenAmounts: BigNumber[]) => SampleResults;
|
|
export type SampleSellsLPHandler = (
|
|
providerAddress: string,
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerTokenAmounts: BigNumber[],
|
|
) => SampleResults;
|
|
export type SampleSellsMultihopHandler = (path: string[], takerTokenAmounts: BigNumber[]) => SampleResults;
|
|
|
|
const DUMMY_PROVIDER = {
|
|
sendAsync: (..._args: any[]): any => {
|
|
/* no-op */
|
|
},
|
|
};
|
|
|
|
interface Handlers {
|
|
getLimitOrderFillableMakerAssetAmounts: GetOrderFillableAssetAmountHandler;
|
|
getLimitOrderFillableTakerAssetAmounts: GetOrderFillableAssetAmountHandler;
|
|
sampleSellsFromKyberNetwork: SampleSellsKyberHandler;
|
|
sampleSellsFromLiquidityProvider: SampleSellsLPHandler;
|
|
sampleSellsFromEth2Dai: SampleSellsHandler;
|
|
sampleSellsFromUniswap: SampleSellsHandler;
|
|
sampleSellsFromUniswapV2: SampleUniswapV2Handler;
|
|
sampleBuysFromEth2Dai: SampleBuysHandler;
|
|
sampleBuysFromUniswap: SampleBuysHandler;
|
|
sampleBuysFromUniswapV2: SampleUniswapV2Handler;
|
|
sampleBuysFromLiquidityProvider: SampleSellsLPHandler;
|
|
}
|
|
|
|
// tslint:disable: no-unbound-method
|
|
|
|
export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|
private readonly _handlers: Partial<Handlers> = {};
|
|
|
|
public constructor(handlers: Partial<Handlers> = {}) {
|
|
super(constants.NULL_ADDRESS, DUMMY_PROVIDER);
|
|
this._handlers = handlers;
|
|
}
|
|
|
|
public batchCall(callDatas: string[]): ContractTxFunctionObj<SamplerCallResult[]> {
|
|
return {
|
|
...super.batchCall(callDatas),
|
|
callAsync: async (..._callArgs: any[]) =>
|
|
callDatas.map(callData => ({ success: true, data: this._callEncodedFunction(callData) })),
|
|
};
|
|
}
|
|
|
|
public getLimitOrderFillableMakerAssetAmounts(
|
|
orders: LimitOrderFields[],
|
|
signatures: Signature[],
|
|
): ContractTxFunctionObj<GetOrderFillableAssetAmountResult> {
|
|
return this._wrapCall(
|
|
super.getLimitOrderFillableMakerAssetAmounts,
|
|
this._handlers.getLimitOrderFillableMakerAssetAmounts,
|
|
orders,
|
|
signatures,
|
|
constants.NULL_ADDRESS,
|
|
);
|
|
}
|
|
|
|
public getLimitOrderFillableTakerAssetAmounts(
|
|
orders: LimitOrderFields[],
|
|
signatures: Signature[],
|
|
): ContractTxFunctionObj<GetOrderFillableAssetAmountResult> {
|
|
return this._wrapCall(
|
|
super.getLimitOrderFillableTakerAssetAmounts,
|
|
this._handlers.getLimitOrderFillableTakerAssetAmounts,
|
|
orders,
|
|
signatures,
|
|
constants.NULL_ADDRESS,
|
|
);
|
|
}
|
|
|
|
public sampleSellsFromKyberNetwork(
|
|
reserveOffset: BigNumber,
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<[string, string, BigNumber[]]> {
|
|
return this._wrapCall(
|
|
super.sampleSellsFromKyberNetwork,
|
|
this._handlers.sampleSellsFromKyberNetwork,
|
|
reserveOffset,
|
|
takerToken,
|
|
makerToken,
|
|
takerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleSellsFromEth2Dai(
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleSellsFromEth2Dai,
|
|
this._handlers.sampleSellsFromEth2Dai,
|
|
takerToken,
|
|
makerToken,
|
|
takerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleSellsFromUniswap(
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleSellsFromUniswap,
|
|
this._handlers.sampleSellsFromUniswap,
|
|
takerToken,
|
|
makerToken,
|
|
takerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleSellsFromUniswapV2(
|
|
router: string,
|
|
path: string[],
|
|
takerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleSellsFromUniswapV2,
|
|
this._handlers.sampleSellsFromUniswapV2,
|
|
router,
|
|
path,
|
|
takerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleSellsFromLiquidityProvider(
|
|
providerAddress: string,
|
|
takerToken: string,
|
|
makerToken: string,
|
|
takerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleSellsFromLiquidityProvider,
|
|
this._handlers.sampleSellsFromLiquidityProvider,
|
|
providerAddress,
|
|
takerToken,
|
|
makerToken,
|
|
takerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleBuysFromEth2Dai(
|
|
takerToken: string,
|
|
makerToken: string,
|
|
makerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleBuysFromEth2Dai,
|
|
this._handlers.sampleBuysFromEth2Dai,
|
|
takerToken,
|
|
makerToken,
|
|
makerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleBuysFromUniswap(
|
|
takerToken: string,
|
|
makerToken: string,
|
|
makerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleBuysFromUniswap,
|
|
this._handlers.sampleBuysFromUniswap,
|
|
takerToken,
|
|
makerToken,
|
|
makerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
public sampleBuysFromUniswapV2(
|
|
router: string,
|
|
path: string[],
|
|
makerAssetAmounts: BigNumber[],
|
|
): ContractTxFunctionObj<BigNumber[]> {
|
|
return this._wrapCall(
|
|
super.sampleBuysFromUniswapV2,
|
|
this._handlers.sampleBuysFromUniswapV2,
|
|
router,
|
|
path,
|
|
makerAssetAmounts,
|
|
);
|
|
}
|
|
|
|
private _callEncodedFunction(callData: string): string {
|
|
if (callData === '0x') {
|
|
return callData;
|
|
}
|
|
// tslint:disable-next-line: custom-no-magic-numbers
|
|
const selector = hexUtils.slice(callData, 0, 4);
|
|
for (const [name, handler] of Object.entries(this._handlers)) {
|
|
if (handler && this.getSelector(name) === selector) {
|
|
const args = this.getABIDecodedTransactionData<any>(name, callData);
|
|
const result = (handler as any)(...args);
|
|
const encoder = this._lookupAbiEncoder(this.getFunctionSignature(name));
|
|
if (encoder.getReturnValueDataItem().components!.length === 1) {
|
|
return encoder.encodeReturnValues([result]);
|
|
} else {
|
|
return encoder.encodeReturnValues(result);
|
|
}
|
|
}
|
|
}
|
|
if (selector === this.getSelector('batchCall')) {
|
|
const calls = this.getABIDecodedTransactionData<string[]>('batchCall', callData);
|
|
const results: SamplerCallResult[] = calls.map(cd => ({
|
|
success: true,
|
|
data: this._callEncodedFunction(cd),
|
|
}));
|
|
return this._lookupAbiEncoder(this.getFunctionSignature('batchCall')).encodeReturnValues([results]);
|
|
}
|
|
throw new Error(`Unkown selector: ${selector}`);
|
|
}
|
|
|
|
private _wrapCall<TArgs extends any[], TResult>(
|
|
superFn: (this: MockSamplerContract, ...args: TArgs) => ContractTxFunctionObj<TResult>,
|
|
handler?: (this: MockSamplerContract, ...args: TArgs) => TResult,
|
|
// tslint:disable-next-line: trailing-comma
|
|
...args: TArgs
|
|
): ContractTxFunctionObj<TResult> {
|
|
return {
|
|
...superFn.call(this, ...args),
|
|
callAsync: async (..._callArgs: any[]): Promise<TResult> => {
|
|
if (!handler) {
|
|
throw new Error(`${superFn.name} handler undefined`);
|
|
}
|
|
return handler.call(this, ...args);
|
|
},
|
|
};
|
|
}
|
|
}
|