我试图将 web3js 与 Trezor 集成在 truffle dev网络中或使用 ropsten test network .
我的想法是使用 hardware wallet and then send a raw transaction using web3js 签署交易
我得到了我们没有 balancer 来进行交易, probably because web3js isnt taking one of the 10 truffle accounts and is using the trezor address that isnt in my local network ..
在ropsten我有一些醚,我得到“无效地址”
有没有办法使用web3js将已签名的交易(使用trezor)发送到松露开发网络?我的意思是,有没有办法将trezor地址包含在松露网络中?
松露的情况在这里详细解释,但问题可以概括为“ is there a way to include hardware wallets into truffle development network? ”:https://github.com/trufflesuite/truffle/issues/973
使用ropsten我已经设法发送一个事务并在回调中接收一个事务哈希,但如果我们查询该事务,我们得到该事务不存在..所以..这怎么可能?
我也尝试将 Contract 部署到Ropsten,现在我在调用智能合约函数时得到“无效地址” . 也许签名功能错了?有人可以将Trezor交易登录与web3js集成吗?
Do you guys see anything wrong in the signing and sending process that we have followed? 可能是R,V和S参数处理有问题..
Another important thing 是我使用https://github.com/ethereumjs/ethereumjs-tx来创建原始事务
Issues published in web3js, truffle and trezzor connect with more information:
亲切的问候
trezorLogin = async()=> {
let trezor= await this.getTrezor();
// site icon, optional. at least 48x48px
var hosticon = 'https://doc.satoshilabs.com/trezor-apps/_images/copay_logo.png';
// server-side generated and randomized challenges
var challenge_hidden = '';
var 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
var address_n = "m/44'/60'/0'/0/0"
// var address_n = [44 | 0x80000000,
// 60 | 0x80000000,
// 0 | 0x80000000 ,
// 0 ]; // same, in raw form
var nonce = transaction.nonce.substring(2); // note - it is hex, not number!!!
var gas_price = transaction.gasPrice.substring(2);
var gas_limit = transaction.gasLimit.substring(2);
var to = transaction.to.substring(2);
// var value = '01'; // in hexadecimal, in wei - this is 1 wei
var value = transaction.value.substring(2); // in hexadecimal, in wei - this is about 18 ETC
var data = transaction.data.substring(2); // some contract data
// var data = null // for no data
var 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
var 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;
var getData = tokenInstance.mint.getData(address, amount);
var 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() {
var trezorConnect = window.TrezorConnect
return resolve(trezorConnect)
})});
export default getTrezorConnect
1 回答
好吧,经过大量的尝试,我们设法将与Trezor签名的原始交易发送到 Ropsten , Truffle (请参阅答案底部的编辑)以及本地私有 Geth 网络,因此,代码是可以的,那里Trezor在这些环境中的集成是没有问题的
https://ropsten.etherscan.io/address/0x89e2c46b22881f747797cf67310aad1a831d50b7
这是我为了能够将已签名的事务发送到Ropsten testnet而更改的内容 .
这假定您已将 Contract 部署到Ropsten并且您拥有 Contract 地址 .
1)获取您的Trezor帐户的地址
2)将trezor地址放入原始事务的
from
字段中,通过获取该地址的事务计数来获取事务的nonce
. 重要提示:使用getTransactionCount上的"pending"可选参数来获取帐户的所有事务,否则您将重写未决事务 .3)r,s,v参数不正确,处理它们的正确方法是获取trezor响应的值并将其转换为hexa:
重要提示:ropsten中的挖掘时间将介于15到30秒之间,因此如果在someCallbackFunction中使用散列检查事务接收,则结果将为null,因为事务处于挂起状态 .
4)要在ropsten测试它我们使用Infura,所以我们改变了web3提供者:
EDIT :
This also works on Truffle !查看此问题的最新评论https://github.com/trufflesuite/truffle/issues/973