Hello,
is it possible to list and transfer ERC20 tokens from an ethers.js wallet?
I didn't find any sample in the documentation ๐
Thank you and keep up the great work ๐ ,
:panos
Seems like this is answering how to send tokens.
Now, is there a way to list the tokens that an ethers.js wallet is holding?
Thank you,
:panos
I think you should save the wallet's tokens by yourself, maybe in a database or local files etc.
I think it's difficult to know what tokens does a wallet have.
Maybe you can use the etherscan api: Get a list of "ERC20 - Token Transfer Events" by Address to get all wallet's token transaction and calculate what token the wallet have.
Maybe you can use the etherscan api: Get a list of "ERC20 - Token Transfer Events" by Address to get all wallet's token transaction and calculate what token the wallet have.
That's what I thought as well. But then I thought that this is such a common scenario that maybe the wallet itself supports it..
Thanks for your reply!
Sorry this took so long to get back to.
Yes, that is correct, you can just treat the token like any other contract. I will add a recipe to the cookbook though, for a more permanent example of transferring tokens.
There is no way to get a list of tokens a wallet has, in general. Luckily ERC-20 has a few design decisions to make this easier, although not all tokens adhere to all the specification. Also, events on a pruning node become unreliable after longer periods of time have elapsed, but you can use the Transfer(address, address, uint256) event to find all events, filtered by an address (you would likely want to query for both sent and received tokens).
I will add a recipe for this to the cookbook too, since it is a common task.
Any update on the recipe for transfer ECR20 tokens?
Hello @apollox-sys ,
the following code worked for my node.js service:
function sendToken(req, res, wallet, abi, ico_address) {
var to = req.query.to;
var amount = req.query.amount;
var contract = new ethers.Contract(ico_address, abi, wallet);
// How many tokens?
var numberOfDecimals = 18;
var numberOfTokens = ethers.utils.parseUnits(amount, numberOfDecimals);
// Send tokens
contract.transfer(to, numberOfTokens).then(function(transaction) {
res.send(transaction);
})
.catch(function(e){
res.status(400);
res.send(e.responseText);
})
}
Don't simply copy-paste it, since it contains some express library usage ๐
@le4ker this code fails with
Error: sending a transaction require a signer (operation="sendTransaction", version=4.0.4)
Any help around this error?
Sounds like you are not providing a signer to the contract instance. How are you instantiating the contract? Make sure you provide it a Signer (e.g. Wallet or JsonRpcSigner).
@ricmoo hm yes, it seams that you are correct.
const contract = new ethers.Contract(contractAddress, abi);
This is how I construct contract.
I added wallet as 3rd argument and the error changed.
my code
try {
const valueToSend = ethers.utils.parseUnits(value.toString(), this.numberOfDecimals);
const transaction = await this.contract.transfer('0x.....', valueToSend);
console.log(transaction);
} catch(error) {
console.log(error);
}
Error:
TypeError: Cannot read property 'getCode' of undefined
at Contract.deployed (~/node_modules/ethers/contract.js:344:48)
at Contract.transfer (~/node_modules/ethers/contract.js:135:26)
at Ethereum.sendToken (~app/common/ethereum/Ethereum.js:39:42)
at Ethereum.checkTransaction (~/app/common/ethereum/Ethereum.js:25:10)
How are you instantiating your wallet? My guess is now you need to add a provider to the Wallet. :)
let provider = ethers.getDefaultProvider();
let wallet = new ethers.Wallet(privateKey, provider);
let contract = new ethers.Contract(contractAddress, abi, wallet);
Let me know if that solves it. If so, then I need to add a better error message for when the provider on a Signer is unspecified for deployed. :)
well look
const provider = ethers.getDefaultProvider();
const wallet = await ethers.Wallet.fromEncryptedJson(JSON.stringify(encryptedWallet), password);
const contract = new ethers.Contract(contractAddress, abi, wallet);
this is how I created wallet. What am I doing wrong here :/
Oh! So, you can use:
const provider = ethers.getDefaultProvider();
// You can do this in one step, just splitting it apart and giving it weird names so it is more
// obvious what is happening
let walletWithoutProvider = await ethers.Wallet.fromEncryptedJson(JSON.stringify(encryptedWallet), password);
let walletWithProvider = walletWithoutProvider.connect(provider);
const contract = new ethers.Contract(contractAddress, abi, wallet)
Nice @ricmoo thanks! Should consider creating a series of tutorials regarding ERC20 tokens this would really help you popularize your library :) thanks again
No worries! Feel free to reach out if you have any further issues.
It's in the works. It will be a whole section in the Cook Book in the documentation... :)
// Send tokens
contract.transfer(targetAddress, numberOfTokens).then(function(tx) {
console.log(tx);
});
got error ๏ผ
Error in mounted hook: "TypeError: contract.transfer is not a function"
Heya @motopig! :)
How are you creating the contract instance?
thanks for your reply ๐
creating contract instance
let privateKey = '0xsdfdfsdfs';
let provider = ethers.getDefaultProvider('rinkeby');
let wallet = new ethers.Wallet(privateKey, provider);
let contractAddress = "0xsswwwfdfdsf";
let contract = new ethers.Contract(contractAddress, abi, wallet);
Where is abi coming from? That's the important part. :)
must use the contract abi which i write in the code let contractAddress = "0xsswwwfdfdsf"; ?
The contract address only specifies the location of the contract on the blockchain, not what the contract ABI is. The Contract class is a meta-class, it will have only the methods which the ABI has specified.
You probably want something like:
let abi = [
"function transfer(address to, uint amount)"
];
so that the contract "knows" about transfer(address,uint256).
Nice @ricmoo thanks!
i just got wrong conception of abi , problem resolved
thanks again
No problem. Glad I could help. :)
I implemented a function sendERC20Token() here https://github.com/soulmachine/coin-wallets/blob/master/src/chains/eth.ts#L196
Most helpful comment
Sorry this took so long to get back to.
Yes, that is correct, you can just treat the token like any other contract. I will add a recipe to the cookbook though, for a more permanent example of transferring tokens.
There is no way to get a list of tokens a wallet has, in general. Luckily ERC-20 has a few design decisions to make this easier, although not all tokens adhere to all the specification. Also, events on a pruning node become unreliable after longer periods of time have elapsed, but you can use the
Transfer(address, address, uint256)event to find all events, filtered by an address (you would likely want to query for both sent and received tokens).I will add a recipe for this to the cookbook too, since it is a common task.