aboutsummaryrefslogblamecommitdiffstats
path: root/src/contract_wrappers/contract_wrapper.ts
blob: 743dfc9b2b22a0375c6f6a2b35d9f025d7b1f85d (plain) (tree)
1
2
3
4
5
6
7
                            
                             
                                           
                                            
                                                
        
                        






                        

                                     

                        
                              
                                        

                                                                    
                                        

                                      

                                                                                                                 
                                                                                         
                                                                         

                                                                                         

                                                                                                



                                                  
                   

                                                                  
                                                                                            

                                        
                                                                                    
                                              
                                                              
         
                                                                              
                                  
     
                                                                                                          

                                                                                                                
                                
                                                                                                       
                                
     
                                                                                                           



                                                                 


                                                                                                                      










                                                                                 



                      
 
import * as _ from 'lodash';
import * as Web3 from 'web3';
import * as ethUtil from 'ethereumjs-util';
import {Web3Wrapper} from '../web3_wrapper';
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;
    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,
                                                                                      ): Promise<A> {
        const contractInstance =
            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;
    }
}