Allow generated wrappers to subscribe/unsubscribe to events (#1970)

* Define SubscriptionManager and instantiate in generated wrappers

* expose subscribe/unsubscribe in generated wrappers

* update changelogs

* use SubscriptionManager in `@0x/contract-wrappers`
This commit is contained in:
Xianny 2019-07-26 16:54:31 -07:00 committed by GitHub
parent 5aeb626045
commit 46384ce80d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1865 additions and 612 deletions

View File

@ -23,7 +23,7 @@ import { LogWithDecodedArgs } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { ERC1155ProxyWrapper, ERC721ProxyContract } from '../src'; import { ERC1155ProxyContract, ERC1155ProxyWrapper } from '../src';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
@ -51,7 +51,7 @@ describe('ERC1155Proxy', () => {
let receiver: string; let receiver: string;
let receiverContract: string; let receiverContract: string;
// contracts & wrappers // contracts & wrappers
let erc1155Proxy: ERC721ProxyContract; let erc1155Proxy: ERC1155ProxyContract;
let erc1155Receiver: DummyERC1155ReceiverContract; let erc1155Receiver: DummyERC1155ReceiverContract;
let erc1155ProxyWrapper: ERC1155ProxyWrapper; let erc1155ProxyWrapper: ERC1155ProxyWrapper;
let erc1155Contract: ERC1155MintableContract; let erc1155Contract: ERC1155MintableContract;

View File

@ -31,6 +31,7 @@ import * as _ from 'lodash';
import { import {
artifacts, artifacts,
ERC1155ProxyContract,
ERC1155ProxyWrapper, ERC1155ProxyWrapper,
ERC20ProxyContract, ERC20ProxyContract,
ERC20Wrapper, ERC20Wrapper,
@ -71,7 +72,7 @@ describe('Asset Transfer Proxies', () => {
let erc721AFromTokenId: BigNumber; let erc721AFromTokenId: BigNumber;
let erc721BFromTokenId: BigNumber; let erc721BFromTokenId: BigNumber;
let erc1155Proxy: ERC721ProxyContract; let erc1155Proxy: ERC1155ProxyContract;
let erc1155ProxyWrapper: ERC1155ProxyWrapper; let erc1155ProxyWrapper: ERC1155ProxyWrapper;
let erc1155Contract: ERC1155MintableContract; let erc1155Contract: ERC1155MintableContract;
let erc1155Contract2: ERC1155MintableContract; let erc1155Contract2: ERC1155MintableContract;

View File

@ -1,5 +1,6 @@
import { import {
artifacts as proxyArtifacts, artifacts as proxyArtifacts,
ERC1155ProxyContract,
ERC1155ProxyWrapper, ERC1155ProxyWrapper,
ERC20ProxyContract, ERC20ProxyContract,
ERC20Wrapper, ERC20Wrapper,
@ -69,7 +70,7 @@ describe('Exchange core', () => {
let exchange: ExchangeContract; let exchange: ExchangeContract;
let erc20Proxy: ERC20ProxyContract; let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract; let erc721Proxy: ERC721ProxyContract;
let erc1155Proxy: ERC721ProxyContract; let erc1155Proxy: ERC1155ProxyContract;
let multiAssetProxy: MultiAssetProxyContract; let multiAssetProxy: MultiAssetProxyContract;
let staticCallProxy: StaticCallProxyContract; let staticCallProxy: StaticCallProxyContract;
let staticCallTarget: TestStaticCallTargetContract; let staticCallTarget: TestStaticCallTargetContract;

View File

@ -4,14 +4,17 @@ import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { AssetProxyOwnerContract } from '../../generated-wrappers/asset_proxy_owner'; import { AssetProxyOwnerContract, TestAssetProxyOwnerContract } from '../../src';
import { artifacts } from '../../src/artifacts'; import { artifacts } from '../../src/artifacts';
export class AssetProxyOwnerWrapper { export class AssetProxyOwnerWrapper {
private readonly _assetProxyOwner: AssetProxyOwnerContract; private readonly _assetProxyOwner: AssetProxyOwnerContract | TestAssetProxyOwnerContract;
private readonly _web3Wrapper: Web3Wrapper; private readonly _web3Wrapper: Web3Wrapper;
private readonly _logDecoder: LogDecoder; private readonly _logDecoder: LogDecoder;
constructor(assetproxyOwnerContract: AssetProxyOwnerContract, provider: Web3ProviderEngine) { constructor(
assetproxyOwnerContract: AssetProxyOwnerContract | TestAssetProxyOwnerContract,
provider: Web3ProviderEngine,
) {
this._assetProxyOwner = assetproxyOwnerContract; this._assetProxyOwner = assetproxyOwnerContract;
this._web3Wrapper = new Web3Wrapper(provider); this._web3Wrapper = new Web3Wrapper(provider);
this._logDecoder = new LogDecoder(this._web3Wrapper, { ...artifacts, ...proxyArtifacts }); this._logDecoder = new LogDecoder(this._web3Wrapper, { ...artifacts, ...proxyArtifacts });
@ -57,7 +60,7 @@ export class AssetProxyOwnerWrapper {
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const txHash = await (this const txHash = await (this
._assetProxyOwner as AssetProxyOwnerContract).executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync( ._assetProxyOwner as TestAssetProxyOwnerContract).executeRemoveAuthorizedAddressAtIndex.sendTransactionAsync(
txId, txId,
{ {
from, from,

View File

@ -3,14 +3,17 @@ import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { MultiSigWalletContract } from '../../generated-wrappers/multi_sig_wallet'; import { MultiSigWalletContract, MultiSigWalletWithTimeLockContract } from '../../src';
import { artifacts } from '../../src/artifacts'; import { artifacts } from '../../src/artifacts';
export class MultiSigWrapper { export class MultiSigWrapper {
private readonly _multiSig: MultiSigWalletContract; private readonly _multiSig: MultiSigWalletContract | MultiSigWalletWithTimeLockContract;
private readonly _web3Wrapper: Web3Wrapper; private readonly _web3Wrapper: Web3Wrapper;
private readonly _logDecoder: LogDecoder; private readonly _logDecoder: LogDecoder;
constructor(multiSigContract: MultiSigWalletContract, provider: Web3ProviderEngine) { constructor(
multiSigContract: MultiSigWalletContract | MultiSigWalletWithTimeLockContract,
provider: Web3ProviderEngine,
) {
this._multiSig = multiSigContract; this._multiSig = multiSigContract;
this._web3Wrapper = new Web3Wrapper(provider); this._web3Wrapper = new Web3Wrapper(provider);
this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts); this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);

View File

@ -1,7 +1,11 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import { BaseContract{{#if events}},
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager{{/if}},PromiseWithTransactionHash } from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -9,7 +13,8 @@ import {
CallData, CallData,
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,{{#if events}}
LogWithDecodedArgs,{{/if}}
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -53,7 +58,8 @@ export class {{contractName}}Contract extends BaseContract {
{{> tx contractName=../contractName}} {{> tx contractName=../contractName}}
{{/this.constant}} {{/this.constant}}
{{/each}} {{/each}}
public static async deployFrom0xArtifactAsync( {{#if events}}private readonly _subscriptionManager: SubscriptionManager<{{contractName}}EventArgs, {{contractName}}Events>;
{{/if}}public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>, txDefaults: Partial<TxData>,
@ -138,10 +144,82 @@ export class {{contractName}}Contract extends BaseContract {
{{/each}} {{/each}}
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
}{{#if events}}
/**
* Subscribe to an event type emitted by the {{contractName}} contract.
* @param eventName The {{contractName}} contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends {{contractName}}EventArgs>(
eventName: {{contractName}}Events,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, {{contractName}}Events);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
{{contractName}}Contract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
} }
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The {{contractName}} contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends {{contractName}}EventArgs>(
eventName: {{contractName}}Events,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, {{contractName}}Events);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
{{contractName}}Contract.ABI(),
);
return logs;
}{{/if}}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('{{contractName}}', {{contractName}}Contract.ABI(), address, supportedProvider, txDefaults); super('{{contractName}}', {{contractName}}Contract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);{{#if events}}
this._subscriptionManager = new SubscriptionManager<{{contractName}}EventArgs, {{contractName}}Events>(
{{contractName}}Contract.ABI(),
this._web3Wrapper,
);{{/if}}
} }
} }

View File

@ -1,4 +1,13 @@
[ [
{
"version": "5.1.0",
"changes": [
{
"note": "Add subscribe/unsubscribe methods for events",
"pr": 1970
}
]
},
{ {
"timestamp": 1563957393, "timestamp": 1563957393,
"version": "5.0.3", "version": "5.0.3",

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -2083,6 +2091,7 @@ export class AssetProxyOwnerContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<AssetProxyOwnerEventArgs, AssetProxyOwnerEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -2861,9 +2870,81 @@ export class AssetProxyOwnerContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the AssetProxyOwner contract.
* @param eventName The AssetProxyOwner contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends AssetProxyOwnerEventArgs>(
eventName: AssetProxyOwnerEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, AssetProxyOwnerEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
AssetProxyOwnerContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The AssetProxyOwner contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends AssetProxyOwnerEventArgs>(
eventName: AssetProxyOwnerEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, AssetProxyOwnerEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
AssetProxyOwnerContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('AssetProxyOwner', AssetProxyOwnerContract.ABI(), address, supportedProvider, txDefaults); super('AssetProxyOwner', AssetProxyOwnerContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<AssetProxyOwnerEventArgs, AssetProxyOwnerEvents>(
AssetProxyOwnerContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -192,6 +200,7 @@ export class CoordinatorRegistryContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<CoordinatorRegistryEventArgs, CoordinatorRegistryEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -313,9 +322,81 @@ export class CoordinatorRegistryContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the CoordinatorRegistry contract.
* @param eventName The CoordinatorRegistry contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends CoordinatorRegistryEventArgs>(
eventName: CoordinatorRegistryEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, CoordinatorRegistryEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
CoordinatorRegistryContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The CoordinatorRegistry contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends CoordinatorRegistryEventArgs>(
eventName: CoordinatorRegistryEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, CoordinatorRegistryEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
CoordinatorRegistryContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('CoordinatorRegistry', CoordinatorRegistryContract.ABI(), address, supportedProvider, txDefaults); super('CoordinatorRegistry', CoordinatorRegistryContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<CoordinatorRegistryEventArgs, CoordinatorRegistryEvents>(
CoordinatorRegistryContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -1102,6 +1110,7 @@ export class DummyERC20TokenContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<DummyERC20TokenEventArgs, DummyERC20TokenEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -1497,9 +1506,81 @@ export class DummyERC20TokenContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the DummyERC20Token contract.
* @param eventName The DummyERC20Token contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends DummyERC20TokenEventArgs>(
eventName: DummyERC20TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, DummyERC20TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
DummyERC20TokenContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The DummyERC20Token contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends DummyERC20TokenEventArgs>(
eventName: DummyERC20TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, DummyERC20TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
DummyERC20TokenContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('DummyERC20Token', DummyERC20TokenContract.ABI(), address, supportedProvider, txDefaults); super('DummyERC20Token', DummyERC20TokenContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<DummyERC20TokenEventArgs, DummyERC20TokenEvents>(
DummyERC20TokenContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -1432,6 +1440,7 @@ export class DummyERC721TokenContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<DummyERC721TokenEventArgs, DummyERC721TokenEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -1866,9 +1875,81 @@ export class DummyERC721TokenContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the DummyERC721Token contract.
* @param eventName The DummyERC721Token contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends DummyERC721TokenEventArgs>(
eventName: DummyERC721TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, DummyERC721TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
DummyERC721TokenContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The DummyERC721Token contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends DummyERC721TokenEventArgs>(
eventName: DummyERC721TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, DummyERC721TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
DummyERC721TokenContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('DummyERC721Token', DummyERC721TokenContract.ABI(), address, supportedProvider, txDefaults); super('DummyERC721Token', DummyERC721TokenContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<DummyERC721TokenEventArgs, DummyERC721TokenEvents>(
DummyERC721TokenContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -691,6 +699,7 @@ export class ERC20ProxyContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<ERC20ProxyEventArgs, ERC20ProxyEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -933,9 +942,81 @@ export class ERC20ProxyContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the ERC20Proxy contract.
* @param eventName The ERC20Proxy contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC20ProxyEventArgs>(
eventName: ERC20ProxyEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ERC20ProxyEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
ERC20ProxyContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ERC20Proxy contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ERC20ProxyEventArgs>(
eventName: ERC20ProxyEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ERC20ProxyEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
ERC20ProxyContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('ERC20Proxy', ERC20ProxyContract.ABI(), address, supportedProvider, txDefaults); super('ERC20Proxy', ERC20ProxyContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<ERC20ProxyEventArgs, ERC20ProxyEvents>(
ERC20ProxyContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -579,6 +587,7 @@ export class ERC20TokenContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -813,9 +822,81 @@ export class ERC20TokenContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the ERC20Token contract.
* @param eventName The ERC20Token contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC20TokenEventArgs>(
eventName: ERC20TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
ERC20TokenContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ERC20Token contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ERC20TokenEventArgs>(
eventName: ERC20TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ERC20TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
ERC20TokenContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('ERC20Token', ERC20TokenContract.ABI(), address, supportedProvider, txDefaults); super('ERC20Token', ERC20TokenContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>(
ERC20TokenContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -691,6 +699,7 @@ export class ERC721ProxyContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<ERC721ProxyEventArgs, ERC721ProxyEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -933,9 +942,81 @@ export class ERC721ProxyContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the ERC721Proxy contract.
* @param eventName The ERC721Proxy contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC721ProxyEventArgs>(
eventName: ERC721ProxyEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ERC721ProxyEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
ERC721ProxyContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ERC721Proxy contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ERC721ProxyEventArgs>(
eventName: ERC721ProxyEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ERC721ProxyEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
ERC721ProxyContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('ERC721Proxy', ERC721ProxyContract.ABI(), address, supportedProvider, txDefaults); super('ERC721Proxy', ERC721ProxyContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<ERC721ProxyEventArgs, ERC721ProxyEvents>(
ERC721ProxyContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -972,6 +980,7 @@ export class ERC721TokenContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -1286,9 +1295,81 @@ export class ERC721TokenContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the ERC721Token contract.
* @param eventName The ERC721Token contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ERC721TokenEventArgs>(
eventName: ERC721TokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
ERC721TokenContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ERC721Token contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ERC721TokenEventArgs>(
eventName: ERC721TokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ERC721TokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
ERC721TokenContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('ERC721Token', ERC721TokenContract.ABI(), address, supportedProvider, txDefaults); super('ERC721Token', ERC721TokenContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>(
ERC721TokenContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -4555,6 +4563,7 @@ export class ExchangeContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<ExchangeEventArgs, ExchangeEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -6591,9 +6600,81 @@ export class ExchangeContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the Exchange contract.
* @param eventName The Exchange contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ExchangeEventArgs>(
eventName: ExchangeEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
ExchangeContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The Exchange contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ExchangeEventArgs>(
eventName: ExchangeEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
ExchangeContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('Exchange', ExchangeContract.ABI(), address, supportedProvider, txDefaults); super('Exchange', ExchangeContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<ExchangeEventArgs, ExchangeEvents>(
ExchangeContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -888,6 +896,7 @@ export class MultiAssetProxyContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<MultiAssetProxyEventArgs, MultiAssetProxyEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -1200,9 +1209,81 @@ export class MultiAssetProxyContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the MultiAssetProxy contract.
* @param eventName The MultiAssetProxy contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends MultiAssetProxyEventArgs>(
eventName: MultiAssetProxyEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, MultiAssetProxyEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
MultiAssetProxyContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The MultiAssetProxy contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends MultiAssetProxyEventArgs>(
eventName: MultiAssetProxyEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, MultiAssetProxyEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
MultiAssetProxyContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('MultiAssetProxy', MultiAssetProxyContract.ABI(), address, supportedProvider, txDefaults); super('MultiAssetProxy', MultiAssetProxyContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<MultiAssetProxyEventArgs, MultiAssetProxyEvents>(
MultiAssetProxyContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -884,6 +892,7 @@ export class WETH9Contract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<WETH9EventArgs, WETH9Events>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -1226,9 +1235,81 @@ export class WETH9Contract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the WETH9 contract.
* @param eventName The WETH9 contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends WETH9EventArgs>(
eventName: WETH9Events,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
WETH9Contract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The WETH9 contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends WETH9EventArgs>(
eventName: WETH9Events,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
WETH9Contract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('WETH9', WETH9Contract.ABI(), address, supportedProvider, txDefaults); super('WETH9', WETH9Contract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<WETH9EventArgs, WETH9Events>(
WETH9Contract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -693,6 +701,7 @@ export class ZRXTokenContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<ZRXTokenEventArgs, ZRXTokenEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -966,9 +975,81 @@ export class ZRXTokenContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the ZRXToken contract.
* @param eventName The ZRXToken contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends ZRXTokenEventArgs>(
eventName: ZRXTokenEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, ZRXTokenEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
ZRXTokenContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The ZRXToken contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends ZRXTokenEventArgs>(
eventName: ZRXTokenEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, ZRXTokenEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
ZRXTokenContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('ZRXToken', ZRXTokenContract.ABI(), address, supportedProvider, txDefaults); super('ZRXToken', ZRXTokenContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<ZRXTokenEventArgs, ZRXTokenEvents>(
ZRXTokenContract.ABI(),
this._web3Wrapper,
);
} }
} }

View File

@ -93,6 +93,7 @@
"mocha": "^6.2.0", "mocha": "^6.2.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"shx": "^0.2.2", "shx": "^0.2.2",
"sinon": "^4.0.0",
"solhint": "^1.4.1", "solhint": "^1.4.1",
"tslint": "5.11.0", "tslint": "5.11.0",
"typescript": "3.0.1" "typescript": "3.0.1"

View File

@ -197,6 +197,39 @@ class AbiGenDummy(BaseContractWrapper):
view_only=True view_only=True
) )
def withdraw(
self,
wad: int,
tx_params: Optional[TxParams] = None,
view_only: bool = False,
) -> Union[None, Union[HexBytes, bytes]]:
"""Execute underlying, same-named contract method.
:param tx_params: transaction parameters
:param view_only: whether to use transact() or call()
:returns: if param `view_only`:code: is `True`:code:, then returns the
value returned from the underlying function; else returns the
transaction hash.
"""
self.validator.assert_valid(
method_name='withdraw',
parameter_name='wad',
argument_value=wad,
)
# safeguard against fractional inputs
wad = int(wad)
func = self._get_contract_instance(
self.contract_address
).functions.withdraw(
wad
)
return self._invoke_function_call(
func=func,
tx_params=tx_params,
view_only=view_only
)
def ecrecover_fn( def ecrecover_fn(
self, self,
_hash: bytes, _hash: bytes,
@ -595,6 +628,19 @@ class AbiGenDummy(BaseContractWrapper):
tx_params=tx_params, tx_params=tx_params,
view_only=True view_only=True
) )
def get_withdrawal_event(
self, tx_hash: Union[HexBytes, bytes]
) -> Tuple[AttributeDict]:
"""Get log entry for Withdrawal event.
:param tx_hash: hash of transaction emitting Withdrawal event
"""
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
return (
self._get_contract_instance(self.contract_address)
.events.Withdrawal()
.processReceipt(tx_receipt)
)
def get_an_event_event( def get_an_event_event(
self, tx_hash: Union[HexBytes, bytes] self, tx_hash: Union[HexBytes, bytes]
) -> Tuple[AttributeDict]: ) -> Tuple[AttributeDict]:
@ -613,7 +659,7 @@ class AbiGenDummy(BaseContractWrapper):
def abi(): def abi():
"""Return the ABI to the underlying contract.""" """Return the ABI to the underlying contract."""
return json.loads( return json.loads(
'[{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes[]"}],"name":"acceptsAnArrayOfBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes"}],"name":"acceptsBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"nestedStructOutput","outputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"address"},{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"y","type":"address"},{"name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"name":"structInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethodThatReturnsNothing","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"n","type":"tuple"}],"name":"nestedStructInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"structOutput","outputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"param","type":"uint8"}],"name":"AnEvent","type":"event"}]' # noqa: E501 (line-too-long) '[{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes[]"}],"name":"acceptsAnArrayOfBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes"}],"name":"acceptsBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"nestedStructOutput","outputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"address"},{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"y","type":"address"},{"name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"name":"structInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethodThatReturnsNothing","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"n","type":"tuple"}],"name":"nestedStructInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"structOutput","outputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"param","type":"uint8"}],"name":"AnEvent","type":"event"}]' # noqa: E501 (line-too-long)
) )
# pylint: disable=too-many-lines # pylint: disable=too-many-lines

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace // tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract, PromiseWithTransactionHash } from '@0x/base-contract'; import {
BaseContract,
BlockRange,
EventCallback,
IndexedFilterValues,
SubscriptionManager,
PromiseWithTransactionHash,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { import {
BlockParam, BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi, ContractAbi,
ContractArtifact, ContractArtifact,
DecodedLogArgs, DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi, MethodAbi,
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
TxData, TxData,
@ -23,12 +31,18 @@ import { assert } from '@0x/assert';
import * as ethers from 'ethers'; import * as ethers from 'ethers';
// tslint:enable:no-unused-variable // tslint:enable:no-unused-variable
export type AbiGenDummyEventArgs = AbiGenDummyAnEventEventArgs; export type AbiGenDummyEventArgs = AbiGenDummyWithdrawalEventArgs | AbiGenDummyAnEventEventArgs;
export enum AbiGenDummyEvents { export enum AbiGenDummyEvents {
Withdrawal = 'Withdrawal',
AnEvent = 'AnEvent', AnEvent = 'AnEvent',
} }
export interface AbiGenDummyWithdrawalEventArgs extends DecodedLogArgs {
_owner: string;
_value: BigNumber;
}
export interface AbiGenDummyAnEventEventArgs extends DecodedLogArgs { export interface AbiGenDummyAnEventEventArgs extends DecodedLogArgs {
param: number; param: number;
} }
@ -115,6 +129,106 @@ export class AbiGenDummyContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
public withdraw = {
async sendTransactionAsync(wad: BigNumber, txData?: Partial<TxData> | undefined): Promise<string> {
assert.isBigNumber('wad', wad);
const self = (this as any) as AbiGenDummyContract;
const encodedData = self._strictEncodeArguments('withdraw(uint256)', [wad]);
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...txData,
data: encodedData,
},
self._web3Wrapper.getContractDefaults(),
self.withdraw.estimateGasAsync.bind(self, wad),
);
if (txDataWithDefaults.from !== undefined) {
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
}
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
return txHash;
},
awaitTransactionSuccessAsync(
wad: BigNumber,
txData?: Partial<TxData>,
pollingIntervalMs?: number,
timeoutMs?: number,
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
assert.isBigNumber('wad', wad);
const self = (this as any) as AbiGenDummyContract;
const txHashPromise = self.withdraw.sendTransactionAsync(wad, txData);
return new PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>(
txHashPromise,
(async (): Promise<TransactionReceiptWithDecodedLogs> => {
// When the transaction hash resolves, wait for it to be mined.
return self._web3Wrapper.awaitTransactionSuccessAsync(
await txHashPromise,
pollingIntervalMs,
timeoutMs,
);
})(),
);
},
async estimateGasAsync(wad: BigNumber, txData?: Partial<TxData> | undefined): Promise<number> {
assert.isBigNumber('wad', wad);
const self = (this as any) as AbiGenDummyContract;
const encodedData = self._strictEncodeArguments('withdraw(uint256)', [wad]);
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...txData,
data: encodedData,
},
self._web3Wrapper.getContractDefaults(),
);
if (txDataWithDefaults.from !== undefined) {
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
}
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
return gas;
},
async callAsync(wad: BigNumber, callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
assert.isBigNumber('wad', wad);
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
schemas.addressSchema,
schemas.numberSchema,
schemas.jsNumber,
]);
if (defaultBlock !== undefined) {
assert.isBlockParam('defaultBlock', defaultBlock);
}
const self = (this as any) as AbiGenDummyContract;
const encodedData = self._strictEncodeArguments('withdraw(uint256)', [wad]);
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
{
to: self.address,
...callData,
data: encodedData,
},
self._web3Wrapper.getContractDefaults(),
);
callDataWithDefaults.from = callDataWithDefaults.from
? callDataWithDefaults.from.toLowerCase()
: callDataWithDefaults.from;
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
const abiEncoder = self._lookupAbiEncoder('withdraw(uint256)');
// tslint:disable boolean-naming
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
// tslint:enable boolean-naming
return result;
},
getABIEncodedTransactionData(wad: BigNumber): string {
assert.isBigNumber('wad', wad);
const self = (this as any) as AbiGenDummyContract;
const abiEncodedTransactionData = self._strictEncodeArguments('withdraw(uint256)', [wad]);
return abiEncodedTransactionData;
},
};
public ecrecoverFn = { public ecrecoverFn = {
async callAsync( async callAsync(
hash: string, hash: string,
@ -903,6 +1017,7 @@ export class AbiGenDummyContract extends BaseContract {
return abiEncodedTransactionData; return abiEncodedTransactionData;
}, },
}; };
private readonly _subscriptionManager: SubscriptionManager<AbiGenDummyEventArgs, AbiGenDummyEvents>;
public static async deployFrom0xArtifactAsync( public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact, artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider, supportedProvider: SupportedProvider,
@ -982,6 +1097,20 @@ export class AbiGenDummyContract extends BaseContract {
stateMutability: 'pure', stateMutability: 'pure',
type: 'function', type: 'function',
}, },
{
constant: false,
inputs: [
{
name: 'wad',
type: 'uint256',
},
],
name: 'withdraw',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function',
},
{ {
constant: true, constant: true,
inputs: [ inputs: [
@ -1307,6 +1436,24 @@ export class AbiGenDummyContract extends BaseContract {
stateMutability: 'pure', stateMutability: 'pure',
type: 'function', type: 'function',
}, },
{
anonymous: false,
inputs: [
{
name: '_owner',
type: 'address',
indexed: true,
},
{
name: '_value',
type: 'uint256',
indexed: false,
},
],
name: 'Withdrawal',
outputs: [],
type: 'event',
},
{ {
anonymous: false, anonymous: false,
inputs: [ inputs: [
@ -1323,9 +1470,81 @@ export class AbiGenDummyContract extends BaseContract {
] as ContractAbi; ] as ContractAbi;
return abi; return abi;
} }
/**
* Subscribe to an event type emitted by the AbiGenDummy contract.
* @param eventName The AbiGenDummy contract event you would like to subscribe to.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
* @param callback Callback that gets called when a log is added/removed
* @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
* @return Subscription token used later to unsubscribe
*/
public subscribe<ArgsType extends AbiGenDummyEventArgs>(
eventName: AbiGenDummyEvents,
indexFilterValues: IndexedFilterValues,
callback: EventCallback<ArgsType>,
isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string {
assert.doesBelongToStringEnum('eventName', eventName, AbiGenDummyEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
this.address,
eventName,
indexFilterValues,
AbiGenDummyContract.ABI(),
callback,
isVerbose,
blockPollingIntervalMs,
);
return subscriptionToken;
}
/**
* Cancel a subscription
* @param subscriptionToken Subscription token returned by `subscribe()`
*/
public unsubscribe(subscriptionToken: string): void {
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
* @param eventName The AbiGenDummy contract event you would like to subscribe to.
* @param blockRange Block range to get logs from.
* @param indexFilterValues An object where the keys are indexed args returned by the event and
* the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
* @return Array of logs that match the parameters
*/
public async getLogsAsync<ArgsType extends AbiGenDummyEventArgs>(
eventName: AbiGenDummyEvents,
blockRange: BlockRange,
indexFilterValues: IndexedFilterValues,
): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
assert.doesBelongToStringEnum('eventName', eventName, AbiGenDummyEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
this.address,
eventName,
blockRange,
indexFilterValues,
AbiGenDummyContract.ABI(),
);
return logs;
}
constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) { constructor(address: string, supportedProvider: SupportedProvider, txDefaults?: Partial<TxData>) {
super('AbiGenDummy', AbiGenDummyContract.ABI(), address, supportedProvider, txDefaults); super('AbiGenDummy', AbiGenDummyContract.ABI(), address, supportedProvider, txDefaults);
classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
this._subscriptionManager = new SubscriptionManager<AbiGenDummyEventArgs, AbiGenDummyEvents>(
AbiGenDummyContract.ABI(),
this._web3Wrapper,
);
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -90,6 +90,12 @@ contract AbiGenDummy
return ecrecover(prefixedHash, v, r, s); return ecrecover(prefixedHash, v, r, s);
} }
event Withdrawal(address indexed _owner, uint _value);
function withdraw(uint wad) public {
emit Withdrawal(msg.sender, wad);
}
// test: generated code should normalize address inputs to lowercase // test: generated code should normalize address inputs to lowercase
// add extra inputs to make sure it works with address in any position // add extra inputs to make sure it works with address in any position
function withAddressInput(address x, uint256 a, uint256 b, address y, uint256 c) function withAddressInput(address x, uint256 a, uint256 b, address y, uint256 c)

View File

@ -7,8 +7,9 @@ import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised'; import * as chaiAsPromised from 'chai-as-promised';
import * as ChaiBigNumber from 'chai-bignumber'; import * as ChaiBigNumber from 'chai-bignumber';
import * as dirtyChai from 'dirty-chai'; import * as dirtyChai from 'dirty-chai';
import * as Sinon from 'sinon';
import { AbiGenDummyContract, artifacts, TestLibDummyContract } from '../src'; import { AbiGenDummyContract, AbiGenDummyEvents, artifacts, TestLibDummyContract } from '../src';
const txDefaults = { const txDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS, from: devConstants.TESTRPC_FIRST_ADDRESS,
@ -92,6 +93,36 @@ describe('AbiGenDummy Contract', () => {
}); });
}); });
describe('event subscription', () => {
const indexFilterValues = {};
const emptyCallback = () => {}; // tslint:disable-line:no-empty
let stubs: Sinon.SinonStub[] = [];
afterEach(() => {
stubs.forEach(s => s.restore());
stubs = [];
});
it('should return a subscription token', done => {
const subscriptionToken = abiGenDummy.subscribe(
AbiGenDummyEvents.Withdrawal,
indexFilterValues,
emptyCallback,
);
expect(subscriptionToken).to.be.a('string');
done();
});
it('should allow unsubscribeAll to be called successfully after an error', done => {
abiGenDummy.subscribe(AbiGenDummyEvents.Withdrawal, indexFilterValues, emptyCallback);
stubs.push(
Sinon.stub((abiGenDummy as any)._web3Wrapper, 'getBlockIfExistsAsync').throws(
new Error('JSON RPC error'),
),
);
abiGenDummy.unsubscribeAll();
done();
});
});
describe('withAddressInput', () => { describe('withAddressInput', () => {
it('should normalize address inputs to lowercase', async () => { it('should normalize address inputs to lowercase', async () => {
const xAddress = devConstants.TESTRPC_FIRST_ADDRESS.toUpperCase(); const xAddress = devConstants.TESTRPC_FIRST_ADDRESS.toUpperCase();

View File

@ -1,4 +1,13 @@
[ [
{
"version": "5.2.0",
"changes": [
{
"note": "Add SubscriptionManager",
"pr": 1970
}
]
},
{ {
"timestamp": 1563957393, "timestamp": 1563957393,
"version": "5.1.2", "version": "5.1.2",

View File

@ -48,8 +48,12 @@
"@0x/utils": "^4.4.1", "@0x/utils": "^4.4.1",
"@0x/web3-wrapper": "^6.0.8", "@0x/web3-wrapper": "^6.0.8",
"ethereum-types": "^2.1.4", "ethereum-types": "^2.1.4",
"ethereumjs-blockstream": "6.0.0",
"ethereumjs-util": "^5.1.1",
"ethers": "~4.0.4", "ethers": "~4.0.4",
"lodash": "^4.17.11" "js-sha3": "^0.7.0",
"lodash": "^4.17.11",
"uuid": "^3.3.2"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"

View File

@ -19,6 +19,10 @@ import * as _ from 'lodash';
import { formatABIDataItem } from './utils'; import { formatABIDataItem } from './utils';
export { SubscriptionManager } from './subscription_manager';
export * from './types';
export interface AbiEncoderByFunctionSignature { export interface AbiEncoderByFunctionSignature {
[key: string]: AbiEncoder.Method; [key: string]: AbiEncoder.Method;
} }

View File

@ -12,24 +12,16 @@ import {
import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream'; import { Block, BlockAndLogStreamer, Log } from 'ethereumjs-blockstream';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { import { BlockRange, EventCallback, IndexedFilterValues, SubscriptionErrors } from './types';
BlockRange, import { filterUtils } from './utils/filter_utils';
ContractEventArgs,
ContractEvents,
ContractWrappersError,
EventCallback,
IndexedFilterValues,
} from '../types';
import { constants } from '../utils/constants';
import { filterUtils } from '../utils/filter_utils';
export abstract class ContractWrapper { const DEFAULT_BLOCK_POLLING_INTERVAL = 1000;
public abstract abi: ContractAbi;
protected _networkId: number; export class SubscriptionManager<ContractEventArgs, ContractEvents extends string> {
protected _web3Wrapper: Web3Wrapper; public abi: ContractAbi;
private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined; private _blockAndLogStreamerIfExists: BlockAndLogStreamer<Block, Log> | undefined;
private readonly _blockPollingIntervalMs: number;
private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer; private _blockAndLogStreamIntervalIfExists?: NodeJS.Timer;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _filters: { [filterToken: string]: FilterObject }; private readonly _filters: { [filterToken: string]: FilterObject };
private readonly _filterCallbacks: { private readonly _filterCallbacks: {
[filterToken: string]: EventCallback<ContractEventArgs>; [filterToken: string]: EventCallback<ContractEventArgs>;
@ -43,26 +35,24 @@ export abstract class ContractWrapper {
logUtils.warn(err); logUtils.warn(err);
} }
} }
constructor(web3Wrapper: Web3Wrapper, networkId: number, blockPollingIntervalMs?: number) { constructor(abi: ContractAbi, web3Wrapper: Web3Wrapper) {
this.abi = abi;
this._web3Wrapper = web3Wrapper; this._web3Wrapper = web3Wrapper;
this._networkId = networkId;
this._blockPollingIntervalMs =
blockPollingIntervalMs === undefined ? constants.DEFAULT_BLOCK_POLLING_INTERVAL : blockPollingIntervalMs;
this._filters = {}; this._filters = {};
this._filterCallbacks = {}; this._filterCallbacks = {};
this._blockAndLogStreamerIfExists = undefined; this._blockAndLogStreamerIfExists = undefined;
this._onLogAddedSubscriptionToken = undefined; this._onLogAddedSubscriptionToken = undefined;
this._onLogRemovedSubscriptionToken = undefined; this._onLogRemovedSubscriptionToken = undefined;
} }
protected _unsubscribeAll(): void { public unsubscribeAll(): void {
const filterTokens = _.keys(this._filterCallbacks); const filterTokens = _.keys(this._filterCallbacks);
_.each(filterTokens, filterToken => { _.each(filterTokens, filterToken => {
this._unsubscribe(filterToken); this.unsubscribe(filterToken);
}); });
} }
protected _unsubscribe(filterToken: string, err?: Error): void { public unsubscribe(filterToken: string, err?: Error): void {
if (this._filters[filterToken] === undefined) { if (this._filters[filterToken] === undefined) {
throw new Error(ContractWrappersError.SubscriptionNotFound); throw new Error(SubscriptionErrors.SubscriptionNotFound);
} }
if (err !== undefined) { if (err !== undefined) {
const callback = this._filterCallbacks[filterToken]; const callback = this._filterCallbacks[filterToken];
@ -74,24 +64,25 @@ export abstract class ContractWrapper {
this._stopBlockAndLogStream(); this._stopBlockAndLogStream();
} }
} }
protected _subscribe<ArgsType extends ContractEventArgs>( public subscribe<ArgsType extends ContractEventArgs>(
address: string, address: string,
eventName: ContractEvents, eventName: ContractEvents,
indexFilterValues: IndexedFilterValues, indexFilterValues: IndexedFilterValues,
abi: ContractAbi, abi: ContractAbi,
callback: EventCallback<ArgsType>, callback: EventCallback<ArgsType>,
isVerbose: boolean = false, isVerbose: boolean = false,
blockPollingIntervalMs?: number,
): string { ): string {
const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi); const filter = filterUtils.getFilter(address, eventName, indexFilterValues, abi);
if (this._blockAndLogStreamerIfExists === undefined) { if (this._blockAndLogStreamerIfExists === undefined) {
this._startBlockAndLogStream(isVerbose); this._startBlockAndLogStream(isVerbose, blockPollingIntervalMs);
} }
const filterToken = filterUtils.generateUUID(); const filterToken = filterUtils.generateUUID();
this._filters[filterToken] = filter; this._filters[filterToken] = filter;
this._filterCallbacks[filterToken] = callback as EventCallback<ContractEventArgs>; this._filterCallbacks[filterToken] = callback as EventCallback<ContractEventArgs>;
return filterToken; return filterToken;
} }
protected async _getLogsAsync<ArgsType extends ContractEventArgs>( public async getLogsAsync<ArgsType extends ContractEventArgs>(
address: string, address: string,
eventName: ContractEvents, eventName: ContractEvents,
blockRange: BlockRange, blockRange: BlockRange,
@ -123,21 +114,23 @@ export abstract class ContractWrapper {
} }
}); });
} }
private _startBlockAndLogStream(isVerbose: boolean): void { private _startBlockAndLogStream(isVerbose: boolean, blockPollingIntervalMs?: number): void {
if (this._blockAndLogStreamerIfExists !== undefined) { if (this._blockAndLogStreamerIfExists !== undefined) {
throw new Error(ContractWrappersError.SubscriptionAlreadyPresent); throw new Error(SubscriptionErrors.SubscriptionAlreadyPresent);
} }
this._blockAndLogStreamerIfExists = new BlockAndLogStreamer( this._blockAndLogStreamerIfExists = new BlockAndLogStreamer(
this._blockstreamGetBlockOrNullAsync.bind(this), this._blockstreamGetBlockOrNullAsync.bind(this),
this._blockstreamGetLogsAsync.bind(this), this._blockstreamGetLogsAsync.bind(this),
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), SubscriptionManager._onBlockAndLogStreamerError.bind(this, isVerbose),
); );
const catchAllLogFilter = {}; const catchAllLogFilter = {};
this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter); this._blockAndLogStreamerIfExists.addLogFilter(catchAllLogFilter);
const _blockPollingIntervalMs =
blockPollingIntervalMs === undefined ? DEFAULT_BLOCK_POLLING_INTERVAL : blockPollingIntervalMs;
this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval( this._blockAndLogStreamIntervalIfExists = intervalUtils.setAsyncExcludingInterval(
this._reconcileBlockAsync.bind(this), this._reconcileBlockAsync.bind(this),
this._blockPollingIntervalMs, _blockPollingIntervalMs,
ContractWrapper._onBlockAndLogStreamerError.bind(this, isVerbose), SubscriptionManager._onBlockAndLogStreamerError.bind(this, isVerbose),
); );
let isRemoved = false; let isRemoved = false;
this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded( this._onLogAddedSubscriptionToken = this._blockAndLogStreamerIfExists.subscribeToOnLogAdded(
@ -176,7 +169,7 @@ export abstract class ContractWrapper {
} }
private _stopBlockAndLogStream(): void { private _stopBlockAndLogStream(): void {
if (this._blockAndLogStreamerIfExists === undefined) { if (this._blockAndLogStreamerIfExists === undefined) {
throw new Error(ContractWrappersError.SubscriptionNotFound); throw new Error(SubscriptionErrors.SubscriptionNotFound);
} }
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string); this._blockAndLogStreamerIfExists.unsubscribeFromOnLogAdded(this._onLogAddedSubscriptionToken as string);
this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string); this._blockAndLogStreamerIfExists.unsubscribeFromOnLogRemoved(this._onLogRemovedSubscriptionToken as string);

View File

@ -0,0 +1,38 @@
import { BlockParam, ContractEventArg, DecodedLogArgs, LogEntryEvent, LogWithDecodedArgs } from 'ethereum-types';
export type LogEvent = LogEntryEvent;
export interface DecodedLogEvent<ArgsType extends DecodedLogArgs> {
isRemoved: boolean;
log: LogWithDecodedArgs<ArgsType>;
}
export type EventCallback<ArgsType extends DecodedLogArgs> = (
err: null | Error,
log?: DecodedLogEvent<ArgsType>,
) => void;
export interface ContractEvent<ContractEventArgs> {
logIndex: number;
transactionIndex: number;
transactionHash: string;
blockHash: string;
blockNumber: number;
address: string;
type: string;
event: string;
args: ContractEventArgs;
}
export enum SubscriptionErrors {
SubscriptionNotFound = 'SUBSCRIPTION_NOT_FOUND',
SubscriptionAlreadyPresent = 'SUBSCRIPTION_ALREADY_PRESENT',
}
export interface IndexedFilterValues {
[index: string]: ContractEventArg;
}
export interface BlockRange {
fromBlock: BlockParam;
toBlock: BlockParam;
}

View File

@ -0,0 +1,87 @@
import { ContractAbi, EventAbi, FilterObject, LogEntry } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util';
import * as jsSHA3 from 'js-sha3';
import * as _ from 'lodash';
import * as uuid from 'uuid/v4';
import { BlockRange, IndexedFilterValues } from '../types';
const TOPIC_LENGTH = 32;
export const filterUtils = {
generateUUID(): string {
return uuid();
},
getFilter<ContractEvents extends string>(
address: string,
eventName: ContractEvents,
indexFilterValues: IndexedFilterValues,
abi: ContractAbi,
blockRange?: BlockRange,
): FilterObject {
const eventAbi = _.find(abi, { name: eventName }) as EventAbi;
const eventSignature = filterUtils.getEventSignatureFromAbiByName(eventAbi);
const topicForEventSignature = ethUtil.addHexPrefix(jsSHA3.keccak256(eventSignature));
const topicsForIndexedArgs = filterUtils.getTopicsForIndexedArgs(eventAbi, indexFilterValues);
const topics = [topicForEventSignature, ...topicsForIndexedArgs];
let filter: FilterObject = {
address,
topics,
};
if (blockRange !== undefined) {
filter = {
...blockRange,
...filter,
};
}
return filter;
},
getEventSignatureFromAbiByName(eventAbi: EventAbi): string {
const types = _.map(eventAbi.inputs, 'type');
const signature = `${eventAbi.name}(${types.join(',')})`;
return signature;
},
getTopicsForIndexedArgs(abi: EventAbi, indexFilterValues: IndexedFilterValues): Array<string | null> {
const topics: Array<string | null> = [];
for (const eventInput of abi.inputs) {
if (!eventInput.indexed) {
continue;
}
if (indexFilterValues[eventInput.name] === undefined) {
// Null is a wildcard topic in a JSON-RPC call
topics.push(null);
} else {
const value = indexFilterValues[eventInput.name] as string;
const buffer = ethUtil.toBuffer(value);
const paddedBuffer = ethUtil.setLengthLeft(buffer, TOPIC_LENGTH);
const topic = ethUtil.bufferToHex(paddedBuffer);
topics.push(topic);
}
}
return topics;
},
matchesFilter(log: LogEntry, filter: FilterObject): boolean {
if (filter.address !== undefined && log.address !== filter.address) {
return false;
}
if (filter.topics !== undefined) {
return filterUtils.doesMatchTopics(log.topics, filter.topics);
}
return true;
},
doesMatchTopics(logTopics: string[], filterTopics: Array<string[] | string | null>): boolean {
const matchesTopic = _.zipWith(logTopics, filterTopics, filterUtils.matchesTopic.bind(filterUtils));
const doesMatchTopics = _.every(matchesTopic);
return doesMatchTopics;
},
matchesTopic(logTopic: string, filterTopic: string[] | string | null): boolean {
if (_.isArray(filterTopic)) {
return _.includes(filterTopic, logTopic);
}
if (_.isString(filterTopic)) {
return filterTopic === logTopic;
}
// null topic is a wildcard
return true;
},
};

View File

@ -1,4 +1,13 @@
[ [
{
"version": "10.0.0",
"changes": [
{
"note": "Constructors for `ERC20TokenWrapper`, `ERC721TokenWrapper`, and `EtherTokenWrapper` no longer accept networkId",
"pr": 1970
}
]
},
{ {
"version": "9.1.8", "version": "9.1.8",
"changes": [ "changes": [

View File

@ -73,6 +73,7 @@
"dependencies": { "dependencies": {
"@0x/abi-gen-wrappers": "^5.0.3", "@0x/abi-gen-wrappers": "^5.0.3",
"@0x/assert": "^2.1.1", "@0x/assert": "^2.1.1",
"@0x/base-contract": "^5.1.2",
"@0x/contract-addresses": "^3.0.2", "@0x/contract-addresses": "^3.0.2",
"@0x/contract-artifacts": "^2.0.2", "@0x/contract-artifacts": "^2.0.2",
"@0x/json-schemas": "^3.1.11", "@0x/json-schemas": "^3.1.11",

View File

@ -119,24 +119,9 @@ export class ContractWrappers {
: config.contractAddresses; : config.contractAddresses;
this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc20Proxy); this.erc20Proxy = new ERC20ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc20Proxy);
this.erc721Proxy = new ERC721ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc721Proxy); this.erc721Proxy = new ERC721ProxyWrapper(this._web3Wrapper, config.networkId, contractAddresses.erc721Proxy);
this.erc20Token = new ERC20TokenWrapper( this.erc20Token = new ERC20TokenWrapper(this._web3Wrapper, this.erc20Proxy, blockPollingIntervalMs);
this._web3Wrapper, this.erc721Token = new ERC721TokenWrapper(this._web3Wrapper, this.erc721Proxy, blockPollingIntervalMs);
config.networkId, this.etherToken = new EtherTokenWrapper(this._web3Wrapper, this.erc20Token, blockPollingIntervalMs);
this.erc20Proxy,
blockPollingIntervalMs,
);
this.erc721Token = new ERC721TokenWrapper(
this._web3Wrapper,
config.networkId,
this.erc721Proxy,
blockPollingIntervalMs,
);
this.etherToken = new EtherTokenWrapper(
this._web3Wrapper,
config.networkId,
this.erc20Token,
blockPollingIntervalMs,
);
this.exchange = new ExchangeWrapper( this.exchange = new ExchangeWrapper(
this._web3Wrapper, this._web3Wrapper,
config.networkId, config.networkId,

View File

@ -25,17 +25,17 @@ import {
import { decorators } from '../utils/decorators'; import { decorators } from '../utils/decorators';
import { TransactionEncoder } from '../utils/transaction_encoder'; import { TransactionEncoder } from '../utils/transaction_encoder';
import { ContractWrapper } from './contract_wrapper';
/** /**
* This class includes all the functionality related to filling or cancelling orders through * This class includes all the functionality related to filling or cancelling orders through
* the 0x V2 Coordinator extension contract. * the 0x V2 Coordinator extension contract.
*/ */
export class CoordinatorWrapper extends ContractWrapper { export class CoordinatorWrapper {
public abi: ContractAbi = Coordinator.compilerOutput.abi; public abi: ContractAbi = Coordinator.compilerOutput.abi;
public networkId: number; public networkId: number;
public address: string; public address: string;
public exchangeAddress: string; public exchangeAddress: string;
public registryAddress: string; public registryAddress: string;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _contractInstance: CoordinatorContract; private readonly _contractInstance: CoordinatorContract;
private readonly _registryInstance: CoordinatorRegistryContract; private readonly _registryInstance: CoordinatorRegistryContract;
private readonly _exchangeInstance: ExchangeContract; private readonly _exchangeInstance: ExchangeContract;
@ -60,13 +60,12 @@ export class CoordinatorWrapper extends ContractWrapper {
exchangeAddress?: string, exchangeAddress?: string,
registryAddress?: string, registryAddress?: string,
) { ) {
super(web3Wrapper, networkId);
this.networkId = networkId; this.networkId = networkId;
const contractAddresses = getContractAddressesForNetworkOrThrow(networkId); const contractAddresses = getContractAddressesForNetworkOrThrow(networkId);
this.address = address === undefined ? contractAddresses.coordinator : address; this.address = address === undefined ? contractAddresses.coordinator : address;
this.exchangeAddress = exchangeAddress === undefined ? contractAddresses.coordinator : exchangeAddress; this.exchangeAddress = exchangeAddress === undefined ? contractAddresses.coordinator : exchangeAddress;
this.registryAddress = registryAddress === undefined ? contractAddresses.coordinatorRegistry : registryAddress; this.registryAddress = registryAddress === undefined ? contractAddresses.coordinatorRegistry : registryAddress;
this._web3Wrapper = web3Wrapper;
this._contractInstance = new CoordinatorContract( this._contractInstance = new CoordinatorContract(
this.address, this.address,

View File

@ -14,12 +14,11 @@ import { DutchAuctionWrapperError, OrderTransactionOpts } from '../types';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper'; export class DutchAuctionWrapper {
export class DutchAuctionWrapper extends ContractWrapper {
public abi: ContractAbi = DutchAuction.compilerOutput.abi; public abi: ContractAbi = DutchAuction.compilerOutput.abi;
public address: string; public address: string;
private _dutchAuctionContractIfExists?: DutchAuctionContract; private readonly _web3Wrapper: Web3Wrapper;
private readonly _dutchAuctionContract: DutchAuctionContract;
/** /**
* Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex * Dutch auction details are encoded with the asset data for a 0x order. This function produces a hex
* encoded assetData string, containing information both about the asset being traded and the * encoded assetData string, containing information both about the asset being traded and the
@ -56,8 +55,13 @@ export class DutchAuctionWrapper extends ContractWrapper {
* default to the known address corresponding to the networkId. * default to the known address corresponding to the networkId.
*/ */
public constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { public constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId);
this.address = address === undefined ? _getDefaultContractAddresses(networkId).dutchAuction : address; this.address = address === undefined ? _getDefaultContractAddresses(networkId).dutchAuction : address;
this._web3Wrapper = web3Wrapper;
this._dutchAuctionContract = new DutchAuctionContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
} }
/** /**
* Matches the buy and sell orders at an amount given the following: the current block time, the auction * Matches the buy and sell orders at an amount given the following: the current block time, the auction
@ -89,11 +93,9 @@ export class DutchAuctionWrapper extends ContractWrapper {
) { ) {
throw new Error(DutchAuctionWrapperError.AssetDataMismatch); throw new Error(DutchAuctionWrapperError.AssetDataMismatch);
} }
// get contract
const dutchAuctionInstance = await this._getDutchAuctionContractAsync();
// validate transaction // validate transaction
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await dutchAuctionInstance.matchOrders.callAsync( await this._dutchAuctionContract.matchOrders.callAsync(
buyOrder, buyOrder,
sellOrder, sellOrder,
buyOrder.signature, buyOrder.signature,
@ -107,7 +109,7 @@ export class DutchAuctionWrapper extends ContractWrapper {
); );
} }
// send transaction // send transaction
const txHash = await dutchAuctionInstance.matchOrders.sendTransactionAsync( const txHash = await this._dutchAuctionContract.matchOrders.sendTransactionAsync(
buyOrder, buyOrder,
sellOrder, sellOrder,
buyOrder.signature, buyOrder.signature,
@ -129,22 +131,8 @@ export class DutchAuctionWrapper extends ContractWrapper {
public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> { public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> {
// type assertions // type assertions
assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema); assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema);
// get contract
const dutchAuctionInstance = await this._getDutchAuctionContractAsync();
// call contract // call contract
const auctionDetails = await dutchAuctionInstance.getAuctionDetails.callAsync(sellOrder); const auctionDetails = await this._dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
return auctionDetails; return auctionDetails;
} }
private async _getDutchAuctionContractAsync(): Promise<DutchAuctionContract> {
if (this._dutchAuctionContractIfExists !== undefined) {
return this._dutchAuctionContractIfExists;
}
const contractInstance = new DutchAuctionContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._dutchAuctionContractIfExists = contractInstance;
return this._dutchAuctionContractIfExists;
}
} }

View File

@ -8,15 +8,14 @@ import * as _ from 'lodash';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
/** /**
* This class includes the functionality related to interacting with the ERC20Proxy contract. * This class includes the functionality related to interacting with the ERC20Proxy contract.
*/ */
export class ERC20ProxyWrapper extends ContractWrapper { export class ERC20ProxyWrapper {
public abi: ContractAbi = ERC20Proxy.compilerOutput.abi; public abi: ContractAbi = ERC20Proxy.compilerOutput.abi;
public address: string; public address: string;
private _erc20ProxyContractIfExists?: ERC20ProxyContract; private readonly _web3Wrapper: Web3Wrapper;
private readonly _erc20ProxyContract: ERC20ProxyContract;
/** /**
* Instantiate ERC20ProxyWrapper * Instantiate ERC20ProxyWrapper
* @param web3Wrapper Web3Wrapper instance to use * @param web3Wrapper Web3Wrapper instance to use
@ -25,19 +24,23 @@ export class ERC20ProxyWrapper extends ContractWrapper {
* default to the known address corresponding to the networkId. * default to the known address corresponding to the networkId.
*/ */
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId); this._web3Wrapper = web3Wrapper;
this.address = address === undefined ? _getDefaultContractAddresses(networkId).erc20Proxy : address; this.address = address === undefined ? _getDefaultContractAddresses(networkId).erc20Proxy : address;
this._erc20ProxyContract = new ERC20ProxyContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
} }
/** /**
* Get the 4 bytes ID of this asset proxy * Get the 4 bytes ID of this asset proxy
* @return Proxy id * @return Proxy id
*/ */
public async getProxyIdAsync(): Promise<AssetProxyId> { public async getProxyIdAsync(): Promise<AssetProxyId> {
const ERC20ProxyContractInstance = this._getERC20ProxyContract();
// Note(albrow): Below is a TSLint false positive. Code won't compile if // Note(albrow): Below is a TSLint false positive. Code won't compile if
// you remove the type assertion. // you remove the type assertion.
/* tslint:disable-next-line:no-unnecessary-type-assertion */ /* tslint:disable-next-line:no-unnecessary-type-assertion */
const proxyId = (await ERC20ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId; const proxyId = (await this._erc20ProxyContract.getProxyId.callAsync()) as AssetProxyId;
return proxyId; return proxyId;
} }
/** /**
@ -48,8 +51,7 @@ export class ERC20ProxyWrapper extends ContractWrapper {
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress); assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase(); const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const ERC20ProxyContractInstance = this._getERC20ProxyContract(); const isAuthorized = await this._erc20ProxyContract.authorized.callAsync(normalizedExchangeContractAddress);
const isAuthorized = await ERC20ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress);
return isAuthorized; return isAuthorized;
} }
/** /**
@ -57,20 +59,7 @@ export class ERC20ProxyWrapper extends ContractWrapper {
* @return The list of authorized addresses. * @return The list of authorized addresses.
*/ */
public async getAuthorizedAddressesAsync(): Promise<string[]> { public async getAuthorizedAddressesAsync(): Promise<string[]> {
const ERC20ProxyContractInstance = this._getERC20ProxyContract(); const authorizedAddresses = await this._erc20ProxyContract.getAuthorizedAddresses.callAsync();
const authorizedAddresses = await ERC20ProxyContractInstance.getAuthorizedAddresses.callAsync();
return authorizedAddresses; return authorizedAddresses;
} }
private _getERC20ProxyContract(): ERC20ProxyContract {
if (this._erc20ProxyContractIfExists !== undefined) {
return this._erc20ProxyContractIfExists;
}
const contractInstance = new ERC20ProxyContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._erc20ProxyContractIfExists = contractInstance;
return this._erc20ProxyContractIfExists;
}
} }

View File

@ -1,4 +1,5 @@
import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from '@0x/abi-gen-wrappers'; import { ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents } from '@0x/abi-gen-wrappers';
import { SubscriptionManager } from '@0x/base-contract';
import { ERC20Token } from '@0x/contract-artifacts'; import { ERC20Token } from '@0x/contract-artifacts';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
@ -20,7 +21,6 @@ import { assert } from '../utils/assert';
import { constants } from '../utils/constants'; import { constants } from '../utils/constants';
import { utils } from '../utils/utils'; import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
import { ERC20ProxyWrapper } from './erc20_proxy_wrapper'; import { ERC20ProxyWrapper } from './erc20_proxy_wrapper';
/** /**
@ -28,27 +28,28 @@ import { ERC20ProxyWrapper } from './erc20_proxy_wrapper';
* All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances * All ERC20 method calls are supported, along with some convenience methods for getting/setting allowances
* to the 0x ERC20 Proxy smart contract. * to the 0x ERC20 Proxy smart contract.
*/ */
export class ERC20TokenWrapper extends ContractWrapper { export class ERC20TokenWrapper {
public abi: ContractAbi = ERC20Token.compilerOutput.abi; public abi: ContractAbi = ERC20Token.compilerOutput.abi;
public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; public UNLIMITED_ALLOWANCE_IN_BASE_UNITS = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _blockPollingIntervalMs?: number;
private readonly _subscriptionManager: SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>;
private readonly _tokenContractsByAddress: { [address: string]: ERC20TokenContract }; private readonly _tokenContractsByAddress: { [address: string]: ERC20TokenContract };
private readonly _erc20ProxyWrapper: ERC20ProxyWrapper; private readonly _erc20ProxyWrapper: ERC20ProxyWrapper;
/** /**
* Instantiate ERC20TokenWrapper * Instantiate ERC20TokenWrapper
* @param web3Wrapper Web3Wrapper instance to use * @param web3Wrapper Web3Wrapper instance to use
* @param networkId Desired networkId
* @param erc20ProxyWrapper The ERC20ProxyWrapper instance to use * @param erc20ProxyWrapper The ERC20ProxyWrapper instance to use
* @param blockPollingIntervalMs The block polling interval to use for active subscriptions
*/ */
constructor( constructor(web3Wrapper: Web3Wrapper, erc20ProxyWrapper: ERC20ProxyWrapper, blockPollingIntervalMs?: number) {
web3Wrapper: Web3Wrapper, this._web3Wrapper = web3Wrapper;
networkId: number,
erc20ProxyWrapper: ERC20ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._tokenContractsByAddress = {}; this._tokenContractsByAddress = {};
this._erc20ProxyWrapper = erc20ProxyWrapper; this._erc20ProxyWrapper = erc20ProxyWrapper;
this._blockPollingIntervalMs = blockPollingIntervalMs;
this._subscriptionManager = new SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>(
ERC20TokenContract.ABI(),
web3Wrapper,
);
} }
/** /**
* Retrieves an owner's ERC20 token balance. * Retrieves an owner's ERC20 token balance.
@ -371,13 +372,14 @@ export class ERC20TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback); assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase(); const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>( const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
normalizedTokenAddress, normalizedTokenAddress,
eventName, eventName,
indexFilterValues, indexFilterValues,
ERC20Token.compilerOutput.abi, ERC20Token.compilerOutput.abi,
callback, callback,
isVerbose, isVerbose,
this._blockPollingIntervalMs,
); );
return subscriptionToken; return subscriptionToken;
} }
@ -387,13 +389,13 @@ export class ERC20TokenWrapper extends ContractWrapper {
*/ */
public unsubscribe(subscriptionToken: string): void { public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken); assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken); this._subscriptionManager.unsubscribe(subscriptionToken); // doesn't matter which contract is used
} }
/** /**
* Cancels all existing subscriptions * Cancels all existing subscriptions
*/ */
public unsubscribeAll(): void { public unsubscribeAll(): void {
super._unsubscribeAll(); this._subscriptionManager.unsubscribeAll();
} }
/** /**
* Gets historical logs without creating a subscription * Gets historical logs without creating a subscription
@ -415,7 +417,7 @@ export class ERC20TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase(); const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>( const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
normalizedTokenAddress, normalizedTokenAddress,
eventName, eventName,
blockRange, blockRange,

View File

@ -8,15 +8,14 @@ import * as _ from 'lodash';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
/** /**
* This class includes the functionality related to interacting with the ERC721Proxy contract. * This class includes the functionality related to interacting with the ERC721Proxy contract.
*/ */
export class ERC721ProxyWrapper extends ContractWrapper { export class ERC721ProxyWrapper {
public abi: ContractAbi = ERC721Proxy.compilerOutput.abi; public abi: ContractAbi = ERC721Proxy.compilerOutput.abi;
public address: string; public address: string;
private _erc721ProxyContractIfExists?: ERC721ProxyContract; private readonly _web3Wrapper: Web3Wrapper;
private readonly _erc721ProxyContract: ERC721ProxyContract;
/** /**
* Instantiate ERC721ProxyWrapper * Instantiate ERC721ProxyWrapper
* @param web3Wrapper Web3Wrapper instance to use * @param web3Wrapper Web3Wrapper instance to use
@ -25,19 +24,23 @@ export class ERC721ProxyWrapper extends ContractWrapper {
* will default to the known address corresponding to the networkId. * will default to the known address corresponding to the networkId.
*/ */
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId); this._web3Wrapper = web3Wrapper;
this.address = address === undefined ? _getDefaultContractAddresses(networkId).erc721Proxy : address; this.address = address === undefined ? _getDefaultContractAddresses(networkId).erc721Proxy : address;
this._erc721ProxyContract = new ERC721ProxyContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
} }
/** /**
* Get the 4 bytes ID of this asset proxy * Get the 4 bytes ID of this asset proxy
* @return Proxy id * @return Proxy id
*/ */
public async getProxyIdAsync(): Promise<AssetProxyId> { public async getProxyIdAsync(): Promise<AssetProxyId> {
const ERC721ProxyContractInstance = await this._getERC721ProxyContract();
// Note(albrow): Below is a TSLint false positive. Code won't compile if // Note(albrow): Below is a TSLint false positive. Code won't compile if
// you remove the type assertion. // you remove the type assertion.
/* tslint:disable-next-line:no-unnecessary-type-assertion */ /* tslint:disable-next-line:no-unnecessary-type-assertion */
const proxyId = (await ERC721ProxyContractInstance.getProxyId.callAsync()) as AssetProxyId; const proxyId = (await this._erc721ProxyContract.getProxyId.callAsync()) as AssetProxyId;
return proxyId; return proxyId;
} }
/** /**
@ -48,8 +51,7 @@ export class ERC721ProxyWrapper extends ContractWrapper {
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> { public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress); assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase(); const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); const isAuthorized = await this._erc721ProxyContract.authorized.callAsync(normalizedExchangeContractAddress);
const isAuthorized = await ERC721ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress);
return isAuthorized; return isAuthorized;
} }
/** /**
@ -57,20 +59,7 @@ export class ERC721ProxyWrapper extends ContractWrapper {
* @return The list of authorized addresses. * @return The list of authorized addresses.
*/ */
public async getAuthorizedAddressesAsync(): Promise<string[]> { public async getAuthorizedAddressesAsync(): Promise<string[]> {
const ERC721ProxyContractInstance = await this._getERC721ProxyContract(); const authorizedAddresses = await this._erc721ProxyContract.getAuthorizedAddresses.callAsync();
const authorizedAddresses = await ERC721ProxyContractInstance.getAuthorizedAddresses.callAsync();
return authorizedAddresses; return authorizedAddresses;
} }
private _getERC721ProxyContract(): ERC721ProxyContract {
if (this._erc721ProxyContractIfExists !== undefined) {
return this._erc721ProxyContractIfExists;
}
const contractInstance = new ERC721ProxyContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._erc721ProxyContractIfExists = contractInstance;
return this._erc721ProxyContractIfExists;
}
} }

View File

@ -1,4 +1,5 @@
import { ERC721TokenContract, ERC721TokenEventArgs, ERC721TokenEvents } from '@0x/abi-gen-wrappers'; import { ERC721TokenContract, ERC721TokenEventArgs, ERC721TokenEvents } from '@0x/abi-gen-wrappers';
import { SubscriptionManager } from '@0x/base-contract';
import { ERC721Token } from '@0x/contract-artifacts'; import { ERC721Token } from '@0x/contract-artifacts';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
@ -20,7 +21,6 @@ import { assert } from '../utils/assert';
import { constants } from '../utils/constants'; import { constants } from '../utils/constants';
import { utils } from '../utils/utils'; import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
import { ERC721ProxyWrapper } from './erc721_proxy_wrapper'; import { ERC721ProxyWrapper } from './erc721_proxy_wrapper';
/** /**
@ -28,26 +28,27 @@ import { ERC721ProxyWrapper } from './erc721_proxy_wrapper';
* All ERC721 method calls are supported, along with some convenience methods for getting/setting allowances * All ERC721 method calls are supported, along with some convenience methods for getting/setting allowances
* to the 0x ERC721 Proxy smart contract. * to the 0x ERC721 Proxy smart contract.
*/ */
export class ERC721TokenWrapper extends ContractWrapper { export class ERC721TokenWrapper {
public abi: ContractAbi = ERC721Token.compilerOutput.abi; public abi: ContractAbi = ERC721Token.compilerOutput.abi;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _subscriptionManager: SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>;
private readonly _blockPollingIntervalMs?: number;
private readonly _tokenContractsByAddress: { [address: string]: ERC721TokenContract }; private readonly _tokenContractsByAddress: { [address: string]: ERC721TokenContract };
private readonly _erc721ProxyWrapper: ERC721ProxyWrapper; private readonly _erc721ProxyWrapper: ERC721ProxyWrapper;
/** /**
* Instantiate ERC721TokenWrapper * Instantiate ERC721TokenWrapper
* @param web3Wrapper Web3Wrapper instance to use * @param web3Wrapper Web3Wrapper instance to use
* @param networkId Desired networkId
* @param erc721ProxyWrapper The ERC721ProxyWrapper instance to use * @param erc721ProxyWrapper The ERC721ProxyWrapper instance to use
* @param blockPollingIntervalMs The block polling interval to use for active subscriptions
*/ */
constructor( constructor(web3Wrapper: Web3Wrapper, erc721ProxyWrapper: ERC721ProxyWrapper, blockPollingIntervalMs?: number) {
web3Wrapper: Web3Wrapper, this._web3Wrapper = web3Wrapper;
networkId: number,
erc721ProxyWrapper: ERC721ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._tokenContractsByAddress = {}; this._tokenContractsByAddress = {};
this._erc721ProxyWrapper = erc721ProxyWrapper; this._erc721ProxyWrapper = erc721ProxyWrapper;
this._blockPollingIntervalMs = blockPollingIntervalMs;
this._subscriptionManager = new SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>(
ERC721TokenContract.ABI(),
web3Wrapper,
);
} }
/** /**
* Count all NFTs assigned to an owner * Count all NFTs assigned to an owner
@ -398,13 +399,14 @@ export class ERC721TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback); assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase(); const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>( const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
normalizedTokenAddress, normalizedTokenAddress,
eventName, eventName,
indexFilterValues, indexFilterValues,
ERC721Token.compilerOutput.abi, ERC721Token.compilerOutput.abi,
callback, callback,
isVerbose, isVerbose,
this._blockPollingIntervalMs,
); );
return subscriptionToken; return subscriptionToken;
} }
@ -414,13 +416,13 @@ export class ERC721TokenWrapper extends ContractWrapper {
*/ */
public unsubscribe(subscriptionToken: string): void { public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken); assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken); this._subscriptionManager.unsubscribe(subscriptionToken);
} }
/** /**
* Cancels all existing subscriptions * Cancels all existing subscriptions
*/ */
public unsubscribeAll(): void { public unsubscribeAll(): void {
super._unsubscribeAll(); this._subscriptionManager.unsubscribeAll();
} }
/** /**
* Gets historical logs without creating a subscription * Gets historical logs without creating a subscription
@ -442,7 +444,7 @@ export class ERC721TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase(); const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>( const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
normalizedTokenAddress, normalizedTokenAddress,
eventName, eventName,
blockRange, blockRange,

View File

@ -1,4 +1,5 @@
import { WETH9Contract, WETH9EventArgs, WETH9Events } from '@0x/abi-gen-wrappers'; import { WETH9Contract, WETH9EventArgs, WETH9Events } from '@0x/abi-gen-wrappers';
import { SubscriptionManager } from '@0x/base-contract';
import { WETH9 } from '@0x/contract-artifacts'; import { WETH9 } from '@0x/contract-artifacts';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
@ -10,15 +11,17 @@ import { BlockRange, ContractWrappersError, EventCallback, IndexedFilterValues,
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { utils } from '../utils/utils'; import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
import { ERC20TokenWrapper } from './erc20_token_wrapper'; import { ERC20TokenWrapper } from './erc20_token_wrapper';
/** /**
* This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract. * This class includes all the functionality related to interacting with a wrapped Ether ERC20 token contract.
* The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back. * The caller can convert ETH into the equivalent number of wrapped ETH ERC20 tokens and back.
*/ */
export class EtherTokenWrapper extends ContractWrapper { export class EtherTokenWrapper {
public abi: ContractAbi = WETH9.compilerOutput.abi; public abi: ContractAbi = WETH9.compilerOutput.abi;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _subscriptionManager: SubscriptionManager<WETH9EventArgs, WETH9Events>;
private readonly _blockPollingIntervalMs?: number;
private readonly _etherTokenContractsByAddress: { private readonly _etherTokenContractsByAddress: {
[address: string]: WETH9Contract; [address: string]: WETH9Contract;
} = {}; } = {};
@ -26,18 +29,16 @@ export class EtherTokenWrapper extends ContractWrapper {
/** /**
* Instantiate EtherTokenWrapper. * Instantiate EtherTokenWrapper.
* @param web3Wrapper Web3Wrapper instance to use * @param web3Wrapper Web3Wrapper instance to use
* @param networkId Desired networkId
* @param erc20TokenWrapper The ERC20TokenWrapper instance to use * @param erc20TokenWrapper The ERC20TokenWrapper instance to use
* @param blockPollingIntervalMs The block polling interval to use for active subscriptions
*/ */
constructor( constructor(web3Wrapper: Web3Wrapper, erc20TokenWrapper: ERC20TokenWrapper, blockPollingIntervalMs?: number) {
web3Wrapper: Web3Wrapper, this._web3Wrapper = web3Wrapper;
networkId: number,
erc20TokenWrapper: ERC20TokenWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
this._erc20TokenWrapper = erc20TokenWrapper; this._erc20TokenWrapper = erc20TokenWrapper;
this._blockPollingIntervalMs = blockPollingIntervalMs;
this._subscriptionManager = new SubscriptionManager<WETH9EventArgs, WETH9Events>(
WETH9Contract.ABI(),
web3Wrapper,
);
} }
/** /**
* Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens * Deposit ETH into the Wrapped ETH smart contract and issues the equivalent number of wrapped ETH tokens
@ -138,7 +139,7 @@ export class EtherTokenWrapper extends ContractWrapper {
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events); assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._getLogsAsync<ArgsType>( const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
normalizedEtherTokenAddress, normalizedEtherTokenAddress,
eventName, eventName,
blockRange, blockRange,
@ -169,13 +170,14 @@ export class EtherTokenWrapper extends ContractWrapper {
assert.doesBelongToStringEnum('eventName', eventName, WETH9Events); assert.doesBelongToStringEnum('eventName', eventName, WETH9Events);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback); assert.isFunction('callback', callback);
const subscriptionToken = this._subscribe<ArgsType>( const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
normalizedEtherTokenAddress, normalizedEtherTokenAddress,
eventName, eventName,
indexFilterValues, indexFilterValues,
WETH9.compilerOutput.abi, WETH9.compilerOutput.abi,
callback, callback,
isVerbose, isVerbose,
this._blockPollingIntervalMs,
); );
return subscriptionToken; return subscriptionToken;
} }
@ -185,13 +187,13 @@ export class EtherTokenWrapper extends ContractWrapper {
*/ */
public unsubscribe(subscriptionToken: string): void { public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken); assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken); this._subscriptionManager.unsubscribe(subscriptionToken);
} }
/** /**
* Cancels all existing subscriptions * Cancels all existing subscriptions
*/ */
public unsubscribeAll(): void { public unsubscribeAll(): void {
super._unsubscribeAll(); this._subscriptionManager.unsubscribeAll();
} }
private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> { private async _getEtherTokenContractAsync(etherTokenAddress: string): Promise<WETH9Contract> {
let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress]; let etherTokenContract = this._etherTokenContractsByAddress[etherTokenAddress];

View File

@ -37,7 +37,6 @@ import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { decorators } from '../utils/decorators'; import { decorators } from '../utils/decorators';
import { TransactionEncoder } from '../utils/transaction_encoder'; import { TransactionEncoder } from '../utils/transaction_encoder';
import { ContractWrapper } from './contract_wrapper';
import { ERC20TokenWrapper } from './erc20_token_wrapper'; import { ERC20TokenWrapper } from './erc20_token_wrapper';
import { ERC721TokenWrapper } from './erc721_token_wrapper'; import { ERC721TokenWrapper } from './erc721_token_wrapper';
@ -45,11 +44,13 @@ import { ERC721TokenWrapper } from './erc721_token_wrapper';
* This class includes all the functionality related to calling methods, sending transactions and subscribing to * This class includes all the functionality related to calling methods, sending transactions and subscribing to
* events of the 0x V2 Exchange smart contract. * events of the 0x V2 Exchange smart contract.
*/ */
export class ExchangeWrapper extends ContractWrapper { export class ExchangeWrapper {
public abi: ContractAbi = Exchange.compilerOutput.abi; public abi: ContractAbi = Exchange.compilerOutput.abi;
public address: string; public address: string;
public zrxTokenAddress: string; public zrxTokenAddress: string;
private _exchangeContractIfExists?: ExchangeContract; private readonly _web3Wrapper: Web3Wrapper;
private readonly _exchangeContract: ExchangeContract;
private readonly _blockPollingIntervalMs?: number;
private readonly _erc721TokenWrapper: ERC721TokenWrapper; private readonly _erc721TokenWrapper: ERC721TokenWrapper;
private readonly _erc20TokenWrapper: ERC20TokenWrapper; private readonly _erc20TokenWrapper: ERC20TokenWrapper;
/** /**
@ -74,12 +75,18 @@ export class ExchangeWrapper extends ContractWrapper {
zrxTokenAddress?: string, zrxTokenAddress?: string,
blockPollingIntervalMs?: number, blockPollingIntervalMs?: number,
) { ) {
super(web3Wrapper, networkId, blockPollingIntervalMs); this._web3Wrapper = web3Wrapper;
this._erc20TokenWrapper = erc20TokenWrapper; this._erc20TokenWrapper = erc20TokenWrapper;
this._erc721TokenWrapper = erc721TokenWrapper; this._erc721TokenWrapper = erc721TokenWrapper;
this._blockPollingIntervalMs = blockPollingIntervalMs;
this.address = address === undefined ? _getDefaultContractAddresses(networkId).exchange : address; this.address = address === undefined ? _getDefaultContractAddresses(networkId).exchange : address;
this.zrxTokenAddress = this.zrxTokenAddress =
zrxTokenAddress === undefined ? _getDefaultContractAddresses(networkId).zrxToken : zrxTokenAddress; zrxTokenAddress === undefined ? _getDefaultContractAddresses(networkId).zrxToken : zrxTokenAddress;
this._exchangeContract = new ExchangeContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
} }
/** /**
* Retrieve the address of an asset proxy by signature. * Retrieve the address of an asset proxy by signature.
@ -90,10 +97,13 @@ export class ExchangeWrapper extends ContractWrapper {
public async getAssetProxyBySignatureAsync(proxyId: AssetProxyId, methodOpts: MethodOpts = {}): Promise<string> { public async getAssetProxyBySignatureAsync(proxyId: AssetProxyId, methodOpts: MethodOpts = {}): Promise<string> {
assert.doesBelongToStringEnum('proxyId', proxyId, AssetProxyId); assert.doesBelongToStringEnum('proxyId', proxyId, AssetProxyId);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const exchangeContract = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const assetProxy = await exchangeContract.getAssetProxy.callAsync(proxyId, callData, methodOpts.defaultBlock); const assetProxy = await this._exchangeContract.getAssetProxy.callAsync(
proxyId,
callData,
methodOpts.defaultBlock,
);
return assetProxy; return assetProxy;
} }
/** /**
@ -105,10 +115,9 @@ export class ExchangeWrapper extends ContractWrapper {
public async getFilledTakerAssetAmountAsync(orderHash: string, methodOpts: MethodOpts = {}): Promise<BigNumber> { public async getFilledTakerAssetAmountAsync(orderHash: string, methodOpts: MethodOpts = {}): Promise<BigNumber> {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const exchangeContract = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const filledTakerAssetAmountInBaseUnits = await exchangeContract.filled.callAsync( const filledTakerAssetAmountInBaseUnits = await this._exchangeContract.filled.callAsync(
orderHash, orderHash,
callData, callData,
methodOpts.defaultBlock, methodOpts.defaultBlock,
@ -122,10 +131,8 @@ export class ExchangeWrapper extends ContractWrapper {
*/ */
public async getVersionAsync(methodOpts: MethodOpts = {}): Promise<string> { public async getVersionAsync(methodOpts: MethodOpts = {}): Promise<string> {
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const exchangeContract = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const version = await exchangeContract.VERSION.callAsync(callData, methodOpts.defaultBlock); const version = await this._exchangeContract.VERSION.callAsync(callData, methodOpts.defaultBlock);
return version; return version;
} }
/** /**
@ -144,10 +151,8 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isETHAddressHex('makerAddress', makerAddress); assert.isETHAddressHex('makerAddress', makerAddress);
assert.isETHAddressHex('senderAddress', senderAddress); assert.isETHAddressHex('senderAddress', senderAddress);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const exchangeContract = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const orderEpoch = await exchangeContract.orderEpoch.callAsync( const orderEpoch = await this._exchangeContract.orderEpoch.callAsync(
makerAddress, makerAddress,
senderAddress, senderAddress,
callData, callData,
@ -164,10 +169,12 @@ export class ExchangeWrapper extends ContractWrapper {
public async isCancelledAsync(orderHash: string, methodOpts: MethodOpts = {}): Promise<boolean> { public async isCancelledAsync(orderHash: string, methodOpts: MethodOpts = {}): Promise<boolean> {
assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema); assert.doesConformToSchema('orderHash', orderHash, schemas.orderHashSchema);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const exchangeContract = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const isCancelled = await exchangeContract.cancelled.callAsync(orderHash, callData, methodOpts.defaultBlock); const isCancelled = await this._exchangeContract.cancelled.callAsync(
orderHash,
callData,
methodOpts.defaultBlock,
);
return isCancelled; return isCancelled;
} }
/** /**
@ -192,9 +199,8 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.fillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, { await this._exchangeContract.fillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, {
from: normalizedTakerAddress, from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
@ -202,7 +208,7 @@ export class ExchangeWrapper extends ContractWrapper {
}); });
} }
const txHash = await exchangeInstance.fillOrder.sendTransactionAsync( const txHash = await this._exchangeContract.fillOrder.sendTransactionAsync(
signedOrder, signedOrder,
takerAssetFillAmount, takerAssetFillAmount,
signedOrder.signature, signedOrder.signature,
@ -237,9 +243,8 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.fillOrderNoThrow.callAsync( await this._exchangeContract.fillOrderNoThrow.callAsync(
signedOrder, signedOrder,
takerAssetFillAmount, takerAssetFillAmount,
signedOrder.signature, signedOrder.signature,
@ -251,7 +256,7 @@ export class ExchangeWrapper extends ContractWrapper {
}, },
); );
} }
const txHash = await exchangeInstance.fillOrderNoThrow.sendTransactionAsync( const txHash = await this._exchangeContract.fillOrderNoThrow.sendTransactionAsync(
signedOrder, signedOrder,
takerAssetFillAmount, takerAssetFillAmount,
signedOrder.signature, signedOrder.signature,
@ -287,16 +292,20 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.fillOrKillOrder.callAsync(signedOrder, takerAssetFillAmount, signedOrder.signature, { await this._exchangeContract.fillOrKillOrder.callAsync(
from: normalizedTakerAddress, signedOrder,
gas: orderTransactionOpts.gasLimit, takerAssetFillAmount,
gasPrice: orderTransactionOpts.gasPrice, signedOrder.signature,
nonce: orderTransactionOpts.nonce, {
}); from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce,
},
);
} }
const txHash = await exchangeInstance.fillOrKillOrder.sendTransactionAsync( const txHash = await this._exchangeContract.fillOrKillOrder.sendTransactionAsync(
signedOrder, signedOrder,
takerAssetFillAmount, takerAssetFillAmount,
signedOrder.signature, signedOrder.signature,
@ -338,16 +347,15 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedSenderAddress = senderAddress.toLowerCase(); const normalizedSenderAddress = senderAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.executeTransaction.callAsync(salt, signerAddress, data, signature, { await this._exchangeContract.executeTransaction.callAsync(salt, signerAddress, data, signature, {
from: normalizedSenderAddress, from: normalizedSenderAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.executeTransaction.sendTransactionAsync( const txHash = await this._exchangeContract.executeTransaction.sendTransactionAsync(
salt, salt,
signerAddress, signerAddress,
data, data,
@ -385,17 +393,16 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.batchFillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, { await this._exchangeContract.batchFillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, {
from: normalizedTakerAddress, from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.batchFillOrders.sendTransactionAsync( const txHash = await this._exchangeContract.batchFillOrders.sendTransactionAsync(
signedOrders, signedOrders,
takerAssetFillAmounts, takerAssetFillAmounts,
signatures, signatures,
@ -430,17 +437,16 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.marketBuyOrders.callAsync(signedOrders, makerAssetFillAmount, signatures, { await this._exchangeContract.marketBuyOrders.callAsync(signedOrders, makerAssetFillAmount, signatures, {
from: normalizedTakerAddress, from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.marketBuyOrders.sendTransactionAsync( const txHash = await this._exchangeContract.marketBuyOrders.sendTransactionAsync(
signedOrders, signedOrders,
makerAssetFillAmount, makerAssetFillAmount,
signatures, signatures,
@ -475,17 +481,16 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.marketSellOrders.callAsync(signedOrders, takerAssetFillAmount, signatures, { await this._exchangeContract.marketSellOrders.callAsync(signedOrders, takerAssetFillAmount, signatures, {
from: normalizedTakerAddress, from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.marketSellOrders.sendTransactionAsync( const txHash = await this._exchangeContract.marketSellOrders.sendTransactionAsync(
signedOrders, signedOrders,
takerAssetFillAmount, takerAssetFillAmount,
signatures, signatures,
@ -520,17 +525,21 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.marketBuyOrdersNoThrow.callAsync(signedOrders, makerAssetFillAmount, signatures, { await this._exchangeContract.marketBuyOrdersNoThrow.callAsync(
from: normalizedTakerAddress, signedOrders,
gas: orderTransactionOpts.gasLimit, makerAssetFillAmount,
gasPrice: orderTransactionOpts.gasPrice, signatures,
nonce: orderTransactionOpts.nonce, {
}); from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce,
},
);
} }
const txHash = await exchangeInstance.marketBuyOrdersNoThrow.sendTransactionAsync( const txHash = await this._exchangeContract.marketBuyOrdersNoThrow.sendTransactionAsync(
signedOrders, signedOrders,
makerAssetFillAmount, makerAssetFillAmount,
signatures, signatures,
@ -565,17 +574,21 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.marketSellOrdersNoThrow.callAsync(signedOrders, takerAssetFillAmount, signatures, { await this._exchangeContract.marketSellOrdersNoThrow.callAsync(
from: normalizedTakerAddress, signedOrders,
gas: orderTransactionOpts.gasLimit, takerAssetFillAmount,
gasPrice: orderTransactionOpts.gasPrice, signatures,
nonce: orderTransactionOpts.nonce, {
}); from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce,
},
);
} }
const txHash = await exchangeInstance.marketSellOrdersNoThrow.sendTransactionAsync( const txHash = await this._exchangeContract.marketSellOrdersNoThrow.sendTransactionAsync(
signedOrders, signedOrders,
takerAssetFillAmount, takerAssetFillAmount,
signatures, signatures,
@ -612,17 +625,21 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.batchFillOrdersNoThrow.callAsync(signedOrders, takerAssetFillAmounts, signatures, { await this._exchangeContract.batchFillOrdersNoThrow.callAsync(
from: normalizedTakerAddress, signedOrders,
gas: orderTransactionOpts.gasLimit, takerAssetFillAmounts,
gasPrice: orderTransactionOpts.gasPrice, signatures,
nonce: orderTransactionOpts.nonce, {
}); from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce,
},
);
} }
const txHash = await exchangeInstance.batchFillOrdersNoThrow.sendTransactionAsync( const txHash = await this._exchangeContract.batchFillOrdersNoThrow.sendTransactionAsync(
signedOrders, signedOrders,
takerAssetFillAmounts, takerAssetFillAmounts,
signatures, signatures,
@ -659,17 +676,21 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = takerAddress.toLowerCase(); const normalizedTakerAddress = takerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const signatures = _.map(signedOrders, signedOrder => signedOrder.signature); const signatures = _.map(signedOrders, signedOrder => signedOrder.signature);
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.batchFillOrKillOrders.callAsync(signedOrders, takerAssetFillAmounts, signatures, { await this._exchangeContract.batchFillOrKillOrders.callAsync(
from: normalizedTakerAddress, signedOrders,
gas: orderTransactionOpts.gasLimit, takerAssetFillAmounts,
gasPrice: orderTransactionOpts.gasPrice, signatures,
nonce: orderTransactionOpts.nonce, {
}); from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce,
},
);
} }
const txHash = await exchangeInstance.batchFillOrKillOrders.sendTransactionAsync( const txHash = await this._exchangeContract.batchFillOrKillOrders.sendTransactionAsync(
signedOrders, signedOrders,
takerAssetFillAmounts, takerAssetFillAmounts,
signatures, signatures,
@ -700,16 +721,15 @@ export class ExchangeWrapper extends ContractWrapper {
await assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper); await assert.isSenderAddressAsync('makerAddress', makerAddress, this._web3Wrapper);
const normalizedMakerAddress = makerAddress.toLowerCase(); const normalizedMakerAddress = makerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.batchCancelOrders.callAsync(orders, { await this._exchangeContract.batchCancelOrders.callAsync(orders, {
from: normalizedMakerAddress, from: normalizedMakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.batchCancelOrders.sendTransactionAsync(orders, { const txHash = await this._exchangeContract.batchCancelOrders.sendTransactionAsync(orders, {
from: normalizedMakerAddress, from: normalizedMakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
@ -746,9 +766,8 @@ export class ExchangeWrapper extends ContractWrapper {
) { ) {
throw new Error(ExchangeWrapperError.AssetDataMismatch); throw new Error(ExchangeWrapperError.AssetDataMismatch);
} }
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.matchOrders.callAsync( await this._exchangeContract.matchOrders.callAsync(
leftSignedOrder, leftSignedOrder,
rightSignedOrder, rightSignedOrder,
leftSignedOrder.signature, leftSignedOrder.signature,
@ -761,7 +780,7 @@ export class ExchangeWrapper extends ContractWrapper {
}, },
); );
} }
const txHash = await exchangeInstance.matchOrders.sendTransactionAsync( const txHash = await this._exchangeContract.matchOrders.sendTransactionAsync(
leftSignedOrder, leftSignedOrder,
rightSignedOrder, rightSignedOrder,
leftSignedOrder.signature, leftSignedOrder.signature,
@ -799,16 +818,15 @@ export class ExchangeWrapper extends ContractWrapper {
await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper); await assert.isSenderAddressAsync('senderAddress', senderAddress, this._web3Wrapper);
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedTakerAddress = senderAddress.toLowerCase(); const normalizedTakerAddress = senderAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.preSign.callAsync(hash, signerAddress, signature, { await this._exchangeContract.preSign.callAsync(hash, signerAddress, signature, {
from: normalizedTakerAddress, from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.preSign.sendTransactionAsync(hash, signerAddress, signature, { const txHash = await this._exchangeContract.preSign.sendTransactionAsync(hash, signerAddress, signature, {
from: normalizedTakerAddress, from: normalizedTakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
@ -835,9 +853,8 @@ export class ExchangeWrapper extends ContractWrapper {
assert.isETHAddressHex('signerAddress', signerAddress); assert.isETHAddressHex('signerAddress', signerAddress);
assert.isHexString('signature', signature); assert.isHexString('signature', signature);
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
const exchangeInstance = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const isValidSignature = await exchangeInstance.isValidSignature.callAsync( const isValidSignature = await this._exchangeContract.isValidSignature.callAsync(
hash, hash,
signerAddress, signerAddress,
signature, signature,
@ -866,9 +883,8 @@ export class ExchangeWrapper extends ContractWrapper {
} }
const normalizedSignerAddress = signerAddress.toLowerCase(); const normalizedSignerAddress = signerAddress.toLowerCase();
const normalizedValidatorAddress = validatorAddress.toLowerCase(); const normalizedValidatorAddress = validatorAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const isValidSignature = await exchangeInstance.allowedValidators.callAsync( const isValidSignature = await this._exchangeContract.allowedValidators.callAsync(
normalizedSignerAddress, normalizedSignerAddress,
normalizedValidatorAddress, normalizedValidatorAddress,
callData, callData,
@ -890,10 +906,9 @@ export class ExchangeWrapper extends ContractWrapper {
if (methodOpts !== undefined) { if (methodOpts !== undefined) {
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
} }
const exchangeInstance = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const isPreSigned = await exchangeInstance.preSigned.callAsync( const isPreSigned = await this._exchangeContract.preSigned.callAsync(
hash, hash,
signerAddress, signerAddress,
callData, callData,
@ -914,9 +929,8 @@ export class ExchangeWrapper extends ContractWrapper {
if (methodOpts !== undefined) { if (methodOpts !== undefined) {
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
} }
const exchangeInstance = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const isExecuted = await exchangeInstance.transactions.callAsync( const isExecuted = await this._exchangeContract.transactions.callAsync(
transactionHash, transactionHash,
callData, callData,
methodOpts.defaultBlock, methodOpts.defaultBlock,
@ -935,9 +949,8 @@ export class ExchangeWrapper extends ContractWrapper {
if (methodOpts !== undefined) { if (methodOpts !== undefined) {
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
} }
const exchangeInstance = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const orderInfo = await exchangeInstance.getOrderInfo.callAsync(order, callData, methodOpts.defaultBlock); const orderInfo = await this._exchangeContract.getOrderInfo.callAsync(order, callData, methodOpts.defaultBlock);
return orderInfo; return orderInfo;
} }
/** /**
@ -955,9 +968,12 @@ export class ExchangeWrapper extends ContractWrapper {
if (methodOpts !== undefined) { if (methodOpts !== undefined) {
assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema); assert.doesConformToSchema('methodOpts', methodOpts, methodOptsSchema);
} }
const exchangeInstance = await this._getExchangeContractAsync();
const callData = {}; const callData = {};
const ordersInfo = await exchangeInstance.getOrdersInfo.callAsync(orders, callData, methodOpts.defaultBlock); const ordersInfo = await this._exchangeContract.getOrdersInfo.callAsync(
orders,
callData,
methodOpts.defaultBlock,
);
return ordersInfo; return ordersInfo;
} }
/** /**
@ -976,16 +992,15 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedMakerAddress = order.makerAddress.toLowerCase(); const normalizedMakerAddress = order.makerAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.cancelOrder.callAsync(order, { await this._exchangeContract.cancelOrder.callAsync(order, {
from: normalizedMakerAddress, from: normalizedMakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.cancelOrder.sendTransactionAsync(order, { const txHash = await this._exchangeContract.cancelOrder.sendTransactionAsync(order, {
from: normalizedMakerAddress, from: normalizedMakerAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
@ -1014,16 +1029,15 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedSenderAddress = senderAddress.toLowerCase(); const normalizedSenderAddress = senderAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.setSignatureValidatorApproval.callAsync(validatorAddress, isApproved, { await this._exchangeContract.setSignatureValidatorApproval.callAsync(validatorAddress, isApproved, {
from: normalizedSenderAddress, from: normalizedSenderAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.setSignatureValidatorApproval.sendTransactionAsync( const txHash = await this._exchangeContract.setSignatureValidatorApproval.sendTransactionAsync(
validatorAddress, validatorAddress,
isApproved, isApproved,
{ {
@ -1054,16 +1068,15 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]); assert.doesConformToSchema('orderTransactionOpts', orderTransactionOpts, orderTxOptsSchema, [txOptsSchema]);
const normalizedSenderAddress = senderAddress.toLowerCase(); const normalizedSenderAddress = senderAddress.toLowerCase();
const exchangeInstance = await this._getExchangeContractAsync();
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await exchangeInstance.cancelOrdersUpTo.callAsync(targetOrderEpoch, { await this._exchangeContract.cancelOrdersUpTo.callAsync(targetOrderEpoch, {
from: normalizedSenderAddress, from: normalizedSenderAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
nonce: orderTransactionOpts.nonce, nonce: orderTransactionOpts.nonce,
}); });
} }
const txHash = await exchangeInstance.cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, { const txHash = await this._exchangeContract.cancelOrdersUpTo.sendTransactionAsync(targetOrderEpoch, {
from: normalizedSenderAddress, from: normalizedSenderAddress,
gas: orderTransactionOpts.gasLimit, gas: orderTransactionOpts.gasLimit,
gasPrice: orderTransactionOpts.gasPrice, gasPrice: orderTransactionOpts.gasPrice,
@ -1089,13 +1102,12 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback); assert.isFunction('callback', callback);
const subscriptionToken = this._subscribe<ArgsType>( const subscriptionToken = this._exchangeContract.subscribe<ArgsType>(
this.address,
eventName, eventName,
indexFilterValues, indexFilterValues,
Exchange.compilerOutput.abi,
callback, callback,
isVerbose, isVerbose,
this._blockPollingIntervalMs,
); );
return subscriptionToken; return subscriptionToken;
} }
@ -1104,13 +1116,13 @@ export class ExchangeWrapper extends ContractWrapper {
* @param subscriptionToken Subscription token returned by `subscribe()` * @param subscriptionToken Subscription token returned by `subscribe()`
*/ */
public unsubscribe(subscriptionToken: string): void { public unsubscribe(subscriptionToken: string): void {
this._unsubscribe(subscriptionToken); this._exchangeContract.unsubscribe(subscriptionToken);
} }
/** /**
* Cancels all existing subscriptions * Cancels all existing subscriptions
*/ */
public unsubscribeAll(): void { public unsubscribeAll(): void {
super._unsubscribeAll(); this._exchangeContract.unsubscribeAll();
} }
/** /**
* Gets historical logs without creating a subscription * Gets historical logs without creating a subscription
@ -1128,13 +1140,7 @@ export class ExchangeWrapper extends ContractWrapper {
assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents); assert.doesBelongToStringEnum('eventName', eventName, ExchangeEvents);
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema); assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema); assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const logs = await this._getLogsAsync<ArgsType>( const logs = await this._exchangeContract.getLogsAsync<ArgsType>(eventName, blockRange, indexFilterValues);
this.address,
eventName,
blockRange,
indexFilterValues,
Exchange.compilerOutput.abi,
);
return logs; return logs;
} }
/** /**
@ -1260,21 +1266,7 @@ export class ExchangeWrapper extends ContractWrapper {
* @return TransactionEncoder * @return TransactionEncoder
*/ */
public async transactionEncoderAsync(): Promise<TransactionEncoder> { public async transactionEncoderAsync(): Promise<TransactionEncoder> {
const exchangeInstance = await this._getExchangeContractAsync(); const encoder = new TransactionEncoder(this._exchangeContract);
const encoder = new TransactionEncoder(exchangeInstance);
return encoder; return encoder;
} }
// tslint:enable:no-unused-variable
private async _getExchangeContractAsync(): Promise<ExchangeContract> {
if (this._exchangeContractIfExists !== undefined) {
return this._exchangeContractIfExists;
}
const contractInstance = new ExchangeContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._exchangeContractIfExists = contractInstance;
return this._exchangeContractIfExists;
}
} // tslint:disable:max-file-line-count } // tslint:disable:max-file-line-count

View File

@ -17,17 +17,16 @@ import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { decorators } from '../utils/decorators'; import { decorators } from '../utils/decorators';
import { utils } from '../utils/utils'; import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
/** /**
* This class includes the functionality related to interacting with the Forwarder contract. * This class includes the functionality related to interacting with the Forwarder contract.
*/ */
export class ForwarderWrapper extends ContractWrapper { export class ForwarderWrapper {
public abi: ContractAbi = Forwarder.compilerOutput.abi; public abi: ContractAbi = Forwarder.compilerOutput.abi;
public address: string; public address: string;
public zrxTokenAddress: string; public zrxTokenAddress: string;
public etherTokenAddress: string; public etherTokenAddress: string;
private _forwarderContractIfExists?: ForwarderContract; private readonly _web3Wrapper: Web3Wrapper;
private readonly _forwarderContract: ForwarderContract;
/** /**
* Instantiate ForwarderWrapper * Instantiate ForwarderWrapper
@ -49,12 +48,17 @@ export class ForwarderWrapper extends ContractWrapper {
zrxTokenAddress?: string, zrxTokenAddress?: string,
etherTokenAddress?: string, etherTokenAddress?: string,
) { ) {
super(web3Wrapper, networkId); this._web3Wrapper = web3Wrapper;
this.address = address === undefined ? _getDefaultContractAddresses(networkId).exchange : address; this.address = address === undefined ? _getDefaultContractAddresses(networkId).exchange : address;
this.zrxTokenAddress = this.zrxTokenAddress =
zrxTokenAddress === undefined ? _getDefaultContractAddresses(networkId).zrxToken : zrxTokenAddress; zrxTokenAddress === undefined ? _getDefaultContractAddresses(networkId).zrxToken : zrxTokenAddress;
this.etherTokenAddress = this.etherTokenAddress =
etherTokenAddress === undefined ? _getDefaultContractAddresses(networkId).etherToken : etherTokenAddress; etherTokenAddress === undefined ? _getDefaultContractAddresses(networkId).etherToken : etherTokenAddress;
this._forwarderContract = new ForwarderContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
} }
/** /**
* Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value. * Purchases as much of orders' makerAssets as possible by selling up to 95% of transaction's ETH value.
@ -106,11 +110,9 @@ export class ForwarderWrapper extends ContractWrapper {
// compile signatures // compile signatures
const signatures = _.map(optimizedMarketOrders, order => order.signature); const signatures = _.map(optimizedMarketOrders, order => order.signature);
const feeSignatures = _.map(optimizedFeeOrders, order => order.signature); const feeSignatures = _.map(optimizedFeeOrders, order => order.signature);
// get contract
const forwarderContractInstance = await this._getForwarderContractAsync();
// validate transaction // validate transaction
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await forwarderContractInstance.marketSellOrdersWithEth.callAsync( await this._forwarderContract.marketSellOrdersWithEth.callAsync(
optimizedMarketOrders, optimizedMarketOrders,
signatures, signatures,
optimizedFeeOrders, optimizedFeeOrders,
@ -127,7 +129,7 @@ export class ForwarderWrapper extends ContractWrapper {
); );
} }
// send transaction // send transaction
const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync( const txHash = await this._forwarderContract.marketSellOrdersWithEth.sendTransactionAsync(
optimizedMarketOrders, optimizedMarketOrders,
signatures, signatures,
optimizedFeeOrders, optimizedFeeOrders,
@ -196,11 +198,9 @@ export class ForwarderWrapper extends ContractWrapper {
// compile signatures // compile signatures
const signatures = _.map(optimizedMarketOrders, order => order.signature); const signatures = _.map(optimizedMarketOrders, order => order.signature);
const feeSignatures = _.map(optimizedFeeOrders, order => order.signature); const feeSignatures = _.map(optimizedFeeOrders, order => order.signature);
// get contract
const forwarderContractInstance = await this._getForwarderContractAsync();
// validate transaction // validate transaction
if (orderTransactionOpts.shouldValidate) { if (orderTransactionOpts.shouldValidate) {
await forwarderContractInstance.marketBuyOrdersWithEth.callAsync( await this._forwarderContract.marketBuyOrdersWithEth.callAsync(
optimizedMarketOrders, optimizedMarketOrders,
makerAssetFillAmount, makerAssetFillAmount,
signatures, signatures,
@ -218,7 +218,7 @@ export class ForwarderWrapper extends ContractWrapper {
); );
} }
// send transaction // send transaction
const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync( const txHash = await this._forwarderContract.marketBuyOrdersWithEth.sendTransactionAsync(
optimizedMarketOrders, optimizedMarketOrders,
makerAssetFillAmount, makerAssetFillAmount,
signatures, signatures,
@ -236,16 +236,4 @@ export class ForwarderWrapper extends ContractWrapper {
); );
return txHash; return txHash;
} }
private async _getForwarderContractAsync(): Promise<ForwarderContract> {
if (this._forwarderContractIfExists !== undefined) {
return this._forwarderContractIfExists;
}
const contractInstance = new ForwarderContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._forwarderContractIfExists = contractInstance;
return this._forwarderContractIfExists;
}
} }

View File

@ -11,15 +11,14 @@ import { BalanceAndAllowance, OrderAndTraderInfo, TraderInfo } from '../types';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { _getDefaultContractAddresses } from '../utils/contract_addresses'; import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
/** /**
* This class includes the functionality related to interacting with the OrderValidator contract. * This class includes the functionality related to interacting with the OrderValidator contract.
*/ */
export class OrderValidatorWrapper extends ContractWrapper { export class OrderValidatorWrapper {
public abi: ContractAbi = OrderValidator.compilerOutput.abi; public abi: ContractAbi = OrderValidator.compilerOutput.abi;
public address: string; public address: string;
private _orderValidatorContractIfExists?: OrderValidatorContract; private readonly _web3Wrapper: Web3Wrapper;
private readonly _orderValidatorContract: OrderValidatorContract;
/** /**
* Instantiate OrderValidatorWrapper * Instantiate OrderValidatorWrapper
* @param web3Wrapper Web3Wrapper instance to use. * @param web3Wrapper Web3Wrapper instance to use.
@ -28,8 +27,13 @@ export class OrderValidatorWrapper extends ContractWrapper {
* will default to the known address corresponding to the networkId. * will default to the known address corresponding to the networkId.
*/ */
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) { constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId); this._web3Wrapper = web3Wrapper;
this.address = address === undefined ? _getDefaultContractAddresses(networkId).orderValidator : address; this.address = address === undefined ? _getDefaultContractAddresses(networkId).orderValidator : address;
this._orderValidatorContract = new OrderValidatorContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
} }
/** /**
* Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address * Get an object conforming to OrderAndTraderInfo containing on-chain information of the provided order and address
@ -40,8 +44,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> { public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> {
assert.doesConformToSchema('order', order, schemas.signedOrderSchema); assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
assert.isETHAddressHex('takerAddress', takerAddress); assert.isETHAddressHex('takerAddress', takerAddress);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const orderAndTraderInfo = await this._orderValidatorContract.getOrderAndTraderInfo.callAsync(
const orderAndTraderInfo = await OrderValidatorContractInstance.getOrderAndTraderInfo.callAsync(
order, order,
takerAddress, takerAddress,
); );
@ -66,8 +69,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress), assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
); );
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length'); assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const ordersAndTradersInfo = await this._orderValidatorContract.getOrdersAndTradersInfo.callAsync(
const ordersAndTradersInfo = await OrderValidatorContractInstance.getOrdersAndTradersInfo.callAsync(
orders, orders,
takerAddresses, takerAddresses,
); );
@ -91,8 +93,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> { public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> {
assert.doesConformToSchema('order', order, schemas.signedOrderSchema); assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
assert.isETHAddressHex('takerAddress', takerAddress); assert.isETHAddressHex('takerAddress', takerAddress);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const result = await this._orderValidatorContract.getTraderInfo.callAsync(order, takerAddress);
const result = await OrderValidatorContractInstance.getTraderInfo.callAsync(order, takerAddress);
return result; return result;
} }
/** /**
@ -107,8 +108,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress), assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
); );
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length'); assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const result = await this._orderValidatorContract.getTradersInfo.callAsync(orders, takerAddresses);
const result = await OrderValidatorContractInstance.getTradersInfo.callAsync(orders, takerAddresses);
return result; return result;
} }
/** /**
@ -120,8 +120,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> { public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> {
assert.isETHAddressHex('address', address); assert.isETHAddressHex('address', address);
assert.isHexString('assetData', assetData); assert.isHexString('assetData', assetData);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const balanceAndAllowance = await this._orderValidatorContract.getBalanceAndAllowance.callAsync(
const balanceAndAllowance = await OrderValidatorContractInstance.getBalanceAndAllowance.callAsync(
address, address,
assetData, assetData,
); );
@ -140,8 +139,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> { public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> {
assert.isETHAddressHex('address', address); assert.isETHAddressHex('address', address);
_.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData)); _.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData));
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const balancesAndAllowances = await this._orderValidatorContract.getBalancesAndAllowances.callAsync(
const balancesAndAllowances = await OrderValidatorContractInstance.getBalancesAndAllowances.callAsync(
address, address,
assetDatas, assetDatas,
); );
@ -165,20 +163,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> { public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> {
assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('tokenId', tokenId); assert.isBigNumber('tokenId', tokenId);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync(); const result = await this._orderValidatorContract.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
return result; return result;
} }
private async _getOrderValidatorContractAsync(): Promise<OrderValidatorContract> {
if (this._orderValidatorContractIfExists !== undefined) {
return this._orderValidatorContractIfExists;
}
const contractInstance = new OrderValidatorContract(
this.address,
this._web3Wrapper.getProvider(),
this._web3Wrapper.getContractDefaults(),
);
this._orderValidatorContractIfExists = contractInstance;
return this._orderValidatorContractIfExists;
}
} }

216
yarn.lock

File diff suppressed because it is too large Load Diff