Merge
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
"stage_docs": "wsrun docs:stage $PKG --fast-exit --parallel --exclude-missing",
|
||||
"lint": "wsrun lint $PKG --fast-exit --parallel --exclude-missing",
|
||||
"comment:postinstall": "HACK: For some reason `yarn` is not setting up symlinks properly for order-utils. We temporarily set them manually. Remove this after V2 refactor is complete.",
|
||||
"postinstall": "rm -rf `pwd`/packages/0x.js/node_modules/@0xproject; mkdir `pwd`/packages/0x.js/node_modules/@0xproject; ln -s `pwd`/packages/contract-wrappers `pwd`/packages/0x.js/node_modules/@0xproject/contract-wrappers; ln -s `pwd`/packages/order-utils `pwd`/packages/0x.js/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/0x.js/node_modules/@0xproject/types; rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/assert `pwd`/packages/order-utils/node_modules/@0xproject/assert; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -f `pwd`/packages/contracts/node_modules/@0xproject/types; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; rm -rf `pwd`/packages/fill-scenarios/node_modules/@0xproject; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/json-schemas `pwd`/packages/fill-scenarios/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/contract-wrappers/node_modules/@0xproject; mkdir -p `pwd`/packages/contract-wrappers/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contract-wrappers/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/assert `pwd`/packages/contract-wrappers/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/contract-wrappers/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/contract-wrappers/node_modules/@0xproject/types; ln -s `pwd`/packages/fill-scenarios `pwd`/packages/contract-wrappers/node_modules/@0xproject/fill-scenarios; rm -rf `pwd`/packages/assert/node_modules/@0xproject; mkdir -p `pwd`/packages/assert/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/assert/node_modules/@0xproject/json-schemas; rm -rf `pwd`/packages/order-watcher/node_modules/@0xproject; mkdir `pwd`/packages/order-watcher/node_modules/@0xproject; ln -s `pwd`/packages/assert `pwd`/packages/order-watcher/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-watcher/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/order-watcher/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/order-watcher/node_modules/@0xproject/types; ln -s `pwd`/packages/contract-wrappers `pwd`/packages/order-watcher/node_modules/@0xproject/contract-wrappers; rm -rf `pwd`/packages/contracts/node_modules/@0xproject; mkdir `pwd`/packages/contracts/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contracts/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/migrations/node_modules/@0xproject; mkdir `pwd`/packages/migrations/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/migrations/node_modules/@0xproject/order-utils"
|
||||
"postinstall": "rm -rf `pwd`/packages/0x.js/node_modules/@0xproject; mkdir `pwd`/packages/0x.js/node_modules/@0xproject; ln -s `pwd`/packages/contract-wrappers `pwd`/packages/0x.js/node_modules/@0xproject/contract-wrappers; ln -s `pwd`/packages/order-utils `pwd`/packages/0x.js/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/0x.js/node_modules/@0xproject/types; rm -rf `pwd`/packages/order-utils/node_modules/@0xproject; mkdir `pwd`/packages/order-utils/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-utils/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/assert `pwd`/packages/order-utils/node_modules/@0xproject/assert; ln -s `pwd`/packages/types `pwd`/packages/order-utils/node_modules/@0xproject/types; rm -rf `pwd`/packages/fill-scenarios/node_modules/@0xproject; mkdir -p `pwd`/packages/fill-scenarios/node_modules/@0xproject; ln -s `pwd`/packages/types `pwd`/packages/fill-scenarios/node_modules/@0xproject/types; ln -s `pwd`/packages/json-schemas `pwd`/packages/fill-scenarios/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/fill-scenarios/node_modules/@0xproject/order-utils; rm -rf `pwd`/packages/contract-wrappers/node_modules/@0xproject; mkdir -p `pwd`/packages/contract-wrappers/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contract-wrappers/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/assert `pwd`/packages/contract-wrappers/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/contract-wrappers/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/types `pwd`/packages/contract-wrappers/node_modules/@0xproject/types; ln -s `pwd`/packages/fill-scenarios `pwd`/packages/contract-wrappers/node_modules/@0xproject/fill-scenarios; rm -rf `pwd`/packages/assert/node_modules/@0xproject; mkdir -p `pwd`/packages/assert/node_modules/@0xproject; ln -s `pwd`/packages/json-schemas `pwd`/packages/assert/node_modules/@0xproject/json-schemas; rm -rf `pwd`/packages/order-watcher/node_modules/@0xproject; mkdir `pwd`/packages/order-watcher/node_modules/@0xproject; ln -s `pwd`/packages/assert `pwd`/packages/order-watcher/node_modules/@0xproject/assert; ln -s `pwd`/packages/json-schemas `pwd`/packages/order-watcher/node_modules/@0xproject/json-schemas; ln -s `pwd`/packages/order-utils `pwd`/packages/order-watcher/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/order-watcher/node_modules/@0xproject/types; ln -s `pwd`/packages/contract-wrappers `pwd`/packages/order-watcher/node_modules/@0xproject/contract-wrappers; rm -rf `pwd`/packages/contracts/node_modules/@0xproject; mkdir `pwd`/packages/contracts/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/contracts/node_modules/@0xproject/order-utils; ln -s `pwd`/packages/types `pwd`/packages/contracts/node_modules/@0xproject/types; rm -rf `pwd`/packages/migrations/node_modules/@0xproject; mkdir `pwd`/packages/migrations/node_modules/@0xproject; ln -s `pwd`/packages/order-utils `pwd`/packages/migrations/node_modules/@0xproject/order-utils"
|
||||
},
|
||||
"config": {
|
||||
"mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic"
|
||||
|
||||
@@ -10021,11 +10021,5 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"networks": {
|
||||
"50": {
|
||||
"address": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c",
|
||||
"links": {},
|
||||
"constructorArgs": "[]"
|
||||
}
|
||||
}
|
||||
"networks": {}
|
||||
}
|
||||
@@ -342,15 +342,17 @@ export class ERC721TokenWrapper extends ContractWrapper {
|
||||
const normalizedSenderAddress = senderAddress.toLowerCase();
|
||||
const tokenContract = await this._getTokenContractAsync(normalizedTokenAddress);
|
||||
const ownerAddress = await this.getOwnerOfAsync(tokenAddress, tokenId);
|
||||
const isApprovedForAll = await this.isApprovedForAllAsync(
|
||||
normalizedTokenAddress,
|
||||
ownerAddress,
|
||||
normalizedSenderAddress,
|
||||
);
|
||||
if (!isApprovedForAll) {
|
||||
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
|
||||
if (approvedAddress !== senderAddress) {
|
||||
throw new Error(ContractWrappersError.ERC721NoApproval);
|
||||
if (normalizedSenderAddress !== ownerAddress) {
|
||||
const isApprovedForAll = await this.isApprovedForAllAsync(
|
||||
normalizedTokenAddress,
|
||||
ownerAddress,
|
||||
normalizedSenderAddress,
|
||||
);
|
||||
if (!isApprovedForAll) {
|
||||
const approvedAddress = await this.getApprovedIfExistsAsync(normalizedTokenAddress, tokenId);
|
||||
if (approvedAddress !== normalizedSenderAddress) {
|
||||
throw new Error(ContractWrappersError.ERC721NoApproval);
|
||||
}
|
||||
}
|
||||
}
|
||||
const txHash = await tokenContract.transferFrom.sendTransactionAsync(
|
||||
|
||||
@@ -53,7 +53,6 @@ describe('ExchangeWrapper', () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
contractWrappers = new ContractWrappers(provider, config);
|
||||
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
|
||||
const erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
|
||||
fillScenarios = new FillScenarios(
|
||||
@@ -61,7 +60,8 @@ describe('ExchangeWrapper', () => {
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
erc20ProxyAddress,
|
||||
contractWrappers.erc20Proxy.getContractAddress(),
|
||||
contractWrappers.erc721Proxy.getContractAddress(),
|
||||
);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
|
||||
@@ -145,7 +145,7 @@ export class ForwarderWrapper {
|
||||
feeProportion: number,
|
||||
makerAssetFillAmount: BigNumber,
|
||||
): Promise<BigNumber> {
|
||||
const makerAssetData = assetProxyUtils.decodeAssetData(orders[0].makerAssetData);
|
||||
const makerAssetData = assetProxyUtils.decodeAssetDataOrThrow(orders[0].makerAssetData);
|
||||
const makerAssetToken = makerAssetData.tokenAddress;
|
||||
const params = formatters.createMarketBuyOrders(orders, makerAssetFillAmount);
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
"build": "yarn pre_build && tsc",
|
||||
"pre_build": "run-s update_artifacts generate_contract_wrappers",
|
||||
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/artifacts; done;",
|
||||
"generate_contract_wrappers": "abi-gen --abis 'lib/artifacts/@(Exchange|ERC20Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
|
||||
"generate_contract_wrappers": "abi-gen --abis 'lib/artifacts/@(Exchange|DummyERC20Token|DummyERC721Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
|
||||
"copy_monorepo_scripts": "copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
|
||||
"clean": "shx rm -rf lib scripts src/generated_contract_wrappers",
|
||||
"lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
|
||||
"manual:postpublish": "yarn build; node ./scripts/postpublish.js"
|
||||
},
|
||||
"config": {
|
||||
"contracts": "Exchange ERC20Token"
|
||||
"contracts": "Exchange DummyERC20Token DummyERC721Token"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { ContractArtifact } from '@0xproject/sol-compiler';
|
||||
|
||||
import * as ERC20Token from './artifacts/ERC20Token.json';
|
||||
import * as DummyERC20Token from './artifacts/DummyERC20Token.json';
|
||||
import * as DummyERC721Token from './artifacts/DummyERC721Token.json';
|
||||
import * as Exchange from './artifacts/Exchange.json';
|
||||
|
||||
export const artifacts = {
|
||||
ERC20Token: (ERC20Token as any) as ContractArtifact,
|
||||
DummyERC20Token: (DummyERC20Token as any) as ContractArtifact,
|
||||
DummyERC721Token: (DummyERC721Token as any) as ContractArtifact,
|
||||
Exchange: (Exchange as any) as ContractArtifact,
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export const constants = {
|
||||
AWAIT_TRANSACTION_MINED_MS: 0,
|
||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||
};
|
||||
|
||||
298
packages/fill-scenarios/src/fill_scenarios.ts
Normal file
298
packages/fill-scenarios/src/fill_scenarios.ts
Normal file
@@ -0,0 +1,298 @@
|
||||
import { assetProxyUtils, orderFactory } from '@0xproject/order-utils';
|
||||
import { AssetProxyId, ERC721AssetData, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import { Provider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { constants } from './constants';
|
||||
import { DummyERC20TokenContract } from './generated_contract_wrappers/dummy_erc20_token';
|
||||
import { DummyERC721TokenContract } from './generated_contract_wrappers/dummy_erc721_token';
|
||||
import { ExchangeContract } from './generated_contract_wrappers/exchange';
|
||||
|
||||
export class FillScenarios {
|
||||
private _web3Wrapper: Web3Wrapper;
|
||||
private _userAddresses: string[];
|
||||
private _coinbase: string;
|
||||
private _zrxTokenAddress: string;
|
||||
private _exchangeAddress: string;
|
||||
private _erc20ProxyAddress: string;
|
||||
private _erc721ProxyAddress: string;
|
||||
constructor(
|
||||
provider: Provider,
|
||||
userAddresses: string[],
|
||||
zrxTokenAddress: string,
|
||||
exchangeAddress: string,
|
||||
erc20ProxyAddress: string,
|
||||
erc721ProxyAddress: string,
|
||||
) {
|
||||
this._web3Wrapper = new Web3Wrapper(provider);
|
||||
this._userAddresses = userAddresses;
|
||||
this._coinbase = userAddresses[0];
|
||||
this._zrxTokenAddress = zrxTokenAddress;
|
||||
this._exchangeAddress = exchangeAddress;
|
||||
this._erc20ProxyAddress = erc20ProxyAddress;
|
||||
this._erc721ProxyAddress = erc721ProxyAddress;
|
||||
}
|
||||
public async createFillableSignedOrderAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
public async createFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerFee: BigNumber,
|
||||
takerFee: BigNumber,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
feeRecepientAddress: string,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
public async createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const makerFee = new BigNumber(0);
|
||||
const takerFee = new BigNumber(0);
|
||||
const feeRecepientAddress = constants.NULL_ADDRESS;
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
public async createPartiallyFilledSignedOrderAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
partialFillAmount: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const [makerAddress] = this._userAddresses;
|
||||
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
);
|
||||
const exchangeInstance = new ExchangeContract(
|
||||
artifacts.Exchange.compilerOutput.abi,
|
||||
signedOrder.exchangeAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
|
||||
const orderWithoutExchangeAddress = _.omit(signedOrder, [
|
||||
'signature',
|
||||
'exchangeAddress',
|
||||
]) as OrderWithoutExchangeAddress;
|
||||
|
||||
const txHash = await exchangeInstance.fillOrder.sendTransactionAsync(
|
||||
orderWithoutExchangeAddress,
|
||||
partialFillAmount,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerFee: BigNumber,
|
||||
takerFee: BigNumber,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
feeRecepientAddress: string,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const decodedMakerAssetData = assetProxyUtils.decodeAssetDataOrThrow(makerAssetData);
|
||||
if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
await this._increaseERC20BalanceAndAllowanceAsync(
|
||||
decodedMakerAssetData.tokenAddress,
|
||||
makerAddress,
|
||||
makerFillableAmount,
|
||||
);
|
||||
} else {
|
||||
if (!makerFillableAmount.equals(1)) {
|
||||
throw new Error(`ERC721 makerFillableAmount should be equal 1. Found: ${makerFillableAmount}`);
|
||||
}
|
||||
await this._increaseERC721BalanceAndAllowanceAsync(
|
||||
decodedMakerAssetData.tokenAddress,
|
||||
makerAddress,
|
||||
(decodedMakerAssetData as ERC721AssetData).tokenId,
|
||||
);
|
||||
}
|
||||
const decodedTakerAssetData = assetProxyUtils.decodeAssetDataOrThrow(takerAssetData);
|
||||
if (decodedTakerAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
const takerTokenAddress = decodedTakerAssetData.tokenAddress;
|
||||
await this._increaseERC20BalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount);
|
||||
} else {
|
||||
if (!takerFillableAmount.equals(1)) {
|
||||
throw new Error(`ERC721 takerFillableAmount should be equal 1. Found: ${takerFillableAmount}`);
|
||||
}
|
||||
await this._increaseERC721BalanceAndAllowanceAsync(
|
||||
decodedTakerAssetData.tokenAddress,
|
||||
takerAddress,
|
||||
(decodedMakerAssetData as ERC721AssetData).tokenId,
|
||||
);
|
||||
}
|
||||
// Fees
|
||||
await Promise.all([
|
||||
this._increaseERC20BalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee),
|
||||
this._increaseERC20BalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
|
||||
]);
|
||||
const senderAddress = constants.NULL_ADDRESS;
|
||||
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||
this._web3Wrapper.getProvider(),
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
senderAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerFillableAmount,
|
||||
makerAssetData,
|
||||
takerFillableAmount,
|
||||
takerAssetData,
|
||||
this._exchangeAddress,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _increaseERC721BalanceAndAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
tokenId: BigNumber,
|
||||
): Promise<void> {
|
||||
await this._increaseERC721BalanceAsync(tokenAddress, address, tokenId);
|
||||
await this._increaseERC721AllowanceAsync(tokenAddress, address, tokenId);
|
||||
}
|
||||
private async _increaseERC721AllowanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
tokenId: BigNumber,
|
||||
): Promise<void> {
|
||||
const erc721Token = new DummyERC721TokenContract(
|
||||
artifacts.DummyERC721Token.compilerOutput.abi,
|
||||
tokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const txHash = await erc721Token.approve.sendTransactionAsync(this._erc721ProxyAddress, tokenId, {
|
||||
from: address,
|
||||
});
|
||||
await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
}
|
||||
private async _increaseERC721BalanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
tokenId: BigNumber,
|
||||
): Promise<void> {
|
||||
const erc721Token = new DummyERC721TokenContract(
|
||||
artifacts.DummyERC721Token.compilerOutput.abi,
|
||||
tokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
try {
|
||||
const currentOwner = await erc721Token.ownerOf.callAsync(tokenId);
|
||||
if (currentOwner !== address) {
|
||||
throw new Error(`Token ${tokenAddress}:${tokenId} is already owner by ${currentOwner}`);
|
||||
}
|
||||
} catch (err) {
|
||||
const txHash = await erc721Token.mint.sendTransactionAsync(address, tokenId, { from: this._coinbase });
|
||||
await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
}
|
||||
}
|
||||
private async _increaseERC20BalanceAndAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
amount: BigNumber,
|
||||
): Promise<void> {
|
||||
if (amount.isZero() || address === constants.NULL_ADDRESS) {
|
||||
return; // noop
|
||||
}
|
||||
await Promise.all([
|
||||
this._increaseERC20BalanceAsync(tokenAddress, address, amount),
|
||||
this._increaseERC20AllowanceAsync(tokenAddress, address, amount),
|
||||
]);
|
||||
}
|
||||
private async _increaseERC20BalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
const erc20Token = new DummyERC20TokenContract(
|
||||
artifacts.DummyERC20Token.compilerOutput.abi,
|
||||
tokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const txHash = await erc20Token.transfer.sendTransactionAsync(address, amount, {
|
||||
from: this._coinbase,
|
||||
});
|
||||
await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
}
|
||||
private async _increaseERC20AllowanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
amount: BigNumber,
|
||||
): Promise<void> {
|
||||
const erc20Token = new DummyERC20TokenContract(
|
||||
artifacts.DummyERC20Token.compilerOutput.abi,
|
||||
tokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const oldMakerAllowance = await erc20Token.allowance.callAsync(address, this._erc20ProxyAddress);
|
||||
const newMakerAllowance = oldMakerAllowance.plus(amount);
|
||||
|
||||
const txHash = await erc20Token.approve.sendTransactionAsync(this._erc20ProxyAddress, newMakerAllowance, {
|
||||
from: address,
|
||||
});
|
||||
await this._web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
|
||||
}
|
||||
}
|
||||
@@ -1,222 +1 @@
|
||||
import { assetProxyUtils, orderFactory } from '@0xproject/order-utils';
|
||||
import { OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import { Provider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { constants } from './constants';
|
||||
import { ERC20TokenContract } from './generated_contract_wrappers/erc20_token';
|
||||
import { ExchangeContract } from './generated_contract_wrappers/exchange';
|
||||
|
||||
export class FillScenarios {
|
||||
private readonly _web3Wrapper: Web3Wrapper;
|
||||
private readonly _userAddresses: string[];
|
||||
private readonly _coinbase: string;
|
||||
private readonly _zrxTokenAddress: string;
|
||||
private readonly _exchangeAddress: string;
|
||||
private readonly _erc20ProxyAddress: string;
|
||||
constructor(
|
||||
provider: Provider,
|
||||
userAddresses: string[],
|
||||
zrxTokenAddress: string,
|
||||
exchangeAddress: string,
|
||||
erc20ProxyAddress: string,
|
||||
) {
|
||||
this._web3Wrapper = new Web3Wrapper(provider);
|
||||
this._userAddresses = userAddresses;
|
||||
this._coinbase = userAddresses[0];
|
||||
this._zrxTokenAddress = zrxTokenAddress;
|
||||
this._exchangeAddress = exchangeAddress;
|
||||
this._erc20ProxyAddress = erc20ProxyAddress;
|
||||
}
|
||||
public async createFillableSignedOrderAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
public async createFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerFee: BigNumber,
|
||||
takerFee: BigNumber,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
feeRecepientAddress: string,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
public async createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const makerFee = new BigNumber(0);
|
||||
const takerFee = new BigNumber(0);
|
||||
const feeRecepientAddress = constants.NULL_ADDRESS;
|
||||
return this._createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
makerFillableAmount,
|
||||
takerFillableAmount,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
}
|
||||
public async createPartiallyFilledSignedOrderAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
takerAddress: string,
|
||||
fillableAmount: BigNumber,
|
||||
partialFillAmount: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const [makerAddress] = this._userAddresses;
|
||||
const signedOrder = await this.createAsymmetricFillableSignedOrderAsync(
|
||||
makerAssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
fillableAmount,
|
||||
);
|
||||
const exchangeInstance = new ExchangeContract(
|
||||
artifacts.Exchange.compilerOutput.abi,
|
||||
signedOrder.exchangeAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
|
||||
const orderWithoutExchangeAddress = _.omit(signedOrder, [
|
||||
'signature',
|
||||
'exchangeAddress',
|
||||
]) as OrderWithoutExchangeAddress;
|
||||
|
||||
await exchangeInstance.fillOrder.sendTransactionAsync(
|
||||
orderWithoutExchangeAddress,
|
||||
partialFillAmount,
|
||||
signedOrder.signature,
|
||||
{ from: takerAddress },
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _createAsymmetricFillableSignedOrderWithFeesAsync(
|
||||
makerAssetData: string,
|
||||
takerAssetData: string,
|
||||
makerFee: BigNumber,
|
||||
takerFee: BigNumber,
|
||||
makerAddress: string,
|
||||
takerAddress: string,
|
||||
makerFillableAmount: BigNumber,
|
||||
takerFillableAmount: BigNumber,
|
||||
feeRecepientAddress: string,
|
||||
expirationTimeSeconds?: BigNumber,
|
||||
): Promise<SignedOrder> {
|
||||
const makerERC20AssetData = assetProxyUtils.decodeERC20AssetData(makerAssetData);
|
||||
const makerTokenAddress = makerERC20AssetData.tokenAddress;
|
||||
const takerERC20AssetData = assetProxyUtils.decodeERC20AssetData(takerAssetData);
|
||||
const takerTokenAddress = takerERC20AssetData.tokenAddress;
|
||||
await Promise.all([
|
||||
this._increaseERC20BalanceAndAllowanceAsync(makerTokenAddress, makerAddress, makerFillableAmount),
|
||||
this._increaseERC20BalanceAndAllowanceAsync(takerTokenAddress, takerAddress, takerFillableAmount),
|
||||
]);
|
||||
await Promise.all([
|
||||
this._increaseERC20BalanceAndAllowanceAsync(this._zrxTokenAddress, makerAddress, makerFee),
|
||||
this._increaseERC20BalanceAndAllowanceAsync(this._zrxTokenAddress, takerAddress, takerFee),
|
||||
]);
|
||||
const senderAddress = constants.NULL_ADDRESS;
|
||||
|
||||
const signedOrder = await orderFactory.createSignedOrderAsync(
|
||||
this._web3Wrapper.getProvider(),
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
senderAddress,
|
||||
makerFee,
|
||||
takerFee,
|
||||
makerFillableAmount,
|
||||
makerAssetData,
|
||||
takerFillableAmount,
|
||||
takerAssetData,
|
||||
this._exchangeAddress,
|
||||
feeRecepientAddress,
|
||||
expirationTimeSeconds,
|
||||
);
|
||||
return signedOrder;
|
||||
}
|
||||
private async _increaseERC20BalanceAndAllowanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
amount: BigNumber,
|
||||
): Promise<void> {
|
||||
if (amount.isZero() || address === constants.NULL_ADDRESS) {
|
||||
return; // noop
|
||||
}
|
||||
await Promise.all([
|
||||
this._increaseERC20BalanceAsync(tokenAddress, address, amount),
|
||||
this._increaseERC20AllowanceAsync(tokenAddress, address, amount),
|
||||
]);
|
||||
}
|
||||
private async _increaseERC20BalanceAsync(tokenAddress: string, address: string, amount: BigNumber): Promise<void> {
|
||||
const token = new ERC20TokenContract(
|
||||
artifacts.ERC20Token.compilerOutput.abi,
|
||||
tokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
await token.transfer.sendTransactionAsync(address, amount, {
|
||||
from: this._coinbase,
|
||||
});
|
||||
}
|
||||
private async _increaseERC20AllowanceAsync(
|
||||
tokenAddress: string,
|
||||
address: string,
|
||||
amount: BigNumber,
|
||||
): Promise<void> {
|
||||
const tokenInstance = new ERC20TokenContract(
|
||||
artifacts.ERC20Token.compilerOutput.abi,
|
||||
tokenAddress,
|
||||
this._web3Wrapper.getProvider(),
|
||||
this._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
const oldMakerAllowance = await tokenInstance.allowance.callAsync(address, this._erc20ProxyAddress);
|
||||
const newMakerAllowance = oldMakerAllowance.plus(amount);
|
||||
|
||||
await tokenInstance.approve.sendTransactionAsync(this._erc20ProxyAddress, newMakerAllowance, {
|
||||
from: address,
|
||||
});
|
||||
}
|
||||
}
|
||||
export { FillScenarios } from './fill_scenarios';
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -134,7 +134,7 @@ export const assetProxyUtils = {
|
||||
const assetProxyId = assetProxyUtils.decodeAssetProxyId(encodedAssetProxyId);
|
||||
return assetProxyId;
|
||||
},
|
||||
decodeAssetData(assetData: string): ERC20AssetData | ERC721AssetData {
|
||||
decodeAssetDataOrThrow(assetData: string): ERC20AssetData | ERC721AssetData {
|
||||
const assetProxyId = assetProxyUtils.decodeAssetDataId(assetData);
|
||||
switch (assetProxyId) {
|
||||
case AssetProxyId.ERC20:
|
||||
|
||||
@@ -79,7 +79,7 @@ export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProx
|
||||
public deleteAllERC721ProxyAllowance(tokenAddress: string, userAddress: string): void {
|
||||
for (const assetData in this._proxyAllowance) {
|
||||
if (this._proxyAllowance.hasOwnProperty(assetData)) {
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetData(assetData);
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetDataOrThrow(assetData);
|
||||
if (
|
||||
decodedAssetData.assetProxyId === AssetProxyId.ERC721 &&
|
||||
decodedAssetData.tokenAddress === tokenAddress &&
|
||||
|
||||
@@ -14,7 +14,7 @@ export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndP
|
||||
this._stateLayer = stateLayer;
|
||||
}
|
||||
public async getBalanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetData(assetData);
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetDataOrThrow(assetData);
|
||||
if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
|
||||
const balance = await this._erc20Token.getBalanceAsync(decodedERC20AssetData.tokenAddress, userAddress, {
|
||||
@@ -35,7 +35,7 @@ export class AssetBalanceAndProxyAllowanceFetcher implements AbstractBalanceAndP
|
||||
}
|
||||
}
|
||||
public async getProxyAllowanceAsync(assetData: string, userAddress: string): Promise<BigNumber> {
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetData(assetData);
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetDataOrThrow(assetData);
|
||||
if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
const decodedERC20AssetData = decodedAssetData as ERC20AssetData;
|
||||
const proxyAllowance = await this._erc20Token.getProxyAllowanceAsync(
|
||||
|
||||
@@ -54,7 +54,7 @@ export class DependentOrderHashesTracker {
|
||||
return dependentOrderHashes;
|
||||
}
|
||||
public getDependentOrderHashesByAssetDataByMaker(makerAddress: string, assetData: string): string[] {
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetData(assetData);
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetDataOrThrow(assetData);
|
||||
const dependentOrderHashes =
|
||||
decodedAssetData.assetProxyId === AssetProxyId.ERC20
|
||||
? this._getDependentOrderHashesByERC20AssetData(makerAddress, assetData)
|
||||
@@ -62,7 +62,7 @@ export class DependentOrderHashesTracker {
|
||||
return dependentOrderHashes;
|
||||
}
|
||||
public addToDependentOrderHashes(signedOrder: SignedOrder): void {
|
||||
const decodedMakerAssetData = assetProxyUtils.decodeAssetData(signedOrder.makerAssetData);
|
||||
const decodedMakerAssetData = assetProxyUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData);
|
||||
if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
this._addToERC20DependentOrderHashes(signedOrder, (decodedMakerAssetData as ERC20AssetData).tokenAddress);
|
||||
} else {
|
||||
@@ -76,7 +76,7 @@ export class DependentOrderHashesTracker {
|
||||
this._addToMakerDependentOrderHashes(signedOrder);
|
||||
}
|
||||
public removeFromDependentOrderHashes(signedOrder: SignedOrder): void {
|
||||
const decodedMakerAssetData = assetProxyUtils.decodeAssetData(signedOrder.makerAssetData);
|
||||
const decodedMakerAssetData = assetProxyUtils.decodeAssetDataOrThrow(signedOrder.makerAssetData);
|
||||
if (decodedMakerAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
this._removeFromERC20DependentOrderhashes(
|
||||
signedOrder,
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
orderHashUtils,
|
||||
OrderStateUtils,
|
||||
} from '@0xproject/order-utils';
|
||||
import { ExchangeContractErrs, OrderState, SignedOrder } from '@0xproject/types';
|
||||
import { AssetProxyId, ExchangeContractErrs, OrderState, SignedOrder } from '@0xproject/types';
|
||||
import { errorUtils, intervalUtils } from '@0xproject/utils';
|
||||
import { BlockParamLiteral, LogEntryEvent, LogWithDecodedArgs, Provider } from 'ethereum-types';
|
||||
import * as _ from 'lodash';
|
||||
@@ -134,16 +134,26 @@ export class OrderWatcher {
|
||||
* signature is verified.
|
||||
* @param signedOrder The order you wish to start watching.
|
||||
*/
|
||||
public addOrder(signedOrder: SignedOrder): void {
|
||||
public async addOrderAsync(signedOrder: SignedOrder): Promise<void> {
|
||||
assert.doesConformToSchema('signedOrder', signedOrder, schemas.signedOrderSchema);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
assert.isValidSignatureAsync(this._provider, orderHash, signedOrder.signature, signedOrder.makerAddress);
|
||||
await assert.isValidSignatureAsync(this._provider, orderHash, signedOrder.signature, signedOrder.makerAddress);
|
||||
|
||||
const expirationUnixTimestampMs = signedOrder.expirationTimeSeconds.times(MILLISECONDS_IN_A_SECOND);
|
||||
this._expirationWatcher.addOrder(orderHash, expirationUnixTimestampMs);
|
||||
|
||||
this._orderByOrderHash[orderHash] = signedOrder;
|
||||
this._dependentOrderHashesTracker.addToDependentOrderHashes(signedOrder);
|
||||
|
||||
const orderAssetDatas = [signedOrder.makerAssetData, signedOrder.takerAssetData];
|
||||
_.each(orderAssetDatas, assetData => {
|
||||
const decodedAssetData = assetProxyUtils.decodeAssetDataOrThrow(assetData);
|
||||
if (decodedAssetData.assetProxyId === AssetProxyId.ERC20) {
|
||||
this._collisionResistantAbiDecoder.addERC20Token(decodedAssetData.tokenAddress);
|
||||
} else if (decodedAssetData.assetProxyId === AssetProxyId.ERC721) {
|
||||
this._collisionResistantAbiDecoder.addERC721Token(decodedAssetData.tokenAddress);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Removes an order from the orderWatcher
|
||||
|
||||
@@ -43,7 +43,6 @@ describe('ExpirationWatcher', () => {
|
||||
let expirationWatcher: ExpirationWatcher;
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
const erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
|
||||
fillScenarios = new FillScenarios(
|
||||
@@ -51,7 +50,8 @@ describe('ExpirationWatcher', () => {
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
erc20ProxyAddress,
|
||||
contractWrappers.erc20Proxy.getContractAddress(),
|
||||
contractWrappers.erc721Proxy.getContractAddress(),
|
||||
);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
const [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
|
||||
@@ -57,7 +57,6 @@ describe('OrderWatcher', () => {
|
||||
const fillableAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(5), decimals);
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
const erc20ProxyAddress = contractWrappers.erc20Proxy.getContractAddress();
|
||||
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
|
||||
zrxTokenAddress = tokenUtils.getProtocolTokenAddress();
|
||||
exchangeContractAddress = contractWrappers.exchange.getContractAddress();
|
||||
@@ -66,7 +65,8 @@ describe('OrderWatcher', () => {
|
||||
userAddresses,
|
||||
zrxTokenAddress,
|
||||
exchangeContractAddress,
|
||||
erc20ProxyAddress,
|
||||
contractWrappers.erc20Proxy.getContractAddress(),
|
||||
contractWrappers.erc721Proxy.getContractAddress(),
|
||||
);
|
||||
[coinbase, makerAddress, takerAddress, feeRecipient] = userAddresses;
|
||||
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
|
||||
@@ -74,7 +74,7 @@ describe('OrderWatcher', () => {
|
||||
assetProxyUtils.encodeERC20AssetData(makerTokenAddress),
|
||||
assetProxyUtils.encodeERC20AssetData(takerTokenAddress),
|
||||
];
|
||||
const orderWatcherConfig = { stateLayer: BlockParamLiteral.Latest };
|
||||
const orderWatcherConfig = {};
|
||||
orderWatcher = new OrderWatcher(provider, networkId, orderWatcherConfig);
|
||||
});
|
||||
after(async () => {
|
||||
@@ -96,7 +96,7 @@ describe('OrderWatcher', () => {
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
expect((orderWatcher as any)._orderByOrderHash).to.include({
|
||||
[orderHash]: signedOrder,
|
||||
});
|
||||
@@ -156,7 +156,7 @@ describe('OrderWatcher', () => {
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
@@ -180,7 +180,7 @@ describe('OrderWatcher', () => {
|
||||
takerAddress,
|
||||
fillableAmount,
|
||||
);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((_orderState: OrderState) => {
|
||||
throw new Error('OrderState callback fired for irrelevant order');
|
||||
});
|
||||
@@ -209,7 +209,7 @@ describe('OrderWatcher', () => {
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
@@ -237,7 +237,7 @@ describe('OrderWatcher', () => {
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
@@ -263,7 +263,7 @@ describe('OrderWatcher', () => {
|
||||
const makerBalance = await contractWrappers.erc20Token.getBalanceAsync(makerTokenAddress, makerAddress);
|
||||
const fillAmountInBaseUnits = new BigNumber(2);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
@@ -299,7 +299,7 @@ describe('OrderWatcher', () => {
|
||||
takerAddress,
|
||||
);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)();
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
orderWatcher.subscribe(callback);
|
||||
await contractWrappers.erc20Token.setProxyAllowanceAsync(
|
||||
zrxTokenAddress,
|
||||
@@ -323,7 +323,7 @@ describe('OrderWatcher', () => {
|
||||
);
|
||||
const fillAmountInBaseUnits = Web3Wrapper.toBaseUnitAmount(new BigNumber(2), decimals);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
@@ -351,7 +351,7 @@ describe('OrderWatcher', () => {
|
||||
);
|
||||
|
||||
const changedMakerApprovalAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(3), decimals);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
@@ -388,7 +388,7 @@ describe('OrderWatcher', () => {
|
||||
|
||||
const remainingAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), decimals);
|
||||
const transferAmount = makerBalance.sub(remainingAmount);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.true();
|
||||
@@ -429,7 +429,7 @@ describe('OrderWatcher', () => {
|
||||
|
||||
const remainingTokenAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(4), decimals);
|
||||
const transferTokenAmount = makerFee.sub(remainingTokenAmount);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
@@ -467,7 +467,7 @@ describe('OrderWatcher', () => {
|
||||
feeRecipient,
|
||||
);
|
||||
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
const validOrderState = orderState as OrderStateValid;
|
||||
@@ -495,7 +495,7 @@ describe('OrderWatcher', () => {
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
@@ -518,7 +518,7 @@ describe('OrderWatcher', () => {
|
||||
fillableAmount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
orderWatcher.addOrder(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
@@ -534,5 +534,101 @@ describe('OrderWatcher', () => {
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
describe('erc721', () => {
|
||||
let makerErc721AssetData: string;
|
||||
let makerErc721TokenAddress: string;
|
||||
const tokenId = new BigNumber(42);
|
||||
[makerErc721TokenAddress] = tokenUtils.getDummyERC721TokenAddresses();
|
||||
makerErc721AssetData = assetProxyUtils.encodeERC721AssetData(makerErc721TokenAddress, tokenId);
|
||||
const fillableErc721Amount = new BigNumber(1);
|
||||
it('should emit orderStateInvalid when maker allowance set to 0 for watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerErc721AssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableErc721Amount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
|
||||
});
|
||||
orderWatcher.subscribe(callback);
|
||||
await contractWrappers.erc721Token.setApprovalAsync(
|
||||
makerErc721TokenAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
tokenId,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateInvalid when maker allowance for all set to 0 for watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerErc721AssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableErc721Amount,
|
||||
);
|
||||
await contractWrappers.erc721Token.setApprovalAsync(
|
||||
makerErc721TokenAddress,
|
||||
constants.NULL_ADDRESS,
|
||||
tokenId,
|
||||
);
|
||||
let isApproved = true;
|
||||
await contractWrappers.erc721Token.setProxyApprovalForAllAsync(
|
||||
makerErc721TokenAddress,
|
||||
makerAddress,
|
||||
isApproved,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerAllowance);
|
||||
});
|
||||
orderWatcher.subscribe(callback);
|
||||
isApproved = false;
|
||||
await contractWrappers.erc721Token.setProxyApprovalForAllAsync(
|
||||
makerErc721TokenAddress,
|
||||
makerAddress,
|
||||
isApproved,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
it('should emit orderStateInvalid when maker moves NFT backing watched order', (done: DoneCallback) => {
|
||||
(async () => {
|
||||
signedOrder = await fillScenarios.createFillableSignedOrderAsync(
|
||||
makerErc721AssetData,
|
||||
takerAssetData,
|
||||
makerAddress,
|
||||
takerAddress,
|
||||
fillableErc721Amount,
|
||||
);
|
||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
await orderWatcher.addOrderAsync(signedOrder);
|
||||
const callback = callbackErrorReporter.reportNodeCallbackErrors(done)((orderState: OrderState) => {
|
||||
expect(orderState.isValid).to.be.false();
|
||||
const invalidOrderState = orderState as OrderStateInvalid;
|
||||
expect(invalidOrderState.orderHash).to.be.equal(orderHash);
|
||||
expect(invalidOrderState.error).to.be.equal(ExchangeContractErrs.InsufficientMakerBalance);
|
||||
});
|
||||
orderWatcher.subscribe(callback);
|
||||
await contractWrappers.erc721Token.transferFromAsync(
|
||||
makerErc721TokenAddress,
|
||||
coinbase,
|
||||
makerAddress,
|
||||
tokenId,
|
||||
);
|
||||
})().catch(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
}); // tslint:disable:max-file-line-count
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"downlevelIteration": true
|
||||
"outDir": "lib"
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*"]
|
||||
}
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
{
|
||||
"extends": [
|
||||
"tslint:latest",
|
||||
"tslint-react",
|
||||
"tslint-eslint-rules"
|
||||
],
|
||||
"extends": ["tslint:latest", "tslint-react", "tslint-eslint-rules"],
|
||||
"rules": {
|
||||
"adjacent-overload-signatures": true,
|
||||
"arrow-parens": [
|
||||
true,
|
||||
"ban-single-arg-parens"
|
||||
],
|
||||
"arrow-parens": [true, "ban-single-arg-parens"],
|
||||
"arrow-return-shorthand": true,
|
||||
"async-suffix": true,
|
||||
"await-promise": true,
|
||||
@@ -21,70 +14,37 @@
|
||||
true,
|
||||
{
|
||||
"functions": {
|
||||
"visibilities": [
|
||||
"exported"
|
||||
]
|
||||
"visibilities": ["exported"]
|
||||
},
|
||||
"methods": {
|
||||
"locations": "instance",
|
||||
"privacies": [
|
||||
"public",
|
||||
"protected"
|
||||
]
|
||||
"privacies": ["public", "protected"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"curly": true,
|
||||
"custom-no-magic-numbers": [
|
||||
true,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
-1
|
||||
],
|
||||
"custom-no-magic-numbers": [true, 0, 1, 2, 3, -1],
|
||||
"encoding": true,
|
||||
"eofline": true,
|
||||
"import-spacing": true,
|
||||
"indent": [
|
||||
true,
|
||||
"spaces",
|
||||
4
|
||||
],
|
||||
"indent": [true, "spaces", 4],
|
||||
"interface-name": false,
|
||||
"interface-over-type-literal": true,
|
||||
"jsx-alignment": true,
|
||||
"jsx-boolean-value": true,
|
||||
"jsx-curly-spacing": [
|
||||
true,
|
||||
"never"
|
||||
],
|
||||
"jsx-curly-spacing": [true, "never"],
|
||||
"jsx-no-bind": false,
|
||||
"jsx-no-lambda": true,
|
||||
"jsx-no-multiline-js": false,
|
||||
"jsx-no-string-ref": true,
|
||||
"jsx-self-close": true,
|
||||
"jsx-wrap-multiline": false,
|
||||
"linebreak-style": [
|
||||
true,
|
||||
"LF"
|
||||
],
|
||||
"max-classes-per-file": [
|
||||
true,
|
||||
1
|
||||
],
|
||||
"max-file-line-count": [
|
||||
true,
|
||||
500
|
||||
],
|
||||
"linebreak-style": [true, "LF"],
|
||||
"max-classes-per-file": [true, 1],
|
||||
"max-file-line-count": [true, 500],
|
||||
"max-line-length": false,
|
||||
"member-access": true,
|
||||
"member-ordering": [
|
||||
true,
|
||||
"public-before-private",
|
||||
"static-before-instance",
|
||||
"variables-before-functions"
|
||||
],
|
||||
"member-ordering": [true, "public-before-private", "static-before-instance", "variables-before-functions"],
|
||||
"new-parens": true,
|
||||
"newline-before-return": false,
|
||||
"no-angle-bracket-type-assertion": true,
|
||||
@@ -97,10 +57,7 @@
|
||||
"no-empty-interface": false,
|
||||
"no-eval": true,
|
||||
"no-floating-promises": true,
|
||||
"no-implicit-dependencies": [
|
||||
true,
|
||||
"dev"
|
||||
],
|
||||
"no-implicit-dependencies": [true, "dev"],
|
||||
"no-inferred-empty-object-type": true,
|
||||
"no-invalid-template-strings": true,
|
||||
"no-invalid-this": true,
|
||||
@@ -120,10 +77,7 @@
|
||||
"no-unnecessary-class": true,
|
||||
"no-unnecessary-type-assertion": true,
|
||||
"no-unsafe-finally": true,
|
||||
"no-unused-variable": [
|
||||
true,
|
||||
"check-parameters"
|
||||
],
|
||||
"no-unused-variable": [true, "check-parameters"],
|
||||
"number-literal-format": true,
|
||||
"object-literal-key-quotes": false,
|
||||
"object-literal-sort-keys": false,
|
||||
@@ -139,17 +93,9 @@
|
||||
"prefer-object-spread": true,
|
||||
"prefer-readonly": true,
|
||||
"promise-function-async": true,
|
||||
"quotemark": [
|
||||
true,
|
||||
"single",
|
||||
"avoid-escape",
|
||||
"jsx-double"
|
||||
],
|
||||
"quotemark": [true, "single", "avoid-escape", "jsx-double"],
|
||||
"restrict-plus-operands": true,
|
||||
"semicolon": [
|
||||
true,
|
||||
"always"
|
||||
],
|
||||
"semicolon": [true, "always"],
|
||||
"space-before-function-paren": [
|
||||
true,
|
||||
{
|
||||
@@ -163,18 +109,9 @@
|
||||
"space-within-parens": false,
|
||||
"switch-default": true,
|
||||
"type-literal-delimiter": true,
|
||||
"typedef": [
|
||||
true,
|
||||
"call-signature",
|
||||
"parameter",
|
||||
"property-declaration"
|
||||
],
|
||||
"typedef": [true, "call-signature", "parameter", "property-declaration"],
|
||||
"underscore-private-and-protected": true,
|
||||
"variable-name": [
|
||||
true,
|
||||
"ban-keywords",
|
||||
"allow-pascal-case"
|
||||
],
|
||||
"variable-name": [true, "ban-keywords", "allow-pascal-case"],
|
||||
"whitespace": [
|
||||
true,
|
||||
"check-branch",
|
||||
@@ -188,4 +125,4 @@
|
||||
]
|
||||
},
|
||||
"rulesDirectory": "lib/rules"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"downlevelIteration": true,
|
||||
"noImplicitReturns": true,
|
||||
"pretty": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
21
yarn.lock
21
yarn.lock
@@ -76,19 +76,6 @@
|
||||
ethers "3.0.22"
|
||||
lodash "4.17.10"
|
||||
|
||||
"@0xproject/fill-scenarios@^0.0.5":
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@0xproject/fill-scenarios/-/fill-scenarios-0.0.5.tgz#a62a240ae40423b9b73ecc0b1fc2abb58b76621c"
|
||||
dependencies:
|
||||
"@0xproject/base-contract" "^0.3.5"
|
||||
"@0xproject/order-utils" "^0.0.8"
|
||||
"@0xproject/types" "^0.8.2"
|
||||
"@0xproject/typescript-typings" "^0.4.2"
|
||||
"@0xproject/utils" "^0.7.2"
|
||||
"@0xproject/web3-wrapper" "^0.7.2"
|
||||
ethers "3.0.22"
|
||||
lodash "4.17.10"
|
||||
|
||||
"@0xproject/json-schemas@0.8.2", "@0xproject/json-schemas@^0.8.2":
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@0xproject/json-schemas/-/json-schemas-0.8.2.tgz#9d3f446e546ce0c959cf7beb45d41ac60476a78c"
|
||||
@@ -8187,7 +8174,7 @@ mz@^2.6.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nan@>=2.5.1, nan@^2.0.5, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3, nan@^2.6.2:
|
||||
nan@2.10.0, nan@>=2.5.1, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3, nan@^2.6.2:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
|
||||
|
||||
@@ -10933,10 +10920,10 @@ sha.js@^2.4.0, sha.js@^2.4.8:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
sha3@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.0.tgz#6989f1b70a498705876a373e2c62ace96aa9399a"
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9"
|
||||
dependencies:
|
||||
nan "^2.0.5"
|
||||
nan "2.10.0"
|
||||
|
||||
shallowequal@^1.0.1:
|
||||
version "1.0.2"
|
||||
|
||||
Reference in New Issue
Block a user