From ab5e021bda5cc8e39d8595580c09c3540a09aff5 Mon Sep 17 00:00:00 2001 From: Fabio Berger Date: Thu, 7 Jun 2018 18:00:13 +0200 Subject: POC: Generates an order from spec, get's the amount fillable --- packages/contracts/src/utils/new_order_factory.ts | 264 ++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 packages/contracts/src/utils/new_order_factory.ts (limited to 'packages/contracts/src/utils/new_order_factory.ts') diff --git a/packages/contracts/src/utils/new_order_factory.ts b/packages/contracts/src/utils/new_order_factory.ts new file mode 100644 index 000000000..a4ded4230 --- /dev/null +++ b/packages/contracts/src/utils/new_order_factory.ts @@ -0,0 +1,264 @@ +import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { Order } from '@0xproject/types'; +import { BigNumber, errorUtils } from '@0xproject/utils'; + +import { DummyERC721TokenContract } from '../contract_wrappers/generated/dummy_e_r_c721_token'; + +import { constants } from './constants'; +import { + AssetDataScenario, + ERC721TokenIdsByOwner, + ExpirationTimeSecondsScenario, + FeeRecipientAddressScenario, + OrderAmountScenario, +} from './types'; + +const TEN_UNITS_EIGHTEEN_DECIMALS = new BigNumber(10000000000000000000); +const POINT_ONE_UNITS_EIGHTEEN_DECIMALS = new BigNumber(100000000000000000); +const TEN_UNITS_FIVE_DECIMALS = new BigNumber(1000000); +const ONE_NFT_UNIT = new BigNumber(1); +const TEN_MINUTES_MS = 1000 * 60 * 10; + +/* + * TODO: + * - Write function that given an order, fillAmount, retrieves orderRelevantState and maps it to expected test outcome. + * - Write function that generates order permutations. + * - Write functions for other steps that must be permutated + */ + +export class NewOrderFactory { + private _userAddresses: string[]; + private _zrxAddress: string; + private _nonZrxERC20EighteenDecimalTokenAddresses: string[]; + private _erc20FiveDecimalTokenAddresses: string[]; + private _erc721Token: DummyERC721TokenContract; + private _erc721Balances: ERC721TokenIdsByOwner; + private _exchangeAddress: string; + constructor( + userAddresses: string[], + zrxAddress: string, + nonZrxERC20EighteenDecimalTokenAddresses: string[], + erc20FiveDecimalTokenAddresses: string[], + erc721Token: DummyERC721TokenContract, + erc721Balances: ERC721TokenIdsByOwner, + exchangeAddress: string, + ) { + this._userAddresses = userAddresses; + this._zrxAddress = zrxAddress; + this._nonZrxERC20EighteenDecimalTokenAddresses = nonZrxERC20EighteenDecimalTokenAddresses; + this._erc20FiveDecimalTokenAddresses = erc20FiveDecimalTokenAddresses; + this._erc721Token = erc721Token; + this._erc721Balances = erc721Balances; + this._exchangeAddress = exchangeAddress; + } + public generateOrder( + feeRecipientScenario: FeeRecipientAddressScenario, + makerAssetAmountScenario: OrderAmountScenario, + takerAssetAmountScenario: OrderAmountScenario, + makerFeeScenario: OrderAmountScenario, + takerFeeScenario: OrderAmountScenario, + expirationTimeSecondsScenario: ExpirationTimeSecondsScenario, + makerAssetDataScenario: AssetDataScenario, + takerAssetDataScenario: AssetDataScenario, + ): Order { + const makerAddress = this._userAddresses[1]; + const takerAddress = this._userAddresses[2]; + const erc721MakerAssetIds = this._erc721Balances[makerAddress][this._erc721Token.address]; + const erc721TakerAssetIds = this._erc721Balances[takerAddress][this._erc721Token.address]; + let feeRecipientAddress; + let makerAssetAmount; + let takerAssetAmount; + let makerFee; + let takerFee; + let expirationTimeSeconds; + let makerAssetData; + let takerAssetData; + + switch (feeRecipientScenario) { + case FeeRecipientAddressScenario.BurnAddress: + feeRecipientAddress = constants.NULL_ADDRESS; + break; + case FeeRecipientAddressScenario.EthUserAddress: + feeRecipientAddress = this._userAddresses[4]; + break; + default: + throw errorUtils.spawnSwitchErr('FeeRecipientAddressScenario', feeRecipientScenario); + } + + const invalidAssetProxyIdHex = '0A'; + switch (makerAssetDataScenario) { + case AssetDataScenario.ZRXFeeToken: + makerAssetData = assetProxyUtils.encodeERC20ProxyData(this._zrxAddress); + break; + case AssetDataScenario.ERC20NonZRXEighteenDecimals: + makerAssetData = assetProxyUtils.encodeERC20ProxyData( + this._nonZrxERC20EighteenDecimalTokenAddresses[0], + ); + break; + case AssetDataScenario.ERC20FiveDecimals: + makerAssetData = assetProxyUtils.encodeERC20ProxyData(this._erc20FiveDecimalTokenAddresses[0]); + break; + case AssetDataScenario.ERC20InvalidAssetProxyId: { + const validAssetData = assetProxyUtils.encodeERC20ProxyData( + this._nonZrxERC20EighteenDecimalTokenAddresses[0], + ); + makerAssetData = `${validAssetData.slice(0, -2)}${invalidAssetProxyIdHex}`; + break; + } + case AssetDataScenario.ERC721ValidAssetProxyId: + makerAssetData = assetProxyUtils.encodeERC721ProxyData( + this._erc721Token.address, + erc721MakerAssetIds[0], + ); + break; + case AssetDataScenario.ERC721InvalidAssetProxyId: { + const validAssetData = assetProxyUtils.encodeERC721ProxyData( + this._erc721Token.address, + erc721MakerAssetIds[0], + ); + makerAssetData = `${validAssetData.slice(0, -2)}${invalidAssetProxyIdHex}`; + break; + } + default: + throw errorUtils.spawnSwitchErr('AssetDataScenario', makerAssetDataScenario); + } + + switch (takerAssetDataScenario) { + case AssetDataScenario.ZRXFeeToken: + takerAssetData = assetProxyUtils.encodeERC20ProxyData(this._zrxAddress); + break; + case AssetDataScenario.ERC20NonZRXEighteenDecimals: + takerAssetData = assetProxyUtils.encodeERC20ProxyData( + this._nonZrxERC20EighteenDecimalTokenAddresses[1], + ); + break; + case AssetDataScenario.ERC20FiveDecimals: + takerAssetData = assetProxyUtils.encodeERC20ProxyData(this._erc20FiveDecimalTokenAddresses[1]); + break; + case AssetDataScenario.ERC20InvalidAssetProxyId: { + const validAssetData = assetProxyUtils.encodeERC20ProxyData( + this._nonZrxERC20EighteenDecimalTokenAddresses[1], + ); + takerAssetData = `${validAssetData.slice(0, -2)}${invalidAssetProxyIdHex}`; + break; + } + case AssetDataScenario.ERC721ValidAssetProxyId: + takerAssetData = assetProxyUtils.encodeERC721ProxyData( + this._erc721Token.address, + erc721TakerAssetIds[0], + ); + break; + case AssetDataScenario.ERC721InvalidAssetProxyId: { + const validAssetData = assetProxyUtils.encodeERC721ProxyData( + this._erc721Token.address, + erc721TakerAssetIds[0], + ); + takerAssetData = `${validAssetData.slice(0, -2)}${invalidAssetProxyIdHex}`; + break; + } + default: + throw errorUtils.spawnSwitchErr('AssetDataScenario', takerAssetDataScenario); + } + + switch (makerAssetAmountScenario) { + case OrderAmountScenario.NonZero: + switch (makerAssetDataScenario) { + case AssetDataScenario.ERC20NonZRXEighteenDecimals: + case AssetDataScenario.ERC20InvalidAssetProxyId: + makerAssetAmount = TEN_UNITS_EIGHTEEN_DECIMALS; + break; + case AssetDataScenario.ERC20FiveDecimals: + makerAssetAmount = TEN_UNITS_FIVE_DECIMALS; + break; + case AssetDataScenario.ERC721ValidAssetProxyId: + case AssetDataScenario.ERC721InvalidAssetProxyId: + makerAssetAmount = ONE_NFT_UNIT; + break; + default: + throw errorUtils.spawnSwitchErr('AssetDataScenario', makerAssetDataScenario); + } + break; + case OrderAmountScenario.Zero: + makerAssetAmount = new BigNumber(0); + break; + default: + throw errorUtils.spawnSwitchErr('OrderAmountScenario', makerAssetAmountScenario); + } + + switch (takerAssetAmountScenario) { + case OrderAmountScenario.NonZero: + switch (takerAssetDataScenario) { + case AssetDataScenario.ERC20NonZRXEighteenDecimals: + case AssetDataScenario.ERC20InvalidAssetProxyId: + takerAssetAmount = TEN_UNITS_EIGHTEEN_DECIMALS; + break; + case AssetDataScenario.ERC20FiveDecimals: + takerAssetAmount = TEN_UNITS_FIVE_DECIMALS; + break; + case AssetDataScenario.ERC721ValidAssetProxyId: + case AssetDataScenario.ERC721InvalidAssetProxyId: + takerAssetAmount = ONE_NFT_UNIT; + break; + default: + throw errorUtils.spawnSwitchErr('AssetDataScenario', takerAssetDataScenario); + } + break; + case OrderAmountScenario.Zero: + takerAssetAmount = new BigNumber(0); + break; + default: + throw errorUtils.spawnSwitchErr('OrderAmountScenario', takerAssetAmountScenario); + } + + switch (makerFeeScenario) { + case OrderAmountScenario.NonZero: + makerFee = POINT_ONE_UNITS_EIGHTEEN_DECIMALS; + break; + case OrderAmountScenario.Zero: + makerFee = new BigNumber(0); + break; + default: + throw errorUtils.spawnSwitchErr('OrderAmountScenario', makerFeeScenario); + } + + switch (takerFeeScenario) { + case OrderAmountScenario.NonZero: + takerFee = POINT_ONE_UNITS_EIGHTEEN_DECIMALS; + break; + case OrderAmountScenario.Zero: + takerFee = new BigNumber(0); + break; + default: + throw errorUtils.spawnSwitchErr('OrderAmountScenario', takerFeeScenario); + } + + switch (expirationTimeSecondsScenario) { + case ExpirationTimeSecondsScenario.InFuture: + expirationTimeSeconds = new BigNumber(Date.now() + TEN_MINUTES_MS); + break; + case ExpirationTimeSecondsScenario.InPast: + expirationTimeSeconds = new BigNumber(Date.now() - TEN_MINUTES_MS); + break; + default: + throw errorUtils.spawnSwitchErr('ExpirationTimeSecondsScenario', expirationTimeSecondsScenario); + } + + const order: Order = { + senderAddress: constants.NULL_ADDRESS, + makerAddress, + takerAddress, + makerFee, + takerFee, + makerAssetAmount, + takerAssetAmount, + makerAssetData, + takerAssetData, + salt: generatePseudoRandomSalt(), + exchangeAddress: this._exchangeAddress, + feeRecipientAddress, + expirationTimeSeconds, + }; + + return order; + } +} -- cgit v1.2.3