我是web3.js和solidity的新手。我的问题与我们在区块链上的搜索方式有关。如果我们知道合约地址,则很容易搜索特定合约。但是,我们如何首先使用用于创建合约的发件人地址查找和识别特定类型的合约。
例如。我有一个合同 合同 A,它由使用 web3.js 的"发件人"地址 A 创建。现在我想找到AddressA创建的所有合同A实例。
我尝试使用 web3.eth.filter API 进行搜索,但注意到永远返回。请帮忙。
我还阅读了有关使用注册表模式存储所有合约并询问注册表的信息,但找不到任何有用的示例。
对于那些正在寻找一种方法的人来说,正如亚当在他的帖子中所说,没有直接的方法可以找到由钱包地址创建的合约。因此,我们必须实现如下所示的注册表模式来跟踪事情,只需在 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));
});
}
}
这就是我的应用程序Web3Svc的样子
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
}
}
希望这有帮助!
不幸的是,没有简单的方法可以做到这一点。 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
}
}
}
});