aboutsummaryrefslogtreecommitdiffstats
path: root/src/contract_wrappers
diff options
context:
space:
mode:
authorLeonid <logvinov.leon@gmail.com>2017-10-04 19:30:36 +0800
committerGitHub <noreply@github.com>2017-10-04 19:30:36 +0800
commit836d9be7fee9986c8ffa380633d873ba557511f4 (patch)
treebdbe710ada39c7619efa5087cdd4eee6256cbf33 /src/contract_wrappers
parent5d554ab88246563a8efcbde1b92e45ab926214d5 (diff)
parente5bdf60460330a24597e018f3611e7bc939c1362 (diff)
downloaddexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.tar
dexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.tar.gz
dexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.tar.bz2
dexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.tar.lz
dexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.tar.xz
dexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.tar.zst
dexon-sol-tools-836d9be7fee9986c8ffa380633d873ba557511f4.zip
Merge pull request #178 from 0xProject/feature/getLogs
Add zeroEx.getLogsAsync
Diffstat (limited to 'src/contract_wrappers')
-rw-r--r--src/contract_wrappers/contract_wrapper.ts66
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts23
-rw-r--r--src/contract_wrappers/token_wrapper.ts24
3 files changed, 107 insertions, 6 deletions
diff --git a/src/contract_wrappers/contract_wrapper.ts b/src/contract_wrappers/contract_wrapper.ts
index 2a55b53d9..743dfc9b2 100644
--- a/src/contract_wrappers/contract_wrapper.ts
+++ b/src/contract_wrappers/contract_wrapper.ts
@@ -1,13 +1,52 @@
import * as _ from 'lodash';
import * as Web3 from 'web3';
+import * as ethUtil from 'ethereumjs-util';
import {Web3Wrapper} from '../web3_wrapper';
-import {ZeroExError, Artifact} from '../types';
+import {AbiDecoder} from '../utils/abi_decoder';
+import {
+ InternalZeroExError,
+ Artifact,
+ LogWithDecodedArgs,
+ RawLog,
+ ContractEvents,
+ SubscriptionOpts,
+ IndexedFilterValues,
+} from '../types';
import {utils} from '../utils/utils';
+const TOPIC_LENGTH = 32;
+
export class ContractWrapper {
protected _web3Wrapper: Web3Wrapper;
- constructor(web3Wrapper: Web3Wrapper) {
+ private _abiDecoder?: AbiDecoder;
+ constructor(web3Wrapper: Web3Wrapper, abiDecoder?: AbiDecoder) {
this._web3Wrapper = web3Wrapper;
+ this._abiDecoder = abiDecoder;
+ }
+ protected async _getLogsAsync(address: string, eventName: ContractEvents, subscriptionOpts: SubscriptionOpts,
+ indexFilterValues: IndexedFilterValues,
+ abi: Web3.ContractAbi): Promise<LogWithDecodedArgs[]> {
+ const eventAbi = _.find(abi, {name: eventName}) as Web3.EventAbi;
+ const eventSignature = this._getEventSignatureFromAbiByName(eventAbi, eventName);
+ const topicForEventSignature = this._web3Wrapper.keccak256(eventSignature);
+ const topicsForIndexedArgs = this._getTopicsForIndexedArgs(eventAbi, indexFilterValues);
+ const topics = [topicForEventSignature, ...topicsForIndexedArgs];
+ const filter = {
+ fromBlock: subscriptionOpts.fromBlock,
+ toBlock: subscriptionOpts.toBlock,
+ address,
+ topics,
+ };
+ const logs = await this._web3Wrapper.getLogsAsync(filter);
+ const logsWithDecodedArguments = _.map(logs, this._tryToDecodeLogOrNoop.bind(this));
+ return logsWithDecodedArguments;
+ }
+ protected _tryToDecodeLogOrNoop(log: Web3.LogEntry): LogWithDecodedArgs|RawLog {
+ if (_.isUndefined(this._abiDecoder)) {
+ throw new Error(InternalZeroExError.NoAbiDecoder);
+ }
+ const logWithDecodedArgs = this._abiDecoder.tryToDecodeLogOrNoop(log);
+ return logWithDecodedArgs;
}
protected async _instantiateContractIfExistsAsync<A extends Web3.ContractInstance>(artifact: Artifact,
addressIfExists?: string,
@@ -16,4 +55,27 @@ export class ContractWrapper {
await this._web3Wrapper.getContractInstanceFromArtifactAsync<A>(artifact, addressIfExists);
return contractInstance;
}
+ protected _getEventSignatureFromAbiByName(eventAbi: Web3.EventAbi, eventName: ContractEvents): string {
+ const types = _.map(eventAbi.inputs, 'type');
+ const signature = `${eventAbi.name}(${types.join(',')})`;
+ return signature;
+ }
+ private _getTopicsForIndexedArgs(abi: Web3.EventAbi, indexFilterValues: IndexedFilterValues): Array<string|null> {
+ const topics: Array<string|null> = [];
+ for (const eventInput of abi.inputs) {
+ if (!eventInput.indexed) {
+ continue;
+ }
+ if (_.isUndefined(indexFilterValues[eventInput.name])) {
+ 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;
+ }
}
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index d02a6e642..b3a35d5bf 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -30,6 +30,7 @@ import {
MethodOpts,
ValidateOrderFillableOpts,
OrderTransactionOpts,
+ RawLog,
} from '../types';
import {assert} from '../utils/assert';
import {utils} from '../utils/utils';
@@ -39,6 +40,7 @@ import {ContractWrapper} from './contract_wrapper';
import {constants} from '../utils/constants';
import {TokenWrapper} from './token_wrapper';
import {decorators} from '../utils/decorators';
+import {AbiDecoder} from '../utils/abi_decoder';
import {artifacts} from '../artifacts';
const SHOULD_VALIDATE_BY_DEFAULT = true;
@@ -79,8 +81,9 @@ export class ExchangeWrapper extends ContractWrapper {
];
return [orderAddresses, orderValues];
}
- constructor(web3Wrapper: Web3Wrapper, tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
- super(web3Wrapper);
+ constructor(web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder,
+ tokenWrapper: TokenWrapper, contractAddressIfExists?: string) {
+ super(web3Wrapper, abiDecoder);
this._tokenWrapper = tokenWrapper;
this._orderValidationUtils = new OrderValidationUtils(tokenWrapper, this);
this._exchangeLogEventEmitters = [];
@@ -656,6 +659,22 @@ export class ExchangeWrapper extends ContractWrapper {
return eventEmitter;
}
/**
+ * Gets historical logs without creating a subscription
+ * @param eventName The exchange contract event you would like to subscribe to.
+ * @param subscriptionOpts Subscriptions options that let you configure the subscription.
+ * @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(eventName: ExchangeEvents, subscriptionOpts: SubscriptionOpts,
+ indexFilterValues: IndexedFilterValues): Promise<LogWithDecodedArgs[]> {
+ const exchangeContractAddress = await this.getContractAddressAsync();
+ const logs = await this._getLogsAsync(
+ exchangeContractAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.ExchangeArtifact.abi,
+ );
+ return logs;
+ }
+ /**
* Stops watching for all exchange events
*/
public async stopWatchingAllEventsAsync(): Promise<void> {
diff --git a/src/contract_wrappers/token_wrapper.ts b/src/contract_wrappers/token_wrapper.ts
index f7f0a0ce3..91af223e4 100644
--- a/src/contract_wrappers/token_wrapper.ts
+++ b/src/contract_wrappers/token_wrapper.ts
@@ -7,6 +7,7 @@ import {utils} from '../utils/utils';
import {eventUtils} from '../utils/event_utils';
import {constants} from '../utils/constants';
import {ContractWrapper} from './contract_wrapper';
+import {AbiDecoder} from '../utils/abi_decoder';
import {artifacts} from '../artifacts';
import {
TokenContract,
@@ -18,6 +19,8 @@ import {
ContractEventEmitter,
ContractEventObj,
MethodOpts,
+ LogWithDecodedArgs,
+ RawLog,
} from '../types';
const ALLOWANCE_TO_ZERO_GAS_AMOUNT = 47155;
@@ -32,8 +35,9 @@ export class TokenWrapper extends ContractWrapper {
private _tokenContractsByAddress: {[address: string]: TokenContract};
private _tokenLogEventEmitters: ContractEventEmitter[];
private _tokenTransferProxyContractAddressFetcher: () => Promise<string>;
- constructor(web3Wrapper: Web3Wrapper, tokenTransferProxyContractAddressFetcher: () => Promise<string>) {
- super(web3Wrapper);
+ constructor(web3Wrapper: Web3Wrapper, abiDecoder: AbiDecoder,
+ tokenTransferProxyContractAddressFetcher: () => Promise<string>) {
+ super(web3Wrapper, abiDecoder);
this._tokenContractsByAddress = {};
this._tokenLogEventEmitters = [];
this._tokenTransferProxyContractAddressFetcher = tokenTransferProxyContractAddressFetcher;
@@ -277,6 +281,22 @@ export class TokenWrapper extends ContractWrapper {
return eventEmitter;
}
/**
+ * Gets historical logs without creating a subscription
+ * @param tokenAddress An address of the token that emmited the logs.
+ * @param eventName The token contract event you would like to subscribe to.
+ * @param subscriptionOpts Subscriptions options that let you configure the subscription.
+ * @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(tokenAddress: string, eventName: TokenEvents, subscriptionOpts: SubscriptionOpts,
+ indexFilterValues: IndexedFilterValues): Promise<LogWithDecodedArgs[]> {
+ const logs = await this._getLogsAsync(
+ tokenAddress, eventName, subscriptionOpts, indexFilterValues, artifacts.TokenArtifact.abi,
+ );
+ return logs;
+ }
+ /**
* Stops watching for all token events
*/
public async stopWatchingAllEventsAsync(): Promise<void> {