Add new runMigrationsOnce method to migrations. Update contract-wrappers to use it.

This commit is contained in:
Alex Browne 2018-10-09 13:52:40 -07:00
parent ecdd6e3303
commit a48e0a08bf
15 changed files with 94 additions and 105 deletions

View File

@ -1,10 +1,10 @@
import { getContractAddresses } from '@0xproject/migrations';
import * as chai from 'chai';
import { ContractWrappers } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { provider } from './utils/web3_wrapper';
chaiSetup.configure();
@ -13,9 +13,10 @@ const expect = chai.expect;
describe('ERC20ProxyWrapper', () => {
let contractWrappers: ContractWrappers;
before(async () => {
const contractAddresses = await migrateOnceAsync();
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);

View File

@ -1,7 +1,6 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { getContractAddresses } from '@0xproject/migrations';
import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
import { DoneCallback } from '@0xproject/types';
import { ContractAddresses, DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import { Provider } from 'ethereum-types';
@ -21,6 +20,7 @@ import {
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -30,6 +30,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('ERC20Wrapper', () => {
let contractWrappers: ContractWrappers;
let contractAddresses: ContractAddresses;
let userAddresses: string[];
let tokens: string[];
let coinbase: string;
@ -37,9 +38,10 @@ describe('ERC20Wrapper', () => {
let config: ContractWrappersConfig;
before(async () => {
contractAddresses = await migrateOnceAsync();
config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
@ -299,7 +301,7 @@ describe('ERC20Wrapper', () => {
});
it('should reduce the gas cost for transfers including tokens with unlimited allowance support', async () => {
const transferAmount = new BigNumber(5);
const zrxAddress = getContractAddresses().zrxToken;
const zrxAddress = contractAddresses.zrxToken;
const [, userWithNormalAllowance, userWithUnlimitedAllowance] = userAddresses;
await contractWrappers.erc20Token.setAllowanceAsync(
zrxAddress,

View File

@ -1,10 +1,10 @@
import { getContractAddresses } from '@0xproject/migrations';
import * as chai from 'chai';
import { ContractWrappers } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { provider } from './utils/web3_wrapper';
chaiSetup.configure();
@ -13,9 +13,10 @@ const expect = chai.expect;
describe('ERC721ProxyWrapper', () => {
let contractWrappers: ContractWrappers;
before(async () => {
const contractAddresses = await migrateOnceAsync();
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);

View File

@ -1,5 +1,4 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { getContractAddresses } from '@0xproject/migrations';
import { EmptyWalletSubprovider, Web3ProviderEngine } from '@0xproject/subproviders';
import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
@ -22,6 +21,7 @@ import {
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -42,9 +42,10 @@ describe('ERC721Wrapper', () => {
let config: ContractWrappersConfig;
before(async () => {
const contractAddresses = await migrateOnceAsync();
config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);

View File

@ -1,6 +1,5 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { getContractAddresses } from '@0xproject/migrations';
import { DoneCallback } from '@0xproject/types';
import { ContractAddresses, DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@ -22,6 +21,7 @@ import { DecodedLogEvent } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { provider, web3Wrapper } from './utils/web3_wrapper';
chaiSetup.configure();
@ -36,6 +36,7 @@ const MAX_REASONABLE_GAS_COST_IN_WEI = 62517;
describe('EtherTokenWrapper', () => {
let contractWrappers: ContractWrappers;
let contractAddresses: ContractAddresses;
let userAddresses: string[];
let addressWithETH: string;
let wethContractAddress: string;
@ -48,16 +49,17 @@ describe('EtherTokenWrapper', () => {
const depositAmount = new BigNumber(42);
const withdrawalAmount = new BigNumber(42);
before(async () => {
contractAddresses = await migrateOnceAsync();
const config = {
gasPrice,
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
userAddresses = await web3Wrapper.getAvailableAddressesAsync();
addressWithETH = userAddresses[0];
wethContractAddress = getContractAddresses().etherToken;
wethContractAddress = contractAddresses.etherToken;
depositWeiAmount = Web3Wrapper.toWei(new BigNumber(5));
addressWithoutFunds = userAddresses[1];
});
@ -69,7 +71,7 @@ describe('EtherTokenWrapper', () => {
});
describe('#getContractAddressIfExists', async () => {
it('should return contract address if connected to a known network', () => {
const contractAddressIfExists = getContractAddresses().etherToken;
const contractAddressIfExists = contractAddresses.etherToken;
expect(contractAddressIfExists).to.not.be.undefined();
});
it('should throw if connected to a private network and contract addresses are not specified', () => {
@ -174,7 +176,7 @@ describe('EtherTokenWrapper', () => {
const indexFilterValues = {};
let etherTokenAddress: string;
before(async () => {
etherTokenAddress = getContractAddresses().etherToken;
etherTokenAddress = contractAddresses.etherToken;
});
afterEach(() => {
contractWrappers.etherToken.unsubscribeAll();
@ -343,7 +345,7 @@ describe('EtherTokenWrapper', () => {
let txHash: string;
before(async () => {
addressWithETH = userAddresses[0];
etherTokenAddress = getContractAddresses().etherToken;
etherTokenAddress = contractAddresses.etherToken;
erc20ProxyAddress = contractWrappers.erc20Proxy.address;
// Start the block range after all migrations to avoid unexpected logs
const currentBlock: number = await web3Wrapper.getBlockNumberAsync();

View File

@ -1,6 +1,5 @@
import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { getContractAddresses } from '@0xproject/migrations';
import { assetDataUtils, orderHashUtils } from '@0xproject/order-utils';
import { DoneCallback, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
@ -13,6 +12,7 @@ import { DecodedLogEvent } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -42,10 +42,11 @@ describe('ExchangeWrapper', () => {
let anotherSignedOrder: SignedOrder;
before(async () => {
const contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
@ -359,9 +360,7 @@ describe('ExchangeWrapper', () => {
});
});
describe('#getVersionAsync', () => {
// TODO(albrow): getVersionAsync is returning 2.0.1-alpha. How can we
// resolve this?
it.skip('should return version the hash', async () => {
it('should return version the hash', async () => {
const version = await contractWrappers.exchange.getVersionAsync();
const VERSION = '2.0.0';
expect(version).to.be.equal(VERSION);

View File

@ -1,6 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { getContractAddresses } from '@0xproject/migrations';
import { assetDataUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
@ -11,6 +10,7 @@ import { ContractWrappers, OrderStatus } from '../src';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -26,11 +26,8 @@ describe('ForwarderWrapper', () => {
let exchangeContractAddress: string;
let zrxTokenAddress: string;
let userAddresses: string[];
let coinbase: string;
let makerAddress: string;
let takerAddress: string;
let feeRecipient: string;
let anotherMakerAddress: string;
let makerTokenAddress: string;
let takerTokenAddress: string;
let makerAssetData: string;
@ -38,10 +35,11 @@ describe('ForwarderWrapper', () => {
let signedOrder: SignedOrder;
let anotherSignedOrder: SignedOrder;
before(async () => {
const contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
@ -56,7 +54,7 @@ describe('ForwarderWrapper', () => {
contractWrappers.erc20Proxy.address,
contractWrappers.erc721Proxy.address,
);
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
[, makerAddress, takerAddress ] = userAddresses;
[makerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
takerTokenAddress = contractWrappers.forwarder.etherTokenAddress;
[makerAssetData, takerAssetData] = [

View File

@ -1,16 +1,6 @@
import { devConstants } from '@0xproject/dev-utils';
import { runMigrationsAsync } from '@0xproject/migrations';
import { provider } from './utils/web3_wrapper';
before('migrate contracts', async function(): Promise<void> {
before('set up mocha', async function(): Promise<void> {
// HACK: Since the migrations take longer then our global mocha timeout limit
// we manually increase it for this before hook.
const mochaTestTimeoutMs = 50000;
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
await runMigrationsAsync(provider, txDefaults);
});

View File

@ -1,6 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { getContractAddresses } from '@0xproject/migrations';
import { assetDataUtils } from '@0xproject/order-utils';
import { ContractAddresses, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
@ -13,6 +12,7 @@ import { OrderInfo, TraderInfo } from '../src/types';
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -42,8 +42,8 @@ describe('OrderValidator', () => {
let contractAddresses: ContractAddresses;
before(async () => {
contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
contractAddresses = getContractAddresses();
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses,

View File

@ -1,6 +1,6 @@
import { BlockchainLifecycle, web3Factory } from '@0xproject/dev-utils';
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { getContractAddresses } from '@0xproject/migrations';
import { runMigrationsAsync } from '@0xproject/migrations';
import { assetDataUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
@ -17,8 +17,7 @@ import { tokenUtils } from './utils/token_utils';
chaiSetup.configure();
const expect = chai.expect;
// TODO(albrow): Re-enable these tests after @0xproject/fill-scenarios is updated.
describe.skip('Revert Validation ExchangeWrapper', () => {
describe('Revert Validation ExchangeWrapper', () => {
let contractWrappers: ContractWrappers;
let userAddresses: string[];
let zrxTokenAddress: string;
@ -26,13 +25,10 @@ describe.skip('Revert Validation ExchangeWrapper', () => {
let exchangeContractAddress: string;
let makerTokenAddress: string;
let takerTokenAddress: string;
let coinbase: string;
let makerAddress: string;
let anotherMakerAddress: string;
let takerAddress: string;
let makerAssetData: string;
let takerAssetData: string;
let feeRecipient: string;
let txHash: string;
let blockchainLifecycle: BlockchainLifecycle;
let web3Wrapper: Web3Wrapper;
@ -52,10 +48,15 @@ describe.skip('Revert Validation ExchangeWrapper', () => {
// Re-deploy the artifacts in this provider, rather than in the default provider exposed in
// the beforeAll hook. This is due to the fact that the default provider enabled vmErrorsOnRPCResponse
// and we are explicity testing with vmErrorsOnRPCResponse disabled.
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
await blockchainLifecycle.startAsync();
const contractAddresses = await runMigrationsAsync(provider, txDefaults);
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
@ -70,7 +71,7 @@ describe.skip('Revert Validation ExchangeWrapper', () => {
contractWrappers.erc20Proxy.address,
contractWrappers.erc721Proxy.address,
);
[coinbase, makerAddress, takerAddress, feeRecipient, anotherMakerAddress] = userAddresses;
[, makerAddress, takerAddress] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
[makerAssetData, takerAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress),
@ -108,7 +109,7 @@ describe.skip('Revert Validation ExchangeWrapper', () => {
makerTokenBalance,
);
await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
expect(
await expect(
contractWrappers.exchange.fillOrderAsync(signedOrder, takerTokenFillAmount, takerAddress, {
shouldValidate: true,
}),

View File

@ -1,5 +1,4 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { getContractAddresses } from '@0xproject/migrations';
import { DoneCallback } from '@0xproject/types';
import * as _ from 'lodash';
import 'mocha';
@ -15,6 +14,7 @@ import {
import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -26,9 +26,10 @@ describe('SubscriptionTest', () => {
let config: ContractWrappersConfig;
before(async () => {
const contractAddresses = await migrateOnceAsync();
config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
};
contractWrappers = new ContractWrappers(provider, config);
});

View File

@ -1,6 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios';
import { getContractAddresses } from '@0xproject/migrations';
import { assetDataUtils, generatePseudoRandomSalt, orderHashUtils, signatureUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
@ -10,6 +9,7 @@ import { ContractWrappers } from '../src';
import { TransactionEncoder } from '../src/utils/transaction_encoder';
import { constants } from './utils/constants';
import { migrateOnceAsync } from './utils/migrate';
import { tokenUtils } from './utils/token_utils';
import { provider, web3Wrapper } from './utils/web3_wrapper';
@ -34,10 +34,11 @@ describe('TransactionEncoder', () => {
let signedOrder: SignedOrder;
before(async () => {
const contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
const config = {
networkId: constants.TESTRPC_NETWORK_ID,
contractAddresses: getContractAddresses(),
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);

View File

@ -0,0 +1,13 @@
import { devConstants } from '@0xproject/dev-utils';
import { runMigrationsOnceAsync } from '@0xproject/migrations';
import { ContractAddresses } from '@0xproject/types';
import { provider } from './web3_wrapper';
export async function migrateOnceAsync(): Promise<ContractAddresses> {
const txDefaults = {
gas: devConstants.GAS_LIMIT,
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
return runMigrationsOnceAsync(provider, txDefaults);
}

View File

@ -1 +1 @@
export { runMigrationsAsync, getContractAddresses } from './migration';
export { runMigrationsAsync, runMigrationsOnceAsync } from './migration';

View File

@ -9,28 +9,15 @@ import * as _ from 'lodash';
import { erc20TokenInfo, erc721TokenInfo } from './utils/token_info';
interface MigrationsResult {
erc20Proxy: wrappers.ERC20ProxyContract;
erc721Proxy: wrappers.ERC721ProxyContract;
zrxToken: wrappers.ZRXTokenContract;
etherToken: wrappers.WETH9Contract;
exchange: wrappers.ExchangeContract;
assetProxyOwner: wrappers.AssetProxyOwnerContract;
forwarder: wrappers.ForwarderContract;
orderValidator: wrappers.OrderValidatorContract;
}
let _cachedMigrationsResult: MigrationsResult | undefined;
let _cachedContractAddresses: ContractAddresses | undefined;
/**
* Custom migrations should be defined in this function. This will be called with the CLI 'migrate:v2' command.
* Migrations could be written to run in parallel, but if you want contract addresses to be created deterministically,
* the migration should be written to run synchronously.
* Creates and deploys all the contracts that are required for the latest
* version of the 0x protocol. Custom migrations can be defined here. This will
* be called with the CLI 'migrate:v2' command.
* @param provider Web3 provider instance.
* @param txDefaults Default transaction values to use when deploying contracts.
* @returns The addresses of the contracts that were deployed.
*/
export async function runMigrationsAsync(provider: Provider, txDefaults: Partial<TxData>): Promise<void> {
export async function runMigrationsAsync(provider: Provider, txDefaults: Partial<TxData>): Promise<ContractAddresses> {
const web3Wrapper = new Web3Wrapper(provider);
// Proxies
@ -154,43 +141,35 @@ export async function runMigrationsAsync(provider: Provider, txDefaults: Partial
zrxAssetData,
);
const migrationsResult = {
erc20Proxy,
erc721Proxy,
zrxToken,
etherToken,
exchange,
assetProxyOwner,
forwarder,
orderValidator,
return {
erc20Proxy: erc20Proxy.address,
erc721Proxy: erc721Proxy.address,
zrxToken: zrxToken.address,
etherToken: etherToken.address,
exchange: exchange.address,
assetProxyOwner: assetProxyOwner.address,
forwarder: forwarder.address,
orderValidator: orderValidator.address,
};
_cachedMigrationsResult = migrationsResult;
}
let _cachedContractAddresses: ContractAddresses;
/**
* Returns the addresses of all contracts that were deployed during migrations.
* Throws if migrations have not been run yet.
* @returns Addresses of all contracts that were deployed.
* Exactly like runMigrationsAsync but will only run the migrations the first
* time it is called. Any subsequent calls will return the cached contract
* addresses.
* @param provider Web3 provider instance.
* @param txDefaults Default transaction values to use when deploying contracts.
* @returns The addresses of the contracts that were deployed.
*/
export function getContractAddresses(): ContractAddresses {
export async function runMigrationsOnceAsync(
provider: Provider,
txDefaults: Partial<TxData>,
): Promise<ContractAddresses> {
if (!_.isUndefined(_cachedContractAddresses)) {
return _cachedContractAddresses;
}
if (_.isUndefined(_cachedMigrationsResult)) {
throw new Error(
'Migrations have not been run! You need to call runMigrationsAsync before getContractAddresses',
);
}
const contractAddresses = {
erc20Proxy: _cachedMigrationsResult.erc20Proxy.address,
erc721Proxy: _cachedMigrationsResult.erc721Proxy.address,
zrxToken: _cachedMigrationsResult.zrxToken.address,
etherToken: _cachedMigrationsResult.etherToken.address,
exchange: _cachedMigrationsResult.exchange.address,
assetProxyOwner: _cachedMigrationsResult.assetProxyOwner.address,
forwarder: _cachedMigrationsResult.forwarder.address,
orderValidator: _cachedMigrationsResult.orderValidator.address,
};
_cachedContractAddresses = contractAddresses;
return contractAddresses;
_cachedContractAddresses = await runMigrationsAsync(provider, txDefaults);
return _cachedContractAddresses;
}