I want to send a contract transaction through infura provider, but I need a signer to do so. The problem is that the infura provider doesn't support getSigner(). How can I send contract transactions through infura?
const TokenArtifacts = require('../build/contracts/Token.json');
const abi = TokenArtifacts.abi;
const address = TokenArtifacts.networks[3].address;
var ethers = require('ethers'); // Require the ethers library
var secrets = require("./../secrets.json");
var mnemonic = secrets.mnemonic; // x x x x x x x x x sight glance vintage";
var path = "m/44'/60'/0'/0/0";
var provider = new ethers.providers.InfuraProvider('ropsten');
var wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
wallet.provider = provider; // Set the provider for the wallet
var newAddress = "0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f";
var contract = new ethers.Contract(address, abi, provider);
var transaction = contract.transfer(newAddress, 10);
// var transaction = contract.totalSupply();
// Send the transaction
var sendTransactionPromise = wallet.sendTransaction(transaction);
sendTransactionPromise.then(function(tx) {
console.log(tx);
});
Right, since INFURA does not have your private key, you need to supply it yourself. I think you are close. I'll just make a few comments and changes to your code:
const TokenArtifacts = require('../build/contracts/Token.json');
const abi = TokenArtifacts.abi;
const address = TokenArtifacts.networks[3].address;
var ethers = require('ethers'); // Require the ethers library
var secrets = require("./../secrets.json");
var mnemonic = secrets.mnemonic; // x x x x x x x x x sight glance vintage";
// *** Since you are using the default path, you do not need to specify it
//var path = "m/44'/60'/0'/0/0";
var provider = new ethers.providers.InfuraProvider('ropsten');
var wallet = ethers.Wallet.fromMnemonic(mnemonic);
// *** You cannot "set" a provider like this; all ethers.js objects are immutable, for safety and consistency reasons
//wallet.provider = provider; // Set the provider for the wallet
// *** You can use the connect method to create a new instance of a Wallet though:
wallet = wallet.connect(provider);
var newAddress = "0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f";
// ** You want to connect you *signer* to the contract, not the *provider*
//var contract = new ethers.Contract(address, abi, provider);
var contract = new ethers.Contract(address, abi, signer);
// *** This returns a promise that calls sendTransaction on the wallet for you:
//var transaction = contract.transfer(newAddress, 10);
var sendTransactionPromise = contract.transfer(newAddress, 10);
// *** So there is no need for this;
// Send the transaction
// var sendTransactionPromise = wallet.sendTransaction(transaction);
sendTransactionPromise.then(function(tx) {
console.log(tx);
});
Let me know if you still have any issues. :)
Thanks for the feedback.
Note that you haven't defined signer above. Adding and using signer produces the following error message 'Error: INFURA does not support signing (operation="getSigner")'. I'll post the full code snippet.
const TokenArtifacts = require('../build/contracts/Token.json');
const abi = TokenArtifacts.abi;
const address = TokenArtifacts.networks[3].address;
var ethers = require('ethers'); // Require the ethers library
var secrets = require("./../secrets.json");
var mnemonic = secrets.mnemonic; // "x x x x x x x x x x x x";
var path = "m/44'/60'/0'/0/0";
var provider = new ethers.providers.InfuraProvider('ropsten');
var wallet = ethers.Wallet.fromMnemonic(mnemonic, path);
var signer = provider.getSigner();
wallet = wallet.connect(provider); // Set the provider for the wallet
var newAddress = "0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f";
var contract = new ethers.Contract(address, abi, signer);
var transaction = contract.transfer(newAddress, 10);
// var transaction = contract.totalSupply();
// Send the transaction
var sendTransactionPromise = wallet.sendTransaction(transaction);
sendTransactionPromise.then(function(tx) {
console.log(tx);
});
I'm wondering what the workaround is.
The wallet is the signer, sorry, the third parameter to Contract should have been wallet.
var contract = new ethers.Contract(address, abi, wallet);
I think we are almost there.
I get the following error:
TypeError: wallet.connect is not a function
It is on the following line:
wallet = wallet.connect(provider); // Set the provider for the wallet
That鈥檚 odd. What鈥檚 version are you using?
Can you do a console.log of the wallet before calling connect.
Wallet {
privateKey: '0xaaaaabd5cae0c3aa546df2aa3272717c558031068d3cd895883e1828b02c87e9',
provider: [Getter/Setter],
defaultGasLimit: [Getter/Setter],
address: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
sign: [Function],
mnemonic: 'x x x x x x x x x x x x',
path: 'm/44\'/60\'/0\'/0/0'
}
Ah, you are definitely using v3. Can you upgrade to v4? :)
Version 3.0.25 of ethers.js.
Sure
I am almost there. Now I just get "UnhandledPromiseRejectionWarning: Error: replacement fee too low". Any suggestions for code to include to make the transaction actually work?
Try incrementing the transaction nonce
That means there is already another transaction with that nonce sent to the network, but not mined.
You must either:
If the old transaction have a very low gas price, you will have to replace it.
Now there is no error message, but you can't see the transaction on https://ropsten.etherscan.io/address/0xf92298d72afe68300ea065c0edadbb1a29804faa.
My previous comment might not be valid. I am now able to see the successful contract transactions at the url https://ropsten.etherscan.io/token/0xf92298d72afe68300ea065c0edadbb1a29804faa?a=0x15c72944b325a3e1c7a4dbdc6f883bd5948d3d9f, but getting a different issue which I'll research on my own. (UnhandledPromiseRejectionWarning: Error: replacement fee too low). Thanks for everything and let me know if there is some way I can help.
@dblockunity The "replacement fee too low" error indicates you have a transaction with the same nonce already. It sounds like you may be setting your gas price too low.
You can check current gas prices here: https://ethgasstation.info
Once you have sent a transaction to the network, you must either increase the nonce for the next transaction, or if you are trying to replace it, set the gasPrice to 50% + wei (or more), to bribe the network into choosing the new transaction over the old one, with the same nonce.
Makes sense.
I think this issue was resolved. Closing now. If you still have problems though, please feel free to re-open.
Thanks! :)
hi, i am new to ether.js i want to send ether from my react-native wallet to another metamask address, but it throws me error, i want to know if that is the right syntax to send transaction or not. I am attaching the error log
let provider = new ethers.providers.InfuraProvider("rinkeby",projectID);
let wallet = new ethers.Wallet(await AsyncStorage.getItem('walletPrivateKey'), provider);
console.log("*wlletAdress:",wallet.address);
let tx={
// Required unless deploying a contract (in which case omit)
to: '0x79980eB91462dd932E490F6927b008465c4aa8E6', // the target address or ENS name
// These are optional/meaningless for call and estimateGas
nonce: 0, // the transaction nonce
gasLimit: 0, // the maximum gas this transaction may spend
gasPrice: 0, // the price (in wei) per unit of gas
// These are always optional (but for call, data is usually specified)
data: "0x", // extra data for the transaction, or input for call
value: 0, // the amount (in wei) this transaction is sending
chainId: 4 // the network ID; usually added by a signer
}
console.log(tx);
const signedTransaction = wallet.sign(tx);
var txPromise = await wallet.sendTransaction(signedTransaction);
if(txPromise)console.log(txPromise);
WARN Possible Unhandled Promise Rejection (id: 0):
Error: invalid object key - _U (argument="transaction", value={"_U":0,"_V":0,"_W":null,"_X":null,"nonce":{"_U":0,"_V":0,"_W":null,"_X":null}}, key="_U", version=4.0.48)
i am using ether.js 4.0.48
@msohaib008 It's been quite a while since I've had to deal with ethers v4. Can you try upgrading to v5? I don't think wallet.sign would be the call you want to use, but if you switch to v5, I can provide more guidance as it is fresher in my mind. :)
okay i will try to upgrade to 5.0. thanks @ricmoo .
hope that it will not break my app
Most helpful comment
The
walletis thesigner, sorry, the third parameter to Contract should have beenwallet.