简体   繁体   中英

web3.js how to search all the contracts ever created by and address

I am new to web3.js and solidity. My question is related to the way we search on the block-chain. Its easy to search for a particular contract if we know the contract address. However, how can we find and identify a specific type of contract using the from address used to create the contracts in the first place.

For eg. I have a contract ContractA which is created by 'from' address AddressA using web3.js. Now I want to find all the instances of ContractA created by AddressA.

I tried searching using web3.eth.filter API but noting ever returns. Please help.

I also read about using registry pattern to store all the contracts and ask the registry, but couldn't find any useful example.

For those who are looking for a way, as Adam said in his post, there is no direct way to find contracts created by wallet address. Hence, we have to implement registry pattern as shown below to keep track of things and just ask that contract in web3.js, also shown below....

This is how my contract look like

contract ContractA {
  bool public is_approved;
  address public visa_details;
  uint public artifact_count;

  // constructors
  function ContractA() public {
    owner = msg.sender;
  }
}

Here is the registry pattern contract

contract ContractARegistry {
  mapping(address => address[]) user_contracts;

  function registerContract(address contractA) public {
    user_applications[msg.sender].push(contractA) - 1; // -1 is very important
  }

  function findContract(address user) view public returns (address[]){
    return user_contracts[user];
  }
}

In web3.js you may search like this (I am using Angular4)

import * as ContractA from '../../../../build/contracts/ContractA.json';
import * as UserContracts from '../../../../build/contracts/UserContracts.json';
import * as TruffleContract from 'truffle-contract';
import {Observable} from "rxjs/Observable";

declare var window: any;

@Injectable()
export class AppWeb3ContractAService {
  CONTRACT_A = TruffleContract(ContractA);
  USER_CONTRACTS = TruffleContract(UserContracts);

  constructor(private appWeb3Svc: AppWeb3Service) {
    console.log("Injecting the provider");
    this.CONTRACT_A.setProvider(this.appWeb3Svc.currentProvider());
    this.USER_CONTRACTS.setProvider(this.appWeb3Svc.currentProvider());
  }

  create(ethAddress): Observable<any> {
    return Observable.create(observer => {
      this.CONTRACT_A
        .new({
          from: ethAddress
        })
        .then(application => {
          this.USER_CONTRACTS
            .deployed()
            .then(registry => {
              registry.registerContractA(application.address, {from: ethAddress})
                .then(result => observer.next(application))
                .catch(error => observer.error(error));
            })
            .catch(error => observer.error(error));
        })
        .catch(error => observer.error(error));
    });
  }


  findAll(ethAddress: string):
    Observable<any[]> {
    return Observable.create(observer => {
      this.USER_CONTRACTS
        .deployed()
        .then(registry => {
          registry.findUserContracts(ethAddress, {from: ethAddress})
            .then(addresses => {
              addresses.forEach(address => observer.next(this.CONTRACT_A.at(address)));
            })
            .catch(error => observer.error(error));
        })
        .catch(error => observer.error(error));
    });
  }
}

This is how my appWeb3Svc looks like

import {Injectable} from '@angular/core';
import {environment} from '../../../environments/environment';
import * as Web3 from 'web3';

declare var window: any;

@Injectable()
export class AppWeb3Service {
  public web3: Web3;

  checkAndInstantiateWeb3 = () => {
    // Checking if Web3 has been injected by the browser (Mist/MetaMask)
    if (typeof window.web3 !== 'undefined') {
      console.warn(
        'Using web3 detected from external source. If you find that your accounts don\'t appear or you have 0 MetaCoin, ensure you\'ve configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask'
      );
      // Use Mist/MetaMask's provider
      this.web3 = new Web3(window.web3.currentProvider);
    } else {
      console.warn(
        'No web3 detected. Falling back to ${environment.HttpProvider}. You should remove this fallback when you deploy live, as it\'s inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask'
      );
      // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
      this.web3 = new Web3(
        new Web3.providers.HttpProvider(environment.HttpProvider)
      );
    }
  };

  constructor() {
    this.checkAndInstantiateWeb3();
  }

  currentProvider() {
    return this.web3.currentProvider;
  }

  eth() {
    return this.web3.eth;
  }

  isAddress(ethAddress: string): boolean {
    if (this.web3) {
      return this.web3.isAddress(ethAddress);
    }
    return false
  }
}

Hope this helps!

Unfortunately, there's no easy way to do this exact thing. web3.eth.filter can be used to apply filters on contract address, or they can be used to search across transaction logs (events emitted by a contract) where the sender is in the topic list.

If you want all transactions submitted by a specific address, you pretty much have to traverse each block on the chain and examine each transaction within each block to see if from is set to the address you're interested in.

// while looping through the block numbers you're interested in
web3.eth.getBlock(blockNum, (err, block) => {
  if (block != null) {
    block.transactions.forEach(tx => {
      if (tx.from === myAddress) {
        // Do something
      }
    }
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM