Im пытается интегрировать web3js с Трезором в Dev сети трюфеля или с помощью Ropsten тестовой сети.
Идея заключается в том, чтобы подписать транзакции с помощью аппаратного кошелька, а затем отправить необработанную транзакцию с помощью web3js.
Я понял, что у нас нет баланса для совершения транзакции, возможно потому, что web3js не берет одну из 10 учетных записей трюфелей и использует адрес трезора, которого нет в моей локальной сети.
На Ropsten у меня есть некоторые эфиры, и я получаю "неверный адрес"
Есть ли способ отправить подписанные транзакции (с трезором) с помощью web3js в сеть разработки трюфелей? Я имею в виду, есть ли способ включить адрес трезора в сеть трюфелей?
Ситуация с трюфелями объясняется более подробно здесь, но вопрос можно обобщить так: " Есть ли способ включить аппаратные кошельки в сеть разработки трюфелей? ": Https://github.com/trufflesuite/truffle/issues/973.
Используя ropsten, мне удалось отправить транзакцию и получить хеш транзакции в обратном вызове, но если мы запросим эту транзакцию, мы получим, что транзакция не существует... так... как это возможно?
Я тоже пытался развернуть контракт в Ropsten, и теперь я получаю "Неверный адрес" при вызове функции умного контракта. Может быть, функция подписи не так? Кто-нибудь может интегрировать подпись транзакции Trezor с web3js?
Ребята, вы видите что-то неправильное в процессе подписания и отправки, который мы выполняли? Возможно, что-то не так с обработкой параметров R, V и S..
Еще одна важная вещь, что я использую https://github.com/ethereumjs/ethereumjs-tx для создания необработанных транзакций
Проблемы, опубликованные в web3js, truffle и trezzor, связаны с дополнительной информацией:
- https://github.com/trufflesuite/truffle/issues/973
- https://github.com/ethereum/web3.js/issues/1669
- https://github.com/trezor/connect/issues/130
С уважением
trezorLogin = async()=> {
let trezor= await this.getTrezor();
// site icon, optional. at least 48x48px
let hosticon = 'https://doc.satoshilabs.com/trezor-apps/_images/copay_logo.png';
// server-side generated and randomized challenges
let challenge_hidden = '';
let challenge_visual = '';
//use anonimous functions on callback otherwise returns cross origin errors
trezor.requestLogin(hosticon, challenge_hidden, challenge_visual, function (result){
if (result.success) {
console.log('Public key:', result.public_key); // pubkey in hex
console.log('Signature:', result.signature); // signature in hex
console.log('Version 2:', result.version === 2); // version field
console.log(result);
}else {
console.error('Error:', result.error);
}
});}
trezorSignTx= async(transaction)=> {
let trezor= await this.getTrezor();
// spend one change output
let address_n = "m/44'/60'/0'/0/0"
// let address_n = [44 | 0x80000000,
// 60 | 0x80000000,
// 0 | 0x80000000 ,
// 0 ]; // same, in raw form
let nonce = transaction.nonce.substring(2); // note - it is hex, not number!!!
let gas_price = transaction.gasPrice.substring(2);
let gas_limit = transaction.gasLimit.substring(2);
let to = transaction.to.substring(2);
// let value = '01'; // in hexadecimal, in wei - this is 1 wei
let value = transaction.value.substring(2); // in hexadecimal, in wei - this is about 18 ETC
let data = transaction.data.substring(2); // some contract data
// let data = null // for no data
let chain_id = 5777; // 1 for ETH, 61 for ETC
return new Promise (function (resolve,reject) {
trezor.ethereumSignTx(
address_n,
nonce,
gas_price,
gas_limit,
to,
value,
data,
chain_id,
function (response) {
if (response.success) {
console.log('Signature V (recovery parameter):', response.v); // number
console.log('Signature R component:', response.r); // bytes
console.log('Signature S component:', response.s); // bytes
resolve(response);
} else {
console.error('Error:', response.error); // error message
resolve(null);
}
});
})
}
getTrezorAddress = async() => {
let trezor= await this.getTrezor();
// spend one change output
let address_n = "m/44'/60'/0'/0/0";
trezor.ethereumGetAddress(address_n, function (result) {
if (result.success) { // success
console.log('Address: ', result.address);
} else {
console.error('Error:', result.error); // error message
}
});
}
getTrezor = async() => {
let trezorC;
await getTrezorConnect
.then(trezorConnect => {
trezorC= trezorConnect;
})
.catch((error) => {
console.log(error)
})
return trezorC;
}
sendTransaction= async(address, amount, id)=>{
let tokenInstance = this.props.smartContractInstance;
let getData = tokenInstance.mint.getData(address, amount);
let tx = {
nonce: '0x00',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
to: CONTRACT_ADDRESS,
value: '0x00',
from:CONTRACT_OWNER_ADDRESS,
data: getData
};
let response = await this.trezorSignTx(tx);
let web3;
let _this = this;
if (response!=null){
getWeb3
.then(results => {
web3= results.web3;
let v = response.v.toString();
if (v.length % 2 != 0){
v="0"+v;
}
tx.r=Buffer.from(response.r,'hex');
tx.v=Buffer.from(v,'hex');
tx.s=Buffer.from(response.s,'hex');
let ethtx = new ethereumjs(tx);
console.dir(ethtx.getSenderAddress().toString('hex'), );
const serializedTx = ethtx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
console.log(rawTx);
//finally pass this data parameter to send Transaction
web3.eth.sendRawTransaction(rawTx, function (error, result) {
if(!error){
_this.props.addTokens(id)
.then(()=>{
_this.setState({modalOpen: true});
_this.props.getAllTransactions();
}
);
}else{
alert(error)
}
});
})
.catch((error) => {
console.log(error)
})
}else{
alert("There was an error signing with trezor hardware wallet")
}
}
Функция getTrezorConnect просто получает window.trezorConnect асинхронно, потому что объект вводится как скрипт
<script src="https://connect.trezor.io/4/connect.js"></script>
let getTrezorConnect = new Promise(function(resolve, reject) {
// Wait for loading completion
window.addEventListener('load', function() {
let trezorConnect = window.TrezorConnect
return resolve(trezorConnect)
})});
export default getTrezorConnect