When I run the following code, it accurately gets the token balance for both addresses and the transaction even goes through (I can see it on the testnet), although no tokens are sent.
I've tried a variety of things including replacing the signed transaction piece with this:
await contract.methods.transfer(toAddress, 100000).send({
from: fromAddress
});
but that fails with an unknown account
error.
My Code for sending tokens:
const Web3 = require("web3");
const { hdkey } = require("ethereumjs-wallet");
const bip39 = require("bip39");
const token = require("./token.json");
const mnemonic = "12 word phrase";
const provider = "https://apis.ankr.com/.../binance/full/test";
(async() => {
try {
const seed = await bip39.mnemonicToSeed(mnemonic);
const root = hdkey.fromMasterSeed(seed);
const web3 = new Web3(provider);
const addrNode = root.derivePath(`m/44'/60'/0'/0/0`);
const wallet = addrNode.getWallet();
// #0 in the hdwallet, the owner of the tokens
const fromAddress = wallet.getAddressString();
// #1 in the hdwallet, already has a token balance
const toAddress = "0x...";
const contract = new web3.eth.Contract(token.abi, token.contract_address);
let fromAddressBalance = await contract.methods.balanceOf(fromAddress).call();
let toAddressBalance = await contract.methods.balanceOf(toAddress).call();
console.log(`Pre Transaction: Sender: ${fromAddressBalance} TOKENS / Wallet: ${toAddressBalance} TOKENS`);
// token has 3 decimal places, this is 100.000
const encodedABI = contract.methods.transfer(toAddress, 100000).encodeABI();
const tx = {
from: fromAddress,
to: toAddress,
gas: 2000000,
value: 0x0,
data: encodedABI
};
const signed = await web3.eth.accounts.signTransaction(tx, wallet.privateKey.toString("hex"));
const trans = await web3.eth.sendSignedTransaction(signed.rawTransaction);
fromAddressBalance = await contract.methods.balanceOf(fromAddress).call();
toAddressBalance = await contract.methods.balanceOf(toAddress).call();
console.log(`Post Transaction: Sender: ${fromAddressBalance} TOKENS / Wallet: ${toAddressBalance} TOKENS`);
} catch (err) {
console.error(err.stack);
}
process.exit();
})();
There were a few things wrong that once fixed resolved my issue. I haven't gone back through and tested which did it, or if all were required, but wanted to leave this for future explorers.
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
web3.eth.accounts.wallet.create();
web3.eth.accounts.wallet.add(account);
const privateKey = `0x${wallet.privateKey.toString("hex")}`;
const tx = {
from: fromAddress,
to: token.contract_address,
gas: 2000000,
value: 0x0,
data: encodedABI
};
Ultimately, I needed to take advantage of the contract's transfer method vs signing/sending a transaction
const result = await contract.methods.transfer(toAddress, 100).send({
from: fromAddress,
gas: 2000000
});