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 _ from 'lodash';
import { ERC1155ProxyWrapper, ERC721ProxyContract } from '../src';
import { ERC1155ProxyContract, ERC1155ProxyWrapper } from '../src';
chaiSetup.configure();
const expect = chai.expect;
@ -51,7 +51,7 @@ describe('ERC1155Proxy', () => {
let receiver: string;
let receiverContract: string;
// contracts & wrappers
let erc1155Proxy: ERC721ProxyContract;
let erc1155Proxy: ERC1155ProxyContract;
let erc1155Receiver: DummyERC1155ReceiverContract;
let erc1155ProxyWrapper: ERC1155ProxyWrapper;
let erc1155Contract: ERC1155MintableContract;

View File

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

View File

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

View File

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

View File

@ -3,14 +3,17 @@ import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { MultiSigWalletContract } from '../../generated-wrappers/multi_sig_wallet';
import { MultiSigWalletContract, MultiSigWalletWithTimeLockContract } from '../../src';
import { artifacts } from '../../src/artifacts';
export class MultiSigWrapper {
private readonly _multiSig: MultiSigWalletContract;
private readonly _multiSig: MultiSigWalletContract | MultiSigWalletWithTimeLockContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _logDecoder: LogDecoder;
constructor(multiSigContract: MultiSigWalletContract, provider: Web3ProviderEngine) {
constructor(
multiSigContract: MultiSigWalletContract | MultiSigWalletWithTimeLockContract,
provider: Web3ProviderEngine,
) {
this._multiSig = multiSigContract;
this._web3Wrapper = new Web3Wrapper(provider);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -9,7 +13,8 @@ import {
CallData,
ContractAbi,
ContractArtifact,
DecodedLogArgs,
DecodedLogArgs,{{#if events}}
LogWithDecodedArgs,{{/if}}
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -53,7 +58,8 @@ export class {{contractName}}Contract extends BaseContract {
{{> tx contractName=../contractName}}
{{/this.constant}}
{{/each}}
public static async deployFrom0xArtifactAsync(
{{#if events}}private readonly _subscriptionManager: SubscriptionManager<{{contractName}}EventArgs, {{contractName}}Events>;
{{/if}}public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
txDefaults: Partial<TxData>,
@ -138,10 +144,82 @@ export class {{contractName}}Contract extends BaseContract {
{{/each}}
] as ContractAbi;
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>) {
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,
"version": "5.0.3",

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -2083,6 +2091,7 @@ export class AssetProxyOwnerContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<AssetProxyOwnerEventArgs, AssetProxyOwnerEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -2861,9 +2870,81 @@ export class AssetProxyOwnerContract extends BaseContract {
] as ContractAbi;
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>) {
super('AssetProxyOwner', AssetProxyOwnerContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -192,6 +200,7 @@ export class CoordinatorRegistryContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<CoordinatorRegistryEventArgs, CoordinatorRegistryEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -313,9 +322,81 @@ export class CoordinatorRegistryContract extends BaseContract {
] as ContractAbi;
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>) {
super('CoordinatorRegistry', CoordinatorRegistryContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -1102,6 +1110,7 @@ export class DummyERC20TokenContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<DummyERC20TokenEventArgs, DummyERC20TokenEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -1497,9 +1506,81 @@ export class DummyERC20TokenContract extends BaseContract {
] as ContractAbi;
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>) {
super('DummyERC20Token', DummyERC20TokenContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -1432,6 +1440,7 @@ export class DummyERC721TokenContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<DummyERC721TokenEventArgs, DummyERC721TokenEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -1866,9 +1875,81 @@ export class DummyERC721TokenContract extends BaseContract {
] as ContractAbi;
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>) {
super('DummyERC721Token', DummyERC721TokenContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -691,6 +699,7 @@ export class ERC20ProxyContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<ERC20ProxyEventArgs, ERC20ProxyEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -933,9 +942,81 @@ export class ERC20ProxyContract extends BaseContract {
] as ContractAbi;
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>) {
super('ERC20Proxy', ERC20ProxyContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -579,6 +587,7 @@ export class ERC20TokenContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -813,9 +822,81 @@ export class ERC20TokenContract extends BaseContract {
] as ContractAbi;
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>) {
super('ERC20Token', ERC20TokenContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -691,6 +699,7 @@ export class ERC721ProxyContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<ERC721ProxyEventArgs, ERC721ProxyEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -933,9 +942,81 @@ export class ERC721ProxyContract extends BaseContract {
] as ContractAbi;
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>) {
super('ERC721Proxy', ERC721ProxyContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -972,6 +980,7 @@ export class ERC721TokenContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -1286,9 +1295,81 @@ export class ERC721TokenContract extends BaseContract {
] as ContractAbi;
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>) {
super('ERC721Token', ERC721TokenContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -4555,6 +4563,7 @@ export class ExchangeContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<ExchangeEventArgs, ExchangeEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -6591,9 +6600,81 @@ export class ExchangeContract extends BaseContract {
] as ContractAbi;
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>) {
super('Exchange', ExchangeContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -888,6 +896,7 @@ export class MultiAssetProxyContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<MultiAssetProxyEventArgs, MultiAssetProxyEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -1200,9 +1209,81 @@ export class MultiAssetProxyContract extends BaseContract {
] as ContractAbi;
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>) {
super('MultiAssetProxy', MultiAssetProxyContract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -884,6 +892,7 @@ export class WETH9Contract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<WETH9EventArgs, WETH9Events>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -1226,9 +1235,81 @@ export class WETH9Contract extends BaseContract {
] as ContractAbi;
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>) {
super('WETH9', WETH9Contract.ABI(), address, supportedProvider, txDefaults);
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:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -693,6 +701,7 @@ export class ZRXTokenContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<ZRXTokenEventArgs, ZRXTokenEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -966,9 +975,81 @@ export class ZRXTokenContract extends BaseContract {
] as ContractAbi;
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>) {
super('ZRXToken', ZRXTokenContract.ABI(), address, supportedProvider, txDefaults);
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",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
"sinon": "^4.0.0",
"solhint": "^1.4.1",
"tslint": "5.11.0",
"typescript": "3.0.1"

View File

@ -197,6 +197,39 @@ class AbiGenDummy(BaseContractWrapper):
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(
self,
_hash: bytes,
@ -595,6 +628,19 @@ class AbiGenDummy(BaseContractWrapper):
tx_params=tx_params,
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(
self, tx_hash: Union[HexBytes, bytes]
) -> Tuple[AttributeDict]:
@ -613,7 +659,7 @@ class AbiGenDummy(BaseContractWrapper):
def abi():
"""Return the ABI to the underlying contract."""
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

View File

@ -1,7 +1,14 @@
// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// 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 {
BlockParam,
@ -10,6 +17,7 @@ import {
ContractAbi,
ContractArtifact,
DecodedLogArgs,
LogWithDecodedArgs,
MethodAbi,
TransactionReceiptWithDecodedLogs,
TxData,
@ -23,12 +31,18 @@ import { assert } from '@0x/assert';
import * as ethers from 'ethers';
// tslint:enable:no-unused-variable
export type AbiGenDummyEventArgs = AbiGenDummyAnEventEventArgs;
export type AbiGenDummyEventArgs = AbiGenDummyWithdrawalEventArgs | AbiGenDummyAnEventEventArgs;
export enum AbiGenDummyEvents {
Withdrawal = 'Withdrawal',
AnEvent = 'AnEvent',
}
export interface AbiGenDummyWithdrawalEventArgs extends DecodedLogArgs {
_owner: string;
_value: BigNumber;
}
export interface AbiGenDummyAnEventEventArgs extends DecodedLogArgs {
param: number;
}
@ -115,6 +129,106 @@ export class AbiGenDummyContract extends BaseContract {
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 = {
async callAsync(
hash: string,
@ -903,6 +1017,7 @@ export class AbiGenDummyContract extends BaseContract {
return abiEncodedTransactionData;
},
};
private readonly _subscriptionManager: SubscriptionManager<AbiGenDummyEventArgs, AbiGenDummyEvents>;
public static async deployFrom0xArtifactAsync(
artifact: ContractArtifact | SimpleContractArtifact,
supportedProvider: SupportedProvider,
@ -982,6 +1097,20 @@ export class AbiGenDummyContract extends BaseContract {
stateMutability: 'pure',
type: 'function',
},
{
constant: false,
inputs: [
{
name: 'wad',
type: 'uint256',
},
],
name: 'withdraw',
outputs: [],
payable: false,
stateMutability: 'nonpayable',
type: 'function',
},
{
constant: true,
inputs: [
@ -1307,6 +1436,24 @@ export class AbiGenDummyContract extends BaseContract {
stateMutability: 'pure',
type: 'function',
},
{
anonymous: false,
inputs: [
{
name: '_owner',
type: 'address',
indexed: true,
},
{
name: '_value',
type: 'uint256',
indexed: false,
},
],
name: 'Withdrawal',
outputs: [],
type: 'event',
},
{
anonymous: false,
inputs: [
@ -1323,9 +1470,81 @@ export class AbiGenDummyContract extends BaseContract {
] as ContractAbi;
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>) {
super('AbiGenDummy', AbiGenDummyContract.ABI(), address, supportedProvider, txDefaults);
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);
}
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
// 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)

View File

@ -7,8 +7,9 @@ import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import * as ChaiBigNumber from 'chai-bignumber';
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 = {
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', () => {
it('should normalize address inputs to lowercase', async () => {
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,
"version": "5.1.2",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,12 +14,11 @@ import { DutchAuctionWrapperError, OrderTransactionOpts } from '../types';
import { assert } from '../utils/assert';
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
export class DutchAuctionWrapper extends ContractWrapper {
export class DutchAuctionWrapper {
public abi: ContractAbi = DutchAuction.compilerOutput.abi;
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
* 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.
*/
public constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId);
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
@ -89,11 +93,9 @@ export class DutchAuctionWrapper extends ContractWrapper {
) {
throw new Error(DutchAuctionWrapperError.AssetDataMismatch);
}
// get contract
const dutchAuctionInstance = await this._getDutchAuctionContractAsync();
// validate transaction
if (orderTransactionOpts.shouldValidate) {
await dutchAuctionInstance.matchOrders.callAsync(
await this._dutchAuctionContract.matchOrders.callAsync(
buyOrder,
sellOrder,
buyOrder.signature,
@ -107,7 +109,7 @@ export class DutchAuctionWrapper extends ContractWrapper {
);
}
// send transaction
const txHash = await dutchAuctionInstance.matchOrders.sendTransactionAsync(
const txHash = await this._dutchAuctionContract.matchOrders.sendTransactionAsync(
buyOrder,
sellOrder,
buyOrder.signature,
@ -129,22 +131,8 @@ export class DutchAuctionWrapper extends ContractWrapper {
public async getAuctionDetailsAsync(sellOrder: SignedOrder): Promise<DutchAuctionDetails> {
// type assertions
assert.doesConformToSchema('sellOrder', sellOrder, schemas.signedOrderSchema);
// get contract
const dutchAuctionInstance = await this._getDutchAuctionContractAsync();
// call contract
const auctionDetails = await dutchAuctionInstance.getAuctionDetails.callAsync(sellOrder);
const auctionDetails = await this._dutchAuctionContract.getAuctionDetails.callAsync(sellOrder);
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 { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
/**
* 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 address: string;
private _erc20ProxyContractIfExists?: ERC20ProxyContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _erc20ProxyContract: ERC20ProxyContract;
/**
* Instantiate ERC20ProxyWrapper
* @param web3Wrapper Web3Wrapper instance to use
@ -25,19 +24,23 @@ export class ERC20ProxyWrapper extends ContractWrapper {
* default to the known address corresponding to the networkId.
*/
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId);
this._web3Wrapper = web3Wrapper;
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
* @return Proxy id
*/
public async getProxyIdAsync(): Promise<AssetProxyId> {
const ERC20ProxyContractInstance = this._getERC20ProxyContract();
// Note(albrow): Below is a TSLint false positive. Code won't compile if
// you remove the 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;
}
/**
@ -48,8 +51,7 @@ export class ERC20ProxyWrapper extends ContractWrapper {
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const ERC20ProxyContractInstance = this._getERC20ProxyContract();
const isAuthorized = await ERC20ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress);
const isAuthorized = await this._erc20ProxyContract.authorized.callAsync(normalizedExchangeContractAddress);
return isAuthorized;
}
/**
@ -57,20 +59,7 @@ export class ERC20ProxyWrapper extends ContractWrapper {
* @return The list of authorized addresses.
*/
public async getAuthorizedAddressesAsync(): Promise<string[]> {
const ERC20ProxyContractInstance = this._getERC20ProxyContract();
const authorizedAddresses = await ERC20ProxyContractInstance.getAuthorizedAddresses.callAsync();
const authorizedAddresses = await this._erc20ProxyContract.getAuthorizedAddresses.callAsync();
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 { SubscriptionManager } from '@0x/base-contract';
import { ERC20Token } from '@0x/contract-artifacts';
import { schemas } from '@0x/json-schemas';
import { BigNumber } from '@0x/utils';
@ -20,7 +21,6 @@ import { assert } from '../utils/assert';
import { constants } from '../utils/constants';
import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_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
* to the 0x ERC20 Proxy smart contract.
*/
export class ERC20TokenWrapper extends ContractWrapper {
export class ERC20TokenWrapper {
public abi: ContractAbi = ERC20Token.compilerOutput.abi;
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 _erc20ProxyWrapper: ERC20ProxyWrapper;
/**
* Instantiate ERC20TokenWrapper
* @param web3Wrapper Web3Wrapper instance to use
* @param networkId Desired networkId
* @param erc20ProxyWrapper The ERC20ProxyWrapper instance to use
* @param blockPollingIntervalMs The block polling interval to use for active subscriptions
*/
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc20ProxyWrapper: ERC20ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
constructor(web3Wrapper: Web3Wrapper, erc20ProxyWrapper: ERC20ProxyWrapper, blockPollingIntervalMs?: number) {
this._web3Wrapper = web3Wrapper;
this._tokenContractsByAddress = {};
this._erc20ProxyWrapper = erc20ProxyWrapper;
this._blockPollingIntervalMs = blockPollingIntervalMs;
this._subscriptionManager = new SubscriptionManager<ERC20TokenEventArgs, ERC20TokenEvents>(
ERC20TokenContract.ABI(),
web3Wrapper,
);
}
/**
* Retrieves an owner's ERC20 token balance.
@ -371,13 +372,14 @@ export class ERC20TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>(
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
normalizedTokenAddress,
eventName,
indexFilterValues,
ERC20Token.compilerOutput.abi,
callback,
isVerbose,
this._blockPollingIntervalMs,
);
return subscriptionToken;
}
@ -387,13 +389,13 @@ export class ERC20TokenWrapper extends ContractWrapper {
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken);
this._subscriptionManager.unsubscribe(subscriptionToken); // doesn't matter which contract is used
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
super._unsubscribeAll();
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
@ -415,7 +417,7 @@ export class ERC20TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>(
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
normalizedTokenAddress,
eventName,
blockRange,

View File

@ -8,15 +8,14 @@ import * as _ from 'lodash';
import { assert } from '../utils/assert';
import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
/**
* 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 address: string;
private _erc721ProxyContractIfExists?: ERC721ProxyContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _erc721ProxyContract: ERC721ProxyContract;
/**
* Instantiate ERC721ProxyWrapper
* @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.
*/
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId);
this._web3Wrapper = web3Wrapper;
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
* @return Proxy id
*/
public async getProxyIdAsync(): Promise<AssetProxyId> {
const ERC721ProxyContractInstance = await this._getERC721ProxyContract();
// Note(albrow): Below is a TSLint false positive. Code won't compile if
// you remove the 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;
}
/**
@ -48,8 +51,7 @@ export class ERC721ProxyWrapper extends ContractWrapper {
public async isAuthorizedAsync(exchangeContractAddress: string): Promise<boolean> {
assert.isETHAddressHex('exchangeContractAddress', exchangeContractAddress);
const normalizedExchangeContractAddress = exchangeContractAddress.toLowerCase();
const ERC721ProxyContractInstance = await this._getERC721ProxyContract();
const isAuthorized = await ERC721ProxyContractInstance.authorized.callAsync(normalizedExchangeContractAddress);
const isAuthorized = await this._erc721ProxyContract.authorized.callAsync(normalizedExchangeContractAddress);
return isAuthorized;
}
/**
@ -57,20 +59,7 @@ export class ERC721ProxyWrapper extends ContractWrapper {
* @return The list of authorized addresses.
*/
public async getAuthorizedAddressesAsync(): Promise<string[]> {
const ERC721ProxyContractInstance = await this._getERC721ProxyContract();
const authorizedAddresses = await ERC721ProxyContractInstance.getAuthorizedAddresses.callAsync();
const authorizedAddresses = await this._erc721ProxyContract.getAuthorizedAddresses.callAsync();
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 { SubscriptionManager } from '@0x/base-contract';
import { ERC721Token } from '@0x/contract-artifacts';
import { schemas } from '@0x/json-schemas';
import { BigNumber } from '@0x/utils';
@ -20,7 +21,6 @@ import { assert } from '../utils/assert';
import { constants } from '../utils/constants';
import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_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
* to the 0x ERC721 Proxy smart contract.
*/
export class ERC721TokenWrapper extends ContractWrapper {
export class ERC721TokenWrapper {
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 _erc721ProxyWrapper: ERC721ProxyWrapper;
/**
* Instantiate ERC721TokenWrapper
* @param web3Wrapper Web3Wrapper instance to use
* @param networkId Desired networkId
* @param erc721ProxyWrapper The ERC721ProxyWrapper instance to use
* @param blockPollingIntervalMs The block polling interval to use for active subscriptions
*/
constructor(
web3Wrapper: Web3Wrapper,
networkId: number,
erc721ProxyWrapper: ERC721ProxyWrapper,
blockPollingIntervalMs?: number,
) {
super(web3Wrapper, networkId, blockPollingIntervalMs);
constructor(web3Wrapper: Web3Wrapper, erc721ProxyWrapper: ERC721ProxyWrapper, blockPollingIntervalMs?: number) {
this._web3Wrapper = web3Wrapper;
this._tokenContractsByAddress = {};
this._erc721ProxyWrapper = erc721ProxyWrapper;
this._blockPollingIntervalMs = blockPollingIntervalMs;
this._subscriptionManager = new SubscriptionManager<ERC721TokenEventArgs, ERC721TokenEvents>(
ERC721TokenContract.ABI(),
web3Wrapper,
);
}
/**
* Count all NFTs assigned to an owner
@ -398,13 +399,14 @@ export class ERC721TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
assert.isFunction('callback', callback);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const subscriptionToken = this._subscribe<ArgsType>(
const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
normalizedTokenAddress,
eventName,
indexFilterValues,
ERC721Token.compilerOutput.abi,
callback,
isVerbose,
this._blockPollingIntervalMs,
);
return subscriptionToken;
}
@ -414,13 +416,13 @@ export class ERC721TokenWrapper extends ContractWrapper {
*/
public unsubscribe(subscriptionToken: string): void {
assert.isValidSubscriptionToken('subscriptionToken', subscriptionToken);
this._unsubscribe(subscriptionToken);
this._subscriptionManager.unsubscribe(subscriptionToken);
}
/**
* Cancels all existing subscriptions
*/
public unsubscribeAll(): void {
super._unsubscribeAll();
this._subscriptionManager.unsubscribeAll();
}
/**
* Gets historical logs without creating a subscription
@ -442,7 +444,7 @@ export class ERC721TokenWrapper extends ContractWrapper {
assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
const normalizedTokenAddress = tokenAddress.toLowerCase();
const logs = await this._getLogsAsync<ArgsType>(
const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
normalizedTokenAddress,
eventName,
blockRange,

View File

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

View File

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

View File

@ -17,17 +17,16 @@ import { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { decorators } from '../utils/decorators';
import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper';
/**
* 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 address: string;
public zrxTokenAddress: string;
public etherTokenAddress: string;
private _forwarderContractIfExists?: ForwarderContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _forwarderContract: ForwarderContract;
/**
* Instantiate ForwarderWrapper
@ -49,12 +48,17 @@ export class ForwarderWrapper extends ContractWrapper {
zrxTokenAddress?: string,
etherTokenAddress?: string,
) {
super(web3Wrapper, networkId);
this._web3Wrapper = web3Wrapper;
this.address = address === undefined ? _getDefaultContractAddresses(networkId).exchange : address;
this.zrxTokenAddress =
zrxTokenAddress === undefined ? _getDefaultContractAddresses(networkId).zrxToken : zrxTokenAddress;
this.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.
@ -106,11 +110,9 @@ export class ForwarderWrapper extends ContractWrapper {
// compile signatures
const signatures = _.map(optimizedMarketOrders, order => order.signature);
const feeSignatures = _.map(optimizedFeeOrders, order => order.signature);
// get contract
const forwarderContractInstance = await this._getForwarderContractAsync();
// validate transaction
if (orderTransactionOpts.shouldValidate) {
await forwarderContractInstance.marketSellOrdersWithEth.callAsync(
await this._forwarderContract.marketSellOrdersWithEth.callAsync(
optimizedMarketOrders,
signatures,
optimizedFeeOrders,
@ -127,7 +129,7 @@ export class ForwarderWrapper extends ContractWrapper {
);
}
// send transaction
const txHash = await forwarderContractInstance.marketSellOrdersWithEth.sendTransactionAsync(
const txHash = await this._forwarderContract.marketSellOrdersWithEth.sendTransactionAsync(
optimizedMarketOrders,
signatures,
optimizedFeeOrders,
@ -196,11 +198,9 @@ export class ForwarderWrapper extends ContractWrapper {
// compile signatures
const signatures = _.map(optimizedMarketOrders, order => order.signature);
const feeSignatures = _.map(optimizedFeeOrders, order => order.signature);
// get contract
const forwarderContractInstance = await this._getForwarderContractAsync();
// validate transaction
if (orderTransactionOpts.shouldValidate) {
await forwarderContractInstance.marketBuyOrdersWithEth.callAsync(
await this._forwarderContract.marketBuyOrdersWithEth.callAsync(
optimizedMarketOrders,
makerAssetFillAmount,
signatures,
@ -218,7 +218,7 @@ export class ForwarderWrapper extends ContractWrapper {
);
}
// send transaction
const txHash = await forwarderContractInstance.marketBuyOrdersWithEth.sendTransactionAsync(
const txHash = await this._forwarderContract.marketBuyOrdersWithEth.sendTransactionAsync(
optimizedMarketOrders,
makerAssetFillAmount,
signatures,
@ -236,16 +236,4 @@ export class ForwarderWrapper extends ContractWrapper {
);
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 { _getDefaultContractAddresses } from '../utils/contract_addresses';
import { ContractWrapper } from './contract_wrapper';
/**
* 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 address: string;
private _orderValidatorContractIfExists?: OrderValidatorContract;
private readonly _web3Wrapper: Web3Wrapper;
private readonly _orderValidatorContract: OrderValidatorContract;
/**
* Instantiate OrderValidatorWrapper
* @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.
*/
constructor(web3Wrapper: Web3Wrapper, networkId: number, address?: string) {
super(web3Wrapper, networkId);
this._web3Wrapper = web3Wrapper;
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
@ -40,8 +44,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getOrderAndTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<OrderAndTraderInfo> {
assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
assert.isETHAddressHex('takerAddress', takerAddress);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const orderAndTraderInfo = await OrderValidatorContractInstance.getOrderAndTraderInfo.callAsync(
const orderAndTraderInfo = await this._orderValidatorContract.getOrderAndTraderInfo.callAsync(
order,
takerAddress,
);
@ -66,8 +69,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
);
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const ordersAndTradersInfo = await OrderValidatorContractInstance.getOrdersAndTradersInfo.callAsync(
const ordersAndTradersInfo = await this._orderValidatorContract.getOrdersAndTradersInfo.callAsync(
orders,
takerAddresses,
);
@ -91,8 +93,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getTraderInfoAsync(order: SignedOrder, takerAddress: string): Promise<TraderInfo> {
assert.doesConformToSchema('order', order, schemas.signedOrderSchema);
assert.isETHAddressHex('takerAddress', takerAddress);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const result = await OrderValidatorContractInstance.getTraderInfo.callAsync(order, takerAddress);
const result = await this._orderValidatorContract.getTraderInfo.callAsync(order, takerAddress);
return result;
}
/**
@ -107,8 +108,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
assert.isETHAddressHex(`takerAddresses[${index}]`, takerAddress),
);
assert.assert(orders.length === takerAddresses.length, 'Expected orders.length to equal takerAddresses.length');
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const result = await OrderValidatorContractInstance.getTradersInfo.callAsync(orders, takerAddresses);
const result = await this._orderValidatorContract.getTradersInfo.callAsync(orders, takerAddresses);
return result;
}
/**
@ -120,8 +120,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getBalanceAndAllowanceAsync(address: string, assetData: string): Promise<BalanceAndAllowance> {
assert.isETHAddressHex('address', address);
assert.isHexString('assetData', assetData);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const balanceAndAllowance = await OrderValidatorContractInstance.getBalanceAndAllowance.callAsync(
const balanceAndAllowance = await this._orderValidatorContract.getBalanceAndAllowance.callAsync(
address,
assetData,
);
@ -140,8 +139,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getBalancesAndAllowancesAsync(address: string, assetDatas: string[]): Promise<BalanceAndAllowance[]> {
assert.isETHAddressHex('address', address);
_.forEach(assetDatas, (assetData, index) => assert.isHexString(`assetDatas[${index}]`, assetData));
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const balancesAndAllowances = await OrderValidatorContractInstance.getBalancesAndAllowances.callAsync(
const balancesAndAllowances = await this._orderValidatorContract.getBalancesAndAllowances.callAsync(
address,
assetDatas,
);
@ -165,20 +163,7 @@ export class OrderValidatorWrapper extends ContractWrapper {
public async getERC721TokenOwnerAsync(tokenAddress: string, tokenId: BigNumber): Promise<string | undefined> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('tokenId', tokenId);
const OrderValidatorContractInstance = await this._getOrderValidatorContractAsync();
const result = await OrderValidatorContractInstance.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
const result = await this._orderValidatorContract.getERC721TokenOwner.callAsync(tokenAddress, tokenId);
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