feat: add IRfqClient (#467)
This commit is contained in:
parent
9eadc5fc28
commit
a7f23a982e
@ -116,6 +116,15 @@ export {
|
|||||||
SamplerMetrics,
|
SamplerMetrics,
|
||||||
} from './types';
|
} from './types';
|
||||||
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
||||||
|
export {
|
||||||
|
IRfqClient,
|
||||||
|
RfqClientV1Price,
|
||||||
|
RfqClientV1PriceRequest,
|
||||||
|
RfqClientV1PriceResponse,
|
||||||
|
RfqClientV1Quote,
|
||||||
|
RfqClientV1QuoteRequest,
|
||||||
|
RfqClientV1QuoteResponse,
|
||||||
|
} from './utils/irfq_client';
|
||||||
export {
|
export {
|
||||||
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
|
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
|
||||||
DEFAULT_GAS_SCHEDULE,
|
DEFAULT_GAS_SCHEDULE,
|
||||||
|
@ -25,6 +25,7 @@ import {
|
|||||||
SwapQuoterRfqOpts,
|
SwapQuoterRfqOpts,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { assert } from './utils/assert';
|
import { assert } from './utils/assert';
|
||||||
|
import { IRfqClient } from './utils/irfq_client';
|
||||||
import { MarketOperationUtils } from './utils/market_operation_utils';
|
import { MarketOperationUtils } from './utils/market_operation_utils';
|
||||||
import { BancorService } from './utils/market_operation_utils/bancor_service';
|
import { BancorService } from './utils/market_operation_utils/bancor_service';
|
||||||
import { SAMPLER_ADDRESS, SOURCE_FLAGS, ZERO_AMOUNT } from './utils/market_operation_utils/constants';
|
import { SAMPLER_ADDRESS, SOURCE_FLAGS, ZERO_AMOUNT } from './utils/market_operation_utils/constants';
|
||||||
@ -327,6 +328,7 @@ export class SwapQuoter {
|
|||||||
assetFillAmount: BigNumber,
|
assetFillAmount: BigNumber,
|
||||||
marketOperation: MarketOperation,
|
marketOperation: MarketOperation,
|
||||||
options: Partial<SwapQuoteRequestOpts>,
|
options: Partial<SwapQuoteRequestOpts>,
|
||||||
|
rfqClient: IRfqClient | undefined,
|
||||||
): Promise<SwapQuote> {
|
): Promise<SwapQuote> {
|
||||||
assert.isETHAddressHex('makerToken', makerToken);
|
assert.isETHAddressHex('makerToken', makerToken);
|
||||||
assert.isETHAddressHex('takerToken', takerToken);
|
assert.isETHAddressHex('takerToken', takerToken);
|
||||||
@ -381,6 +383,7 @@ export class SwapQuoter {
|
|||||||
this.expiryBufferMs,
|
this.expiryBufferMs,
|
||||||
rfqtOptions?.metricsProxy,
|
rfqtOptions?.metricsProxy,
|
||||||
);
|
);
|
||||||
|
calcOpts.rfqt.rfqClient = rfqClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result: OptimizerResultWithReport = await this._marketOperationUtils.getOptimizerResultAsync(
|
const result: OptimizerResultWithReport = await this._marketOperationUtils.getOptimizerResultAsync(
|
||||||
|
@ -17,7 +17,10 @@ import {
|
|||||||
|
|
||||||
const SUCCESS_CODE = 201;
|
const SUCCESS_CODE = 201;
|
||||||
|
|
||||||
function getAltMarketInfo(
|
/**
|
||||||
|
* Returns the AltOffering if it exists for a given pair
|
||||||
|
*/
|
||||||
|
export function getAltMarketInfo(
|
||||||
offerings: AltOffering[],
|
offerings: AltOffering[],
|
||||||
buyTokenAddress: string,
|
buyTokenAddress: string,
|
||||||
sellTokenAddress: string,
|
sellTokenAddress: string,
|
||||||
|
59
packages/asset-swapper/src/utils/irfq_client.ts
Normal file
59
packages/asset-swapper/src/utils/irfq_client.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { RfqOrder, Signature } from '@0x/protocol-utils';
|
||||||
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
|
import { AltRfqMakerAssetOfferings } from '../types';
|
||||||
|
|
||||||
|
export interface RfqClientV1PriceRequest {
|
||||||
|
altRfqAssetOfferings: AltRfqMakerAssetOfferings | undefined;
|
||||||
|
assetFillAmount: BigNumber;
|
||||||
|
chainId: number;
|
||||||
|
comparisonPrice: BigNumber | undefined;
|
||||||
|
integratorId: string;
|
||||||
|
intentOnFilling: boolean;
|
||||||
|
makerToken: string;
|
||||||
|
marketOperation: 'Sell' | 'Buy';
|
||||||
|
takerAddress: string;
|
||||||
|
takerToken: string;
|
||||||
|
txOrigin: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RfqClientV1QuoteRequest extends RfqClientV1PriceRequest {}
|
||||||
|
|
||||||
|
export interface RfqClientV1Price {
|
||||||
|
expiry: BigNumber;
|
||||||
|
kind: 'rfq' | 'otc';
|
||||||
|
makerAmount: BigNumber;
|
||||||
|
makerToken: string;
|
||||||
|
makerUri: string;
|
||||||
|
takerAmount: BigNumber;
|
||||||
|
takerToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RfqClientV1PriceResponse {
|
||||||
|
prices: RfqClientV1Price[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RfqClientV1Quote {
|
||||||
|
makerUri: string;
|
||||||
|
order: RfqOrder;
|
||||||
|
signature: Signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RfqClientV1QuoteResponse {
|
||||||
|
quotes: RfqClientV1Quote[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IRfqClient is an interface that defines how to connect with an Rfq system.
|
||||||
|
*/
|
||||||
|
export interface IRfqClient {
|
||||||
|
/**
|
||||||
|
* Fetches a list of "indicative quotes" or prices from a remote Rfq server
|
||||||
|
*/
|
||||||
|
getV1PricesAsync(request: RfqClientV1PriceRequest): Promise<RfqClientV1PriceResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a list of "firm quotes" or signed quotes from a remote Rfq server.
|
||||||
|
*/
|
||||||
|
getV1QuotesAsync(request: RfqClientV1QuoteRequest): Promise<RfqClientV1QuoteResponse>;
|
||||||
|
}
|
@ -4,12 +4,15 @@ import * as _ from 'lodash';
|
|||||||
|
|
||||||
import { DEFAULT_INFO_LOGGER, INVALID_SIGNATURE } from '../../constants';
|
import { DEFAULT_INFO_LOGGER, INVALID_SIGNATURE } from '../../constants';
|
||||||
import {
|
import {
|
||||||
|
AltRfqMakerAssetOfferings,
|
||||||
AssetSwapperContractAddresses,
|
AssetSwapperContractAddresses,
|
||||||
MarketOperation,
|
MarketOperation,
|
||||||
NativeOrderWithFillableAmounts,
|
NativeOrderWithFillableAmounts,
|
||||||
SignedNativeOrder,
|
SignedNativeOrder,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
import { QuoteRequestor } from '../quote_requestor';
|
import { getAltMarketInfo } from '../alt_mm_implementation_utils';
|
||||||
|
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../quote_requestor';
|
||||||
|
import { toSignedNativeOrder } from '../rfq_client_mappers';
|
||||||
import {
|
import {
|
||||||
getNativeAdjustedFillableAmountsFromMakerAmount,
|
getNativeAdjustedFillableAmountsFromMakerAmount,
|
||||||
getNativeAdjustedFillableAmountsFromTakerAmount,
|
getNativeAdjustedFillableAmountsFromTakerAmount,
|
||||||
@ -663,10 +666,42 @@ export class MarketOperationUtils {
|
|||||||
// Timing of RFQT lifecycle
|
// Timing of RFQT lifecycle
|
||||||
const timeStart = new Date().getTime();
|
const timeStart = new Date().getTime();
|
||||||
const { makerToken, takerToken } = nativeOrders[0].order;
|
const { makerToken, takerToken } = nativeOrders[0].order;
|
||||||
|
|
||||||
|
// Filter Alt Rfq Maker Asset Offerings to the current pair
|
||||||
|
const filteredOfferings: AltRfqMakerAssetOfferings = {};
|
||||||
|
if (rfqt.altRfqAssetOfferings) {
|
||||||
|
const endpoints = Object.keys(rfqt.altRfqAssetOfferings);
|
||||||
|
for (const endpoint of endpoints) {
|
||||||
|
// Get the current pair if being offered
|
||||||
|
const offering = getAltMarketInfo(rfqt.altRfqAssetOfferings[endpoint], makerToken, takerToken);
|
||||||
|
if (offering) {
|
||||||
|
filteredOfferings[endpoint] = [offering];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rfqt.isIndicative) {
|
if (rfqt.isIndicative) {
|
||||||
// An indicative quote is being requested, and indicative quotes price-aware enabled
|
// An indicative quote is being requested, and indicative quotes price-aware enabled
|
||||||
// Make the RFQT request and then re-run the sampler if new orders come back.
|
// Make the RFQT request and then re-run the sampler if new orders come back.
|
||||||
const indicativeQuotes = await rfqt.quoteRequestor.requestRfqtIndicativeQuotesAsync(
|
|
||||||
|
const indicativeQuotes =
|
||||||
|
rfqt.rfqClient !== undefined
|
||||||
|
? ((
|
||||||
|
await rfqt.rfqClient.getV1PricesAsync({
|
||||||
|
altRfqAssetOfferings: filteredOfferings,
|
||||||
|
assetFillAmount: amount,
|
||||||
|
chainId: this._sampler.chainId,
|
||||||
|
comparisonPrice: wholeOrderPrice,
|
||||||
|
integratorId: rfqt.integrator.integratorId,
|
||||||
|
intentOnFilling: rfqt.intentOnFilling,
|
||||||
|
makerToken,
|
||||||
|
marketOperation: side,
|
||||||
|
takerAddress: rfqt.takerAddress,
|
||||||
|
takerToken,
|
||||||
|
txOrigin: rfqt.txOrigin,
|
||||||
|
})
|
||||||
|
).prices as V4RFQIndicativeQuoteMM[])
|
||||||
|
: await rfqt.quoteRequestor.requestRfqtIndicativeQuotesAsync(
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
amount,
|
amount,
|
||||||
@ -687,7 +722,24 @@ export class MarketOperationUtils {
|
|||||||
} else {
|
} else {
|
||||||
// A firm quote is being requested, and firm quotes price-aware enabled.
|
// A firm quote is being requested, and firm quotes price-aware enabled.
|
||||||
// Ensure that `intentOnFilling` is enabled and make the request.
|
// Ensure that `intentOnFilling` is enabled and make the request.
|
||||||
const firmQuotes = await rfqt.quoteRequestor.requestRfqtFirmQuotesAsync(
|
const firmQuotes =
|
||||||
|
rfqt.rfqClient !== undefined
|
||||||
|
? (
|
||||||
|
await rfqt.rfqClient.getV1QuotesAsync({
|
||||||
|
altRfqAssetOfferings: filteredOfferings,
|
||||||
|
assetFillAmount: amount,
|
||||||
|
chainId: this._sampler.chainId,
|
||||||
|
comparisonPrice: wholeOrderPrice,
|
||||||
|
integratorId: rfqt.integrator.integratorId,
|
||||||
|
intentOnFilling: rfqt.intentOnFilling,
|
||||||
|
makerToken,
|
||||||
|
marketOperation: side,
|
||||||
|
takerAddress: rfqt.takerAddress,
|
||||||
|
takerToken,
|
||||||
|
txOrigin: rfqt.txOrigin,
|
||||||
|
})
|
||||||
|
).quotes.map(toSignedNativeOrder)
|
||||||
|
: await rfqt.quoteRequestor.requestRfqtFirmQuotesAsync(
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
amount,
|
amount,
|
||||||
|
@ -8,6 +8,7 @@ import { BigNumber } from '@0x/utils';
|
|||||||
|
|
||||||
import { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
|
import { NativeOrderWithFillableAmounts, RfqFirmQuoteValidator, RfqRequestOpts } from '../../types';
|
||||||
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../../utils/quote_requestor';
|
import { QuoteRequestor, V4RFQIndicativeQuoteMM } from '../../utils/quote_requestor';
|
||||||
|
import { IRfqClient } from '../irfq_client';
|
||||||
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
|
import { ExtendedQuoteReportSources, PriceComparisonsReport, QuoteReport } from '../quote_report_generator';
|
||||||
|
|
||||||
import { SourceFilters } from './source_filters';
|
import { SourceFilters } from './source_filters';
|
||||||
@ -446,6 +447,7 @@ export type OptimizedMarketOrder =
|
|||||||
| OptimizedMarketOrderBase<NativeRfqOrderFillData>;
|
| OptimizedMarketOrderBase<NativeRfqOrderFillData>;
|
||||||
|
|
||||||
export interface GetMarketOrdersRfqOpts extends RfqRequestOpts {
|
export interface GetMarketOrdersRfqOpts extends RfqRequestOpts {
|
||||||
|
rfqClient?: IRfqClient;
|
||||||
quoteRequestor?: QuoteRequestor;
|
quoteRequestor?: QuoteRequestor;
|
||||||
firmQuoteValidator?: RfqFirmQuoteValidator;
|
firmQuoteValidator?: RfqFirmQuoteValidator;
|
||||||
}
|
}
|
||||||
|
16
packages/asset-swapper/src/utils/rfq_client_mappers.ts
Normal file
16
packages/asset-swapper/src/utils/rfq_client_mappers.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
||||||
|
|
||||||
|
import { SignedNativeOrder } from '../types';
|
||||||
|
|
||||||
|
import { RfqClientV1Quote } from './irfq_client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a RfqClientRfqOrderFirmQuote to a SignedNativeOrder
|
||||||
|
*/
|
||||||
|
export const toSignedNativeOrder = (quote: RfqClientV1Quote): SignedNativeOrder => {
|
||||||
|
return {
|
||||||
|
type: FillQuoteTransformerOrderType.Rfq,
|
||||||
|
order: quote.order,
|
||||||
|
signature: quote.signature,
|
||||||
|
};
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user