web3.js как искать во всех когда-либо созданных контрактах и адресовать
Я новичок в web3.js и солидность. Мой вопрос связан с тем, как мы ищем в цепочке блоков. Легко найти конкретный договор, если мы знаем адрес договора. Тем не менее, как мы можем найти и идентифицировать конкретный тип контракта, используя адрес отправителя, который использовался для создания контрактов.
Например, У меня есть контракт ContractA, который создается по адресу "from" AddressA с использованием web3.js. Теперь я хочу найти все экземпляры ContractA, созданные AddressA.
Я попытался выполнить поиск с помощью API web3.eth.filter, но заметил, что когда-либо возвращается. Пожалуйста помоги.
Я также читал об использовании шаблона реестра для хранения всех контрактов и запроса реестра, но не смог найти ни одного полезного примера.
2 ответа
Для тех, кто ищет путь, как сказал Адам в своем посте, нет прямого способа найти контракты, созданные по адресу кошелька. Следовательно, мы должны реализовать шаблон реестра, как показано ниже, чтобы отслеживать вещи и просто запросить этот контракт в 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
}
}
}
});