web3.js如何搜索所有创建的合同和地址

时间:2018-04-20 09:41:12

标签: blockchain ethereum solidity web3js

我是web3.js和新手的新手。我的问题与我们搜索区块链的方式有关。如果我们知道合同地址,很容易搜索特定合同。但是,我们如何使用首先用于创建合同的起始地址来查找和识别特定类型的合同。

例如。 我有一个合同ContractA,它由'from'地址AddressA使用web3.js创建。现在我想找到AddressA创建的ContractA的所有实例。

我尝试使用web3.eth.filter API进行搜索,但注意到要返回。请帮忙。

我还读到了使用注册表模式存储所有合同并询问注册表,但找不到任何有用的示例。

2 个答案:

答案 0 :(得分:4)

对于那些正在寻找方法的人,正如亚当在帖子中所说,没有直接的方法可以找到钱包地址创建的合同。因此,我们必须实现如下所示的注册表模式以跟踪事物,并在web3.js中询问该合同,也显示在下面....

这是我的合同的样子

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

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

这是注册模式合同

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];
  }
}

在web3.js中你可以像这样搜索(我使用的是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));
    });
  }
}

这就是我的appWeb3Svc的样子

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
  }
}

希望这有帮助!

答案 1 :(得分:2)

不幸的是,没有简单的方法可以做到这一点。 web3.eth.filter可用于在合同地址上应用过滤器,或者可用于搜索发件人在主题列表中的事务日志(合同发出的事件)。

如果您想要通过特定地址提交所有交易,您几乎必须遍历链上的每个块并检查每个块中的每个事务,以查看from是否设置为您感兴趣的地址

// 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
      }
    }
  }
});