diff options
Diffstat (limited to 'packages/fill-scenarios/src/index.ts')
-rw-r--r-- | packages/fill-scenarios/src/index.ts | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/packages/fill-scenarios/src/index.ts b/packages/fill-scenarios/src/index.ts new file mode 100644 index 000000000..28b64208b --- /dev/null +++ b/packages/fill-scenarios/src/index.ts @@ -0,0 +1,245 @@ +import { formatters, orderFactory } from '@0xproject/order-utils'; +import { Provider, SignedOrder, Token } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import { Web3Wrapper } from '@0xproject/web3-wrapper'; +import * as _ from 'lodash'; + +import { artifacts } from './artifacts'; +import { constants } from './constants'; +import { DummyTokenContract } from './generated_contract_wrappers/dummy_token'; +import { ExchangeContract } from './generated_contract_wrappers/exchange'; +import { TokenContract } from './generated_contract_wrappers/token'; + +const INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS = new BigNumber(100); + +export class FillScenarios { + private _provider: Provider; + private _web3Wrapper: Web3Wrapper; + private _userAddresses: string[]; + private _tokens: Token[]; + private _coinbase: string; + private _zrxTokenAddress: string; + private _exchangeContractAddress: string; + constructor( + provider: Provider, + userAddresses: string[], + tokens: Token[], + zrxTokenAddress: string, + exchangeContractAddress: string, + ) { + this._provider = provider; + this._web3Wrapper = new Web3Wrapper(this._provider); + this._userAddresses = userAddresses; + this._tokens = tokens; + this._coinbase = userAddresses[0]; + this._zrxTokenAddress = zrxTokenAddress; + this._exchangeContractAddress = exchangeContractAddress; + } + public async initTokenBalancesAsync() { + for (const token of this._tokens) { + if (token.symbol !== 'ZRX' && token.symbol !== 'WETH') { + const defaults = {}; + const dummyToken = new DummyTokenContract( + artifacts.DummyToken.abi, + token.address, + this._provider, + this._web3Wrapper.getContractDefaults(), + ); + const tokenSupply = Web3Wrapper.toBaseUnitAmount( + INITIAL_COINBASE_TOKEN_SUPPLY_IN_UNITS, + token.decimals, + ); + const txHash = await dummyToken.setBalance.sendTransactionAsync(this._coinbase, tokenSupply, { + from: this._coinbase, + }); + await this._web3Wrapper.awaitTransactionMinedAsync(txHash); + } + } + } + public async createFillableSignedOrderAsync( + makerTokenAddress: string, + takerTokenAddress: string, + makerAddress: string, + takerAddress: string, + fillableAmount: BigNumber, + expirationUnixTimestampSec?: BigNumber, + ): Promise<SignedOrder> { + return this.createAsymmetricFillableSignedOrderAsync( + makerTokenAddress, + takerTokenAddress, + makerAddress, + takerAddress, + fillableAmount, + fillableAmount, + expirationUnixTimestampSec, + ); + } + public async createFillableSignedOrderWithFeesAsync( + makerTokenAddress: string, + takerTokenAddress: string, + makerFee: BigNumber, + takerFee: BigNumber, + makerAddress: string, + takerAddress: string, + fillableAmount: BigNumber, + feeRecepient: string, + expirationUnixTimestampSec?: BigNumber, + ): Promise<SignedOrder> { + return this._createAsymmetricFillableSignedOrderWithFeesAsync( + makerTokenAddress, + takerTokenAddress, + makerFee, + takerFee, + makerAddress, + takerAddress, + fillableAmount, + fillableAmount, + feeRecepient, + expirationUnixTimestampSec, + ); + } + public async createAsymmetricFillableSignedOrderAsync( + makerTokenAddress: string, + takerTokenAddress: string, + makerAddress: string, + takerAddress: string, + makerFillableAmount: BigNumber, + takerFillableAmount: BigNumber, + expirationUnixTimestampSec?: BigNumber, + ): Promise<SignedOrder> { + const makerFee = new BigNumber(0); + const takerFee = new BigNumber(0); + const feeRecepient = constants.NULL_ADDRESS; + return this._createAsymmetricFillableSignedOrderWithFeesAsync( + makerTokenAddress, + takerTokenAddress, + makerFee, + takerFee, + makerAddress, + takerAddress, + makerFillableAmount, + takerFillableAmount, + feeRecepient, + expirationUnixTimestampSec, + ); + } + public async createPartiallyFilledSignedOrderAsync( + makerTokenAddress: string, + takerTokenAddress: string, + takerAddress: string, + fillableAmount: BigNumber, + partialFillAmount: BigNumber, + ) { + const [makerAddress] = this._userAddresses; + const signedOrder = await this.createAsymmetricFillableSignedOrderAsync( + makerTokenAddress, + takerTokenAddress, + makerAddress, + takerAddress, + fillableAmount, + fillableAmount, + ); + const shouldThrowOnInsufficientBalanceOrAllowance = false; + const exchangeInstance = new ExchangeContract( + artifacts.Exchange.abi, + signedOrder.exchangeContractAddress, + this._provider, + this._web3Wrapper.getContractDefaults(), + ); + + const [orderAddresses, orderValues] = formatters.getOrderAddressesAndValues(signedOrder); + + await exchangeInstance.fillOrder.sendTransactionAsync( + orderAddresses, + orderValues, + partialFillAmount, + shouldThrowOnInsufficientBalanceOrAllowance, + signedOrder.ecSignature.v, + signedOrder.ecSignature.r, + signedOrder.ecSignature.s, + { from: takerAddress }, + ); + return signedOrder; + } + private async _createAsymmetricFillableSignedOrderWithFeesAsync( + makerTokenAddress: string, + takerTokenAddress: string, + makerFee: BigNumber, + takerFee: BigNumber, + makerAddress: string, + takerAddress: string, + makerFillableAmount: BigNumber, + takerFillableAmount: BigNumber, + feeRecepient: string, + expirationUnixTimestampSec?: BigNumber, + ): Promise<SignedOrder> { + await Promise.all([ + this._increaseBalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount), + this._increaseBalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount), + ]); + await Promise.all([ + this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee), + this._increaseBalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee), + ]); + + const signedOrder = await orderFactory.createSignedOrderAsync( + this._provider, + makerAddress, + takerAddress, + makerFee, + takerFee, + makerFillableAmount, + makerTokenAddress, + takerFillableAmount, + takerTokenAddress, + this._exchangeContractAddress, + feeRecepient, + expirationUnixTimestampSec, + ); + return signedOrder; + } + private async _increaseBalanceAndAllowanceAsync( + tokenAddress: string, + address: string, + amount: BigNumber, + ): Promise<void> { + if (amount.isZero() || address === constants.NULL_ADDRESS) { + return; // noop + } + await Promise.all([ + this._increaseBalanceAsync(tokenAddress, address, amount), + this._increaseAllowanceAsync(tokenAddress, address, amount), + ]); + } + private async _increaseBalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> { + const token = new TokenContract( + artifacts.Token.abi, + tokenAddress, + this._provider, + this._web3Wrapper.getContractDefaults(), + ); + await token.transfer.sendTransactionAsync(address, amount, { + from: this._coinbase, + }); + } + private async _increaseAllowanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> { + const tokenInstance = new TokenContract( + artifacts.Token.abi, + tokenAddress, + this._provider, + this._web3Wrapper.getContractDefaults(), + ); + const txData = {}; + const networkArtifactsIfExists = artifacts.TokenTransferProxy.networks[constants.TEST_RPC_NETWORK_ID]; + if (_.isUndefined(networkArtifactsIfExists)) { + throw new Error(`Did not find network artifacts for networkId: ${constants.TEST_RPC_NETWORK_ID}`); + } + const proxyAddress = networkArtifactsIfExists.address; + const oldMakerAllowance = await tokenInstance.allowance.callAsync(address, proxyAddress, txData); + const newMakerAllowance = oldMakerAllowance.plus(amount); + + await tokenInstance.approve.sendTransactionAsync(proxyAddress, newMakerAllowance, { + from: address, + }); + } +} |