aboutsummaryrefslogtreecommitdiffstats
path: root/packages/asset-buyer/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/asset-buyer/src')
-rw-r--r--packages/asset-buyer/src/asset_buyer.ts107
-rw-r--r--packages/asset-buyer/src/asset_buyer_manager.ts171
-rw-r--r--packages/asset-buyer/src/constants.ts24
-rw-r--r--packages/asset-buyer/src/index.ts7
-rw-r--r--packages/asset-buyer/src/standard_relayer_api_asset_buyer_manager.ts133
-rw-r--r--packages/asset-buyer/src/types.ts31
6 files changed, 256 insertions, 217 deletions
diff --git a/packages/asset-buyer/src/asset_buyer.ts b/packages/asset-buyer/src/asset_buyer.ts
index 409e34e74..afef0d070 100644
--- a/packages/asset-buyer/src/asset_buyer.ts
+++ b/packages/asset-buyer/src/asset_buyer.ts
@@ -11,8 +11,10 @@ import { BasicOrderProvider } from './order_providers/basic_order_provider';
import { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
import {
AssetBuyerError,
+ AssetBuyerOpts,
AssetBuyerOrdersAndFillableAmounts,
BuyQuote,
+ BuyQuoteExecutionOpts,
BuyQuoteRequestOpts,
OrderProvider,
OrderProviderResponse,
@@ -38,9 +40,7 @@ export class AssetBuyer {
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param orders A non-empty array of objects that conform to SignedOrder. All orders must have the same makerAssetData and takerAssetData (WETH).
* @param feeOrders A array of objects that conform to SignedOrder. All orders must have the same makerAssetData (ZRX) and takerAssetData (WETH). Defaults to an empty array.
- * @param networkId The ethereum network id. Defaults to 1 (mainnet).
- * @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
- * @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
+ * @param options Initialization options for the AssetBuyer. See type definition for details.
*
* @return An instance of AssetBuyer
*/
@@ -48,28 +48,17 @@ export class AssetBuyer {
provider: Provider,
orders: SignedOrder[],
feeOrders: SignedOrder[] = [],
- networkId: number = constants.MAINNET_NETWORK_ID,
- orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
- expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
+ options: Partial<AssetBuyerOpts>,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.doesConformToSchema('orders', orders, schemas.signedOrdersSchema);
assert.doesConformToSchema('feeOrders', feeOrders, schemas.signedOrdersSchema);
- assert.isNumber('networkId', networkId);
- assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
assert.areValidProvidedOrders('orders', orders);
assert.areValidProvidedOrders('feeOrders', feeOrders);
assert.assert(orders.length !== 0, `Expected orders to contain at least one order`);
const assetData = orders[0].makerAssetData;
const orderProvider = new BasicOrderProvider(_.concat(orders, feeOrders));
- const assetBuyer = new AssetBuyer(
- provider,
- assetData,
- orderProvider,
- networkId,
- orderRefreshIntervalMs,
- expiryBufferSeconds,
- );
+ const assetBuyer = new AssetBuyer(provider, assetData, orderProvider, options);
return assetBuyer;
}
/**
@@ -77,9 +66,7 @@ export class AssetBuyer {
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param assetData The assetData that identifies the desired asset to buy.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
- * @param networkId The ethereum network id. Defaults to 1 (mainnet).
- * @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
- * @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
+ * @param options Initialization options for the AssetBuyer. See type definition for details.
*
* @return An instance of AssetBuyer
*/
@@ -87,24 +74,13 @@ export class AssetBuyer {
provider: Provider,
assetData: string,
sraApiUrl: string,
- networkId: number = constants.MAINNET_NETWORK_ID,
- orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
- expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
+ options: Partial<AssetBuyerOpts>,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.isHexString('assetData', assetData);
assert.isWebUri('sraApiUrl', sraApiUrl);
- assert.isNumber('networkId', networkId);
- assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
const orderProvider = new StandardRelayerAPIOrderProvider(sraApiUrl);
- const assetBuyer = new AssetBuyer(
- provider,
- assetData,
- orderProvider,
- networkId,
- orderRefreshIntervalMs,
- expiryBufferSeconds,
- );
+ const assetBuyer = new AssetBuyer(provider, assetData, orderProvider, options);
return assetBuyer;
}
/**
@@ -112,59 +88,43 @@ export class AssetBuyer {
* @param provider The Provider instance you would like to use for interacting with the Ethereum network.
* @param tokenAddress The ERC20 token address that identifies the desired asset to buy.
* @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
- * @param networkId The ethereum network id. Defaults to 1 (mainnet).
- * @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
- * @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
+ * @param options Initialization options for the AssetBuyer. See type definition for details.
+ *
* @return An instance of AssetBuyer
*/
public static getAssetBuyerForERC20TokenAddress(
provider: Provider,
tokenAddress: string,
sraApiUrl: string,
- networkId: number = constants.MAINNET_NETWORK_ID,
- orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
- expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
+ options: Partial<AssetBuyerOpts>,
): AssetBuyer {
assert.isWeb3Provider('provider', provider);
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isWebUri('sraApiUrl', sraApiUrl);
- assert.isNumber('networkId', networkId);
- assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
- const assetBuyer = AssetBuyer.getAssetBuyerForAssetData(
- provider,
- assetData,
- sraApiUrl,
- networkId,
- orderRefreshIntervalMs,
- expiryBufferSeconds,
- );
+ const assetBuyer = AssetBuyer.getAssetBuyerForAssetData(provider, assetData, sraApiUrl, options);
return assetBuyer;
}
/**
* Instantiates a new AssetBuyer instance
- * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
- * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
- * @param orderProvider An object that conforms to OrderProvider, see type for definition.
- * @param networkId The ethereum network id. Defaults to 1 (mainnet).
- * @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
- * @param expiryBufferSeconds The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
+ * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
+ * @param assetData The assetData of the desired asset to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
+ * @param orderProvider An object that conforms to OrderProvider, see type for definition.
+ * @param options Initialization options for the AssetBuyer. See type definition for details.
*
* @return An instance of AssetBuyer
*/
- constructor(
- provider: Provider,
- assetData: string,
- orderProvider: OrderProvider,
- networkId: number = constants.MAINNET_NETWORK_ID,
- orderRefreshIntervalMs: number = constants.DEFAULT_ORDER_REFRESH_INTERVAL_MS,
- expiryBufferSeconds: number = constants.DEFAULT_EXPIRY_BUFFER_SECONDS,
- ) {
+ constructor(provider: Provider, assetData: string, orderProvider: OrderProvider, options: Partial<AssetBuyerOpts>) {
+ const { networkId, orderRefreshIntervalMs, expiryBufferSeconds } = {
+ ...constants.DEFAULT_ASSET_BUYER_OPTS,
+ ...options,
+ };
assert.isWeb3Provider('provider', provider);
assert.isString('assetData', assetData);
assert.isValidOrderProvider('orderProvider', orderProvider);
assert.isNumber('networkId', networkId);
assert.isNumber('orderRefreshIntervalMs', orderRefreshIntervalMs);
+ assert.isNumber('expiryBufferSeconds', expiryBufferSeconds);
this.provider = provider;
this.assetData = assetData;
this.orderProvider = orderProvider;
@@ -179,15 +139,14 @@ export class AssetBuyer {
* Get a `BuyQuote` containing all information relevant to fulfilling a buy.
* You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
* @param assetBuyAmount The amount of asset to buy.
- * @param feePercentage The affiliate fee percentage. Defaults to 0.
- * @param forceOrderRefresh If set to true, new orders and state will be fetched instead of waiting for
- * the next orderRefreshIntervalMs. Defaults to false.
+ * @param options Options for the request. See type definition for more information.
+ *
* @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
*/
public async getBuyQuoteAsync(assetBuyAmount: BigNumber, options: Partial<BuyQuoteRequestOpts>): Promise<BuyQuote> {
const { feePercentage, shouldForceOrderRefresh, slippagePercentage } = {
- ...options,
...constants.DEFAULT_BUY_QUOTE_REQUEST_OPTS,
+ ...options,
};
assert.isBigNumber('assetBuyAmount', assetBuyAmount);
assert.isValidPercentage('feePercentage', feePercentage);
@@ -222,17 +181,15 @@ export class AssetBuyer {
/**
* Given a BuyQuote and desired rate, attempt to execute the buy.
* @param buyQuote An object that conforms to BuyQuote. See type definition for more information.
- * @param rate The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
- * @param takerAddress The address to perform the buy. Defaults to the first available address from the provider.
- * @param feeRecipient The address where affiliate fees are sent. Defaults to null address (0x000...000).
+ * @param options Options for the execution of the BuyQuote. See type definition for more information.
+ *
* @return A promise of the txHash.
*/
- public async executeBuyQuoteAsync(
- buyQuote: BuyQuote,
- rate?: BigNumber,
- takerAddress?: string,
- feeRecipient: string = constants.NULL_ADDRESS,
- ): Promise<string> {
+ public async executeBuyQuoteAsync(buyQuote: BuyQuote, options: Partial<BuyQuoteExecutionOpts>): Promise<string> {
+ const { rate, takerAddress, feeRecipient } = {
+ ...constants.DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
+ ...options,
+ };
assert.isValidBuyQuote('buyQuote', buyQuote);
if (!_.isUndefined(rate)) {
assert.isBigNumber('rate', rate);
diff --git a/packages/asset-buyer/src/asset_buyer_manager.ts b/packages/asset-buyer/src/asset_buyer_manager.ts
new file mode 100644
index 000000000..1bde55eff
--- /dev/null
+++ b/packages/asset-buyer/src/asset_buyer_manager.ts
@@ -0,0 +1,171 @@
+import { HttpClient } from '@0xproject/connect';
+import { ContractWrappers } from '@0xproject/contract-wrappers';
+import { SignedOrder } from '@0xproject/order-utils';
+import { ObjectMap } from '@0xproject/types';
+import { BigNumber } from '@0xproject/utils';
+import { Provider } from 'ethereum-types';
+import * as _ from 'lodash';
+
+import { AssetBuyer } from './asset_buyer';
+import { constants } from './constants';
+import { BasicOrderProvider } from './order_providers/basic_order_provider';
+import { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
+import { assert } from './utils/assert';
+import { assetDataUtils } from './utils/asset_data_utils';
+
+import {
+ AssetBuyerManagerError,
+ AssetBuyerOpts,
+ BuyQuote,
+ BuyQuoteExecutionOpts,
+ BuyQuoteRequestOpts,
+ OrderProvider,
+} from './types';
+
+export class AssetBuyerManager {
+ // Map of assetData to AssetBuyer for that assetData
+ private readonly _assetBuyerMap: ObjectMap<AssetBuyer>;
+ /**
+ * Returns an array of all assetDatas available at the provided sraApiUrl
+ * @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
+ * @param pairedWithAssetData Optional filter argument to return assetDatas that only pair with this assetData value.
+ *
+ * @return An array of all assetDatas available at the provider sraApiUrl
+ */
+ public static async getAllAvailableAssetDatasAsync(
+ sraApiUrl: string,
+ pairedWithAssetData?: string,
+ ): Promise<string[]> {
+ const client = new HttpClient(sraApiUrl);
+ const params = {
+ assetDataA: pairedWithAssetData,
+ perPage: constants.MAX_PER_PAGE,
+ };
+ const assetPairsResponse = await client.getAssetPairsAsync(params);
+ return _.uniq(_.map(assetPairsResponse.records, pairsItem => pairsItem.assetDataB.assetData));
+ }
+ /**
+ * Instantiates a new AssetBuyerManager instance with all available assetDatas at the provided sraApiUrl
+ * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
+ * @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
+ * @param options Initialization options for an AssetBuyer. See type definition for details.
+ *
+ * @return An promise of an instance of AssetBuyerManager
+ */
+ public static async getAssetBuyerManagerFromStandardRelayerApiAsync(
+ provider: Provider,
+ sraApiUrl: string,
+ options: Partial<AssetBuyerOpts>,
+ ): Promise<AssetBuyerManager> {
+ const networkId = options.networkId || constants.MAINNET_NETWORK_ID;
+ const contractWrappers = new ContractWrappers(provider, { networkId });
+ const etherTokenAssetData = assetDataUtils.getEtherTokenAssetDataOrThrow(contractWrappers);
+ const assetDatas = await AssetBuyerManager.getAllAvailableAssetDatasAsync(sraApiUrl, etherTokenAssetData);
+ const orderProvider = new StandardRelayerAPIOrderProvider(sraApiUrl);
+ return new AssetBuyerManager(provider, assetDatas, orderProvider, options);
+ }
+ /**
+ * Instantiates a new AssetBuyerManager instance given existing liquidity in the form of orders and feeOrders.
+ * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
+ * @param orders A non-empty array of objects that conform to SignedOrder. All orders must have the same makerAssetData and takerAssetData (WETH).
+ * @param feeOrders A array of objects that conform to SignedOrder. All orders must have the same makerAssetData (ZRX) and takerAssetData (WETH). Defaults to an empty array.
+ * @param options Initialization options for an AssetBuyer. See type definition for details.
+ *
+ * @return An instance of AssetBuyerManager
+ */
+ public static getAssetBuyerManagerFromProvidedOrders(
+ provider: Provider,
+ orders: SignedOrder[],
+ feeOrders: SignedOrder[] = [],
+ options: Partial<AssetBuyerOpts>,
+ ): AssetBuyerManager {
+ const assetDatas = _.map(orders, order => order.makerAssetData);
+ const orderProvider = new BasicOrderProvider(_.concat(orders, feeOrders));
+ return new AssetBuyerManager(provider, assetDatas, orderProvider, options);
+ }
+ /**
+ * Instantiates a new AssetBuyerManager instance
+ * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
+ * @param assetDatas The assetDatas of the desired assets to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
+ * @param orderProvider An object that conforms to OrderProvider, see type for definition.
+ * @param options Initialization options for an AssetBuyer. See type definition for details.
+ *
+ * @return An instance of AssetBuyerManager
+ */
+ constructor(
+ provider: Provider,
+ assetDatas: string[],
+ orderProvider: OrderProvider,
+ options: Partial<AssetBuyerOpts>,
+ ) {
+ assert.assert(assetDatas.length > 0, `Expected 'assetDatas' to be a non-empty array.`);
+ this._assetBuyerMap = _.reduce(
+ assetDatas,
+ (accAssetBuyerMap: ObjectMap<AssetBuyer>, assetData: string) => {
+ accAssetBuyerMap[assetData] = new AssetBuyer(provider, assetData, orderProvider, options);
+ return accAssetBuyerMap;
+ },
+ {},
+ );
+ }
+ /**
+ * Get an AssetBuyer for the provided assetData
+ * @param assetData The desired assetData.
+ *
+ * @return An instance of AssetBuyer
+ */
+ public getAssetBuyerFromAssetData(assetData: string): AssetBuyer {
+ const assetBuyer = this._assetBuyerMap[assetData];
+ if (_.isUndefined(assetBuyer)) {
+ throw new Error(`${AssetBuyerManagerError.AssetBuyerNotFound}: For assetData ${assetData}`);
+ }
+ return assetBuyer;
+ }
+ /**
+ * Get an AssetBuyer for the provided ERC20 tokenAddress
+ * @param tokenAddress The desired tokenAddress.
+ *
+ * @return An instance of AssetBuyer
+ */
+ public getAssetBuyerFromERC20TokenAddress(tokenAddress: string): AssetBuyer {
+ const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
+ return this.getAssetBuyerFromAssetData(assetData);
+ }
+ /**
+ * Get a list of all the assetDatas that the instance supports
+ *
+ * @return An array of assetData strings
+ */
+ public getAssetDatas(): string[] {
+ return _.keys(this._assetBuyerMap);
+ }
+ /**
+ * Get a `BuyQuote` containing all information relevant to fulfilling a buy.
+ * You can then pass the `BuyQuote` to `executeBuyQuoteAsync` to execute the buy.
+ *
+ * @param assetData The assetData that identifies the desired asset to buy.
+ * @param assetBuyAmount The amount of asset to buy.
+ * @param options Options for the execution of the BuyQuote. See type definition for more information.
+ *
+ * @return An object that conforms to BuyQuote that satisfies the request. See type definition for more information.
+ */
+ public async getBuyQuoteAsync(
+ assetData: string,
+ assetBuyAmount: BigNumber,
+ options: Partial<BuyQuoteRequestOpts>,
+ ): Promise<BuyQuote> {
+ return this.getAssetBuyerFromAssetData(assetData).getBuyQuoteAsync(assetBuyAmount, options);
+ }
+ /**
+ * Given a BuyQuote and desired rate, attempt to execute the buy.
+ * @param buyQuote An object that conforms to BuyQuote. See type definition for more information.
+ * @param rate The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
+ * @param takerAddress The address to perform the buy. Defaults to the first available address from the provider.
+ * @param feeRecipient The address where affiliate fees are sent. Defaults to null address (0x000...000).
+ *
+ * @return A promise of the txHash.
+ */
+ public async executeBuyQuoteAsync(buyQuote: BuyQuote, options: Partial<BuyQuoteExecutionOpts>): Promise<string> {
+ return this.getAssetBuyerFromAssetData(buyQuote.assetData).executeBuyQuoteAsync(buyQuote, options);
+ }
+}
diff --git a/packages/asset-buyer/src/constants.ts b/packages/asset-buyer/src/constants.ts
index 79b5d9052..e1056e39b 100644
--- a/packages/asset-buyer/src/constants.ts
+++ b/packages/asset-buyer/src/constants.ts
@@ -1,6 +1,15 @@
import { BigNumber } from '@0xproject/utils';
-import { BuyQuoteRequestOpts } from './types';
+import { AssetBuyerOpts, BuyQuoteExecutionOpts, BuyQuoteRequestOpts } from './types';
+
+const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
+const MAINNET_NETWORK_ID = 1;
+
+const DEFAULT_ASSET_BUYER_OPTS: AssetBuyerOpts = {
+ networkId: MAINNET_NETWORK_ID,
+ orderRefreshIntervalMs: 10000, // 10 seconds
+ expiryBufferSeconds: 15,
+};
const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
feePercentage: 0,
@@ -8,13 +17,18 @@ const DEFAULT_BUY_QUOTE_REQUEST_OPTS: BuyQuoteRequestOpts = {
slippagePercentage: 0.2, // 20% slippage protection
};
+// Other default values are dynamically determined
+const DEFAULT_BUY_QUOTE_EXECUTION_OPTS: BuyQuoteExecutionOpts = {
+ feeRecipient: NULL_ADDRESS,
+};
+
export const constants = {
ZERO_AMOUNT: new BigNumber(0),
- NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
- MAINNET_NETWORK_ID: 1,
- DEFAULT_ORDER_REFRESH_INTERVAL_MS: 10000, // 10 seconds
+ NULL_ADDRESS,
+ MAINNET_NETWORK_ID,
ETHER_TOKEN_DECIMALS: 18,
+ DEFAULT_ASSET_BUYER_OPTS,
+ DEFAULT_BUY_QUOTE_EXECUTION_OPTS,
DEFAULT_BUY_QUOTE_REQUEST_OPTS,
MAX_PER_PAGE: 10000,
- DEFAULT_EXPIRY_BUFFER_SECONDS: 15,
};
diff --git a/packages/asset-buyer/src/index.ts b/packages/asset-buyer/src/index.ts
index 8ef529ac0..830b4d8b8 100644
--- a/packages/asset-buyer/src/index.ts
+++ b/packages/asset-buyer/src/index.ts
@@ -5,13 +5,16 @@ export { BigNumber } from '@0xproject/utils';
export { AssetBuyer } from './asset_buyer';
export { BasicOrderProvider } from './order_providers/basic_order_provider';
export { StandardRelayerAPIOrderProvider } from './order_providers/standard_relayer_api_order_provider';
-export { StandardRelayerAPIAssetBuyerManager } from './standard_relayer_api_asset_buyer_manager';
+export { AssetBuyerManager } from './asset_buyer_manager';
export {
AssetBuyerError,
+ AssetBuyerOpts,
BuyQuote,
+ BuyQuoteExecutionOpts,
+ BuyQuoteRequestOpts,
OrderProvider,
OrderProviderRequest,
OrderProviderResponse,
SignedOrderWithRemainingFillableMakerAssetAmount,
- StandardRelayerApiAssetBuyerManagerError,
+ AssetBuyerManagerError,
} from './types';
diff --git a/packages/asset-buyer/src/standard_relayer_api_asset_buyer_manager.ts b/packages/asset-buyer/src/standard_relayer_api_asset_buyer_manager.ts
deleted file mode 100644
index 947c738a1..000000000
--- a/packages/asset-buyer/src/standard_relayer_api_asset_buyer_manager.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-import { HttpClient } from '@0xproject/connect';
-import { ContractWrappers } from '@0xproject/contract-wrappers';
-import { ObjectMap } from '@0xproject/types';
-import { Provider } from 'ethereum-types';
-import * as _ from 'lodash';
-
-import { AssetBuyer } from './asset_buyer';
-import { constants } from './constants';
-import { assert } from './utils/assert';
-import { assetDataUtils } from './utils/asset_data_utils';
-
-import { OrderProvider, StandardRelayerApiAssetBuyerManagerError } from './types';
-
-export class StandardRelayerAPIAssetBuyerManager {
- // Map of assetData to AssetBuyer for that assetData
- private readonly _assetBuyerMap: ObjectMap<AssetBuyer>;
- /**
- * Returns an array of all assetDatas available at the provided sraApiUrl
- * @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
- * @param pairedWithAssetData Optional filter argument to return assetDatas that only pair with this assetData value.
- *
- * @return An array of all assetDatas available at the provider sraApiUrl
- */
- public static async getAllAvailableAssetDatasAsync(
- sraApiUrl: string,
- pairedWithAssetData?: string,
- ): Promise<string[]> {
- const client = new HttpClient(sraApiUrl);
- const params = {
- assetDataA: pairedWithAssetData,
- perPage: constants.MAX_PER_PAGE,
- };
- const assetPairsResponse = await client.getAssetPairsAsync(params);
- return _.uniq(_.map(assetPairsResponse.records, pairsItem => pairsItem.assetDataB.assetData));
- }
- /**
- * Instantiates a new StandardRelayerAPIAssetBuyerManager instance with all available assetDatas at the provided sraApiUrl
- * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
- * @param sraApiUrl The standard relayer API base HTTP url you would like to source orders from.
- * @param orderProvider An object that conforms to OrderProvider, see type for definition.
- * @param networkId The ethereum network id. Defaults to 1 (mainnet).
- * @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states.
- * Defaults to 10000ms (10s).
- * @return An promise of an instance of StandardRelayerAPIAssetBuyerManager
- */
- public static async getAssetBuyerManagerWithAllAvailableAssetDatasAsync(
- provider: Provider,
- sraApiUrl: string,
- orderProvider: OrderProvider,
- networkId: number = constants.MAINNET_NETWORK_ID,
- orderRefreshIntervalMs?: number,
- ): Promise<StandardRelayerAPIAssetBuyerManager> {
- const contractWrappers = new ContractWrappers(provider, { networkId });
- const etherTokenAssetData = assetDataUtils.getEtherTokenAssetDataOrThrow(contractWrappers);
- const assetDatas = await StandardRelayerAPIAssetBuyerManager.getAllAvailableAssetDatasAsync(
- sraApiUrl,
- etherTokenAssetData,
- );
- return new StandardRelayerAPIAssetBuyerManager(
- provider,
- assetDatas,
- orderProvider,
- networkId,
- orderRefreshIntervalMs,
- );
- }
- /**
- * Instantiates a new StandardRelayerAPIAssetBuyerManager instance
- * @param provider The Provider instance you would like to use for interacting with the Ethereum network.
- * @param assetDatas The assetDatas of the desired assets to buy (for more info: https://github.com/0xProject/0x-protocol-specification/blob/master/v2/v2-specification.md).
- * @param orderProvider An object that conforms to OrderProvider, see type for definition.
- * @param networkId The ethereum network id. Defaults to 1 (mainnet).
- * @param orderRefreshIntervalMs The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states.
- * Defaults to 10000ms (10s).
- * @return An instance of StandardRelayerAPIAssetBuyerManager
- */
- constructor(
- provider: Provider,
- assetDatas: string[],
- orderProvider: OrderProvider,
- networkId?: number,
- orderRefreshIntervalMs?: number,
- ) {
- assert.assert(assetDatas.length > 0, `Expected 'assetDatas' to be a non-empty array.`);
- this._assetBuyerMap = _.reduce(
- assetDatas,
- (accAssetBuyerMap: ObjectMap<AssetBuyer>, assetData: string) => {
- accAssetBuyerMap[assetData] = new AssetBuyer(
- provider,
- assetData,
- orderProvider,
- networkId,
- orderRefreshIntervalMs,
- );
- return accAssetBuyerMap;
- },
- {},
- );
- }
- /**
- * Get an AssetBuyer for the provided assetData
- * @param assetData The desired assetData.
- *
- * @return An instance of AssetBuyer
- */
- public getAssetBuyerFromAssetData(assetData: string): AssetBuyer {
- const assetBuyer = this._assetBuyerMap[assetData];
- if (_.isUndefined(assetBuyer)) {
- throw new Error(
- `${StandardRelayerApiAssetBuyerManagerError.AssetBuyerNotFound}: For assetData ${assetData}`,
- );
- }
- return assetBuyer;
- }
- /**
- * Get an AssetBuyer for the provided ERC20 tokenAddress
- * @param tokenAddress The desired tokenAddress.
- *
- * @return An instance of AssetBuyer
- */
- public getAssetBuyerFromERC20TokenAddress(tokenAddress: string): AssetBuyer {
- const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress);
- return this.getAssetBuyerFromAssetData(assetData);
- }
- /**
- * Get a list of all the assetDatas that the instance supports
- *
- * @return An array of assetData strings
- */
- public getAssetDatas(): string[] {
- return _.keys(this._assetBuyerMap);
- }
-}
diff --git a/packages/asset-buyer/src/types.ts b/packages/asset-buyer/src/types.ts
index ee6858525..67baa51c7 100644
--- a/packages/asset-buyer/src/types.ts
+++ b/packages/asset-buyer/src/types.ts
@@ -52,6 +52,11 @@ export interface BuyQuote {
feePercentage?: number;
}
+/**
+ * feePercentage: The affiliate fee percentage. Defaults to 0.
+ * shouldForceOrderRefresh: If set to true, new orders and state will be fetched instead of waiting for the next orderRefreshIntervalMs. Defaults to false.
+ * slippagePercentage: The percentage buffer to add to account for slippage. Affects max ETH price estimates. Defaults to 0.2 (20%).
+ */
export interface BuyQuoteRequestOpts {
feePercentage: number;
shouldForceOrderRefresh: boolean;
@@ -59,6 +64,28 @@ export interface BuyQuoteRequestOpts {
}
/**
+ * rate: The desired rate to execute the buy at. Affects the amount of ETH sent with the transaction, defaults to buyQuote.maxRate.
+ * takerAddress: The address to perform the buy. Defaults to the first available address from the provider.
+ * feeRecipient: The address where affiliate fees are sent. Defaults to null address (0x000...000).
+ */
+export interface BuyQuoteExecutionOpts {
+ rate?: BigNumber;
+ takerAddress?: string;
+ feeRecipient: string;
+}
+
+/**
+ * networkId: The ethereum network id. Defaults to 1 (mainnet).
+ * orderRefreshIntervalMs: The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
+ * expiryBufferSeconds: The number of seconds to add when calculating whether an order is expired or not. Defaults to 15s.
+ */
+export interface AssetBuyerOpts {
+ networkId: number;
+ orderRefreshIntervalMs: number;
+ expiryBufferSeconds: number;
+}
+
+/**
* Possible errors thrown by an AssetBuyer instance or associated static methods.
*/
export enum AssetBuyerError {
@@ -72,9 +99,9 @@ export enum AssetBuyerError {
}
/**
- * Possible errors thrown by an StandardRelayerApiAssetBuyerManager instance or associated static methods.
+ * Possible errors thrown by an AssetBuyerManager instance or associated static methods.
*/
-export enum StandardRelayerApiAssetBuyerManagerError {
+export enum AssetBuyerManagerError {
AssetBuyerNotFound = 'ASSET_BUYER_NOT_FOUND',
}