我正在尝试整合 web3js 与 特雷佐 在 松露 开发网络或使用 ropsten测试网 .
想法是使用 签署交易。硬件钱包,然后使用 web3js 发送原始交易
我知道我们没有余额来进行交易,可能是因为 web3js 没有使用 10 个 truffle 帐户之一,而是使用了我本地网络中不存在的 trezor 地址 ..
在 ropsten 我有一些以太币,我得到“无效地址”
有没有办法使用 web3js 将签名交易(使用 trezor)发送到松露开发网络?我的意思是,有没有办法将 trezor 地址包含到松露网络中?
这里更详细地解释了松露的情况,但问题可以概括为“ 有没有办法将硬件钱包包含在松露开发网络中?”:https://github.com/trufflesuite/truffle/issues/973
使用 ropsten 我已经设法在回调中发送交易并接收交易哈希,但是如果我们查询该交易,我们会得到交易不存在..所以..这怎么可能?
我也尝试将合约部署到 Ropsten 中,现在在调用智能合约功能时我得到“无效地址”。也许签名功能是错误的?任何人都可以将 Trezor 交易签名与 web3js 集成在一起吗?
你们在我们遵循的签名和发送过程中发现任何问题吗? 可能 R、V 和 S 参数处理有问题
..
另一个重要的事情是我在使用https://github.com/ethereumjs/ethereumjs-tx用于创建原始交易
在 web3js、truffle 和 trezzor 中发布的问题与更多信息有关:
亲切的问候
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 因为对象是作为脚本注入(inject)的
<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
最佳答案
好吧,经过多次尝试,我们已经成功地将与 Trezor 签署的原始交易发送到 。罗普斯滕 , 松露 (请参阅答案底部的编辑)以及本地私有(private) 格特 网络,所以,代码没问题,在这些环境中集成 Trezor 没有问题
https://ropsten.etherscan.io/address/0x89e2c46b22881f747797cf67310aad1a831d50b7
这是我为了能够将签名交易发送到 Ropsten 测试网而更改的内容。
这假设您已将合约部署到 Ropsten 并且您拥有合约地址。
1) 获取您的 Trezor 帐户的地址
getTrezorAddress = async() => {
let trezor= await this.getTrezor();
// spend one change output
let address_n = "m/44'/1'/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
}
});
}
2)将trezor地址放入
from
您的原始交易字段,获取 nonce
通过获取该地址的交易计数来计算交易。重要提示:使用 getTransactionCount 上的“pending”可选参数来获取帐户的所有交易,否则您将覆盖待处理的交易。getNonce = async(address) => {
let web3 = await this.getWeb3();
return new Promise (function (resolve,reject) {
web3.eth.getTransactionCount(address, "pending", function (error,result){
console.log("Nonce "+result);
resolve(result);
});
});
}
let count = null;
await this.getNonce("0xedff546ac229317df81ef9e6cb3b67c0e6425fa7").then(result => {
if(result.length % 2 !==0){
result = "0"+result;
}
count = "0x"+result;
});
let tx = {
nonce: count ,
gasPrice: web3.toHex(gasPriceGwei*1e9),
gasLimit: web3.toHex(gasLimit),
to: CONTRACT_ADDRESS,
value: '0x00',
data: getData,
chainId:chainId,
from:"yourTrezzorAddress"
};
3) r, s, v 参数不正确,处理它们的正确方法是获取 trezor 响应的值并将其转换为 hexa:
// response is the Trezor sign response
tx.v= response.v;
tx.r="0x"+response.r;
tx.s="0x"+response.s;
let ethtx = new ethereumjs(tx);.
const serializedTx = ethtx.serialize();
const rawTx = '0x' + serializedTx.toString('hex');
//finally pass this data parameter to send Transaction
web3.eth.sendRawTransaction(rawTx, someCallbackFunction);
重要提示:ropsten 中的挖掘时间将在 15 到 30 秒之间,因此如果您在 someCallbackFunction 中使用哈希检查交易收据,您将得到 null 作为结果,因为交易处于待处理状态。
4) 为了在 ropsten 进行测试,我们使用 Infura,因此我们更改了 web3 提供程序:
import Web3 from 'web3'
import HDWalletProvider from "truffle-hdwallet-provider";
let getWeb3 = new Promise(function(resolve, reject) {
// Wait for loading completion to avoid race conditions with web3 injection timing.
window.addEventListener('load', function() {
let results
let web3 = window.web3
// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use Mist/MetaMask's provider.
web3 = new Web3(web3.currentProvider)
results = {
web3: web3
}
console.log('Injected web3 detected.');
return resolve(results)
} else {
// Fallback to localhost if no web3 injection. We've configured this to
// use the development console's port by default.
// let provider = new Web3.providers.HttpProvider("https://ropsten.infura.io/your_infura_api_key")
let mnemonic = "infura mnemonic"
let provider = new HDWalletProvider(mnemonic, "https://ropsten.infura.io/your_infura_api_key")
web3 = new Web3(provider)
results = {
web3: web3
}
console.log('No web3 instance injected, using Local web3.');
return resolve(results)
}
})
})
export default getWeb3
编辑 :
这也适用于 Truffle !查看此问题的最后评论https://github.com/trufflesuite/truffle/issues/973
关于ethereum - 使用 Trezor(硬件钱包)将签名交易发送到 Ropsten 或 Truffle 开发网络,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50596256/