web3 / web3.js

Collection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.
https://web3js.org/
Other
19.4k stars 4.97k forks source link

Transferring ERC20 tokens from account using web3 over Ropsten #1151

Closed greggmojica closed 6 years ago

greggmojica commented 7 years ago

I created a contract token using the sample solidity code tutorial. It has a function called transfer to send tokens between accounts:

function transfer(address _to, uint256 _value)

I need to now connect to this contract using web3, and then send a certain number of tokens generated to another account. I've been struggling with how to do this for quite some time and hoping this community could help. Here is what I have thus far, using web3 version 0.20.0:

```const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new 
web3.providers.HttpProvider("https://ropsten.infura.io/XXXXXX"));
var abi = [ {} ] // redacted on purpose
var count = web3.eth.getTransactionCount("0x9...");
var abiArray = abi;
var contractAddress = "0x2...";
var contract =  web3.eth.contract(abiArray).at(contractAddress);

var data = contract.transfer.getData("0x2...", 10000, {from: "0x9..."});
var gasPrice = web3.eth.gasPrice;
var gasLimit = 90000;

var rawTransaction = {
  "from": "0x9...",
  "nonce": web3.toHex(count),
  "gasPrice": web3.toHex(gasPrice),
  "gasLimit": web3.toHex(gasLimit),
  "to": "0x2...",
  "value": "0x1",
  "data": data,
  "chainId": 0x03
};

var privKey = new Buffer('XXXXXXXXXXXXXX', 'hex');
var tx = new Tx(rawTransaction);

tx.sign(privKey);
var serializedTx = tx.serialize();

web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
  if (!err)
      console.log(hash);
  else
      console.log(err);
});```

This transaction works but it's sending ether as opposed to the actual ERC20 token. I'm really at a loss for why this is the case and would appreciate any help whatsoever.

jdkanani commented 7 years ago

Use following -

rawTransaction.from = "0x9..."; // as you have set in example
rawTransaction.value = 0; // as you don't want to send ether with transaction
rawTransaction.to = tokenAddress;
rawTransaction.data = contract.transfer.getData(userAddress, tokenValues); // user's address is the address you want to send tokens to.
Nishchit14 commented 6 years ago

a new version of web3 1.x

 tx = {
  value: '0x0', 
  from: from,
  to: Contract._address,
  data: Contract.methods.transfer(to, 1000).encodeABI(),  
}
sherhan361 commented 6 years ago

Hello! Give me, please, an example of the working code for sending tokens for the version of web3@1.0.0-beta.27. I'm trying to write code for these examples. But there are a lot of mistakes related to the irrelevance of the data. I think that it will be useful to many. Thank you!

FradSer commented 6 years ago

Single-address allocation of MineFIL Token (MFIL) code which was written and tested using web3 version 1.0.0-beta.29.

Check the MFIL Ethereum Smart Contract Scripts for more.

// Dotenv javascript libraries needed
require('dotenv').config();
// Ethereum javascript libraries needed
var Web3 = require('web3');
var Tx = require('ethereumjs-tx');
// Rather than using a local copy of geth, interact with the ethereum blockchain via infura.io
// The key for infura.io is in .env
const web3 = new Web3(Web3.givenProvider || "https://ropsten.infura.io/" + process.env["INFURA_KEY"])
// Fixed-point notation for number of MFIL which is divisible to 3 decimal places
function financialMfil(numMfil) {
    return Number.parseFloat(numMfil / 1e3).toFixed(3);
}
// Create an async function so I can use the "await" keyword to wait for things to finish
const main = async () => {
    // This code was written and tested using web3 version 1.0.0-beta.29
    console.log(`web3 version: ${web3.version}`)
    // Who holds the token now?
    var myAddress = "0x644dE7C3f6425D8920332FC6C97Fbf7e04445C74";
    // Who are we trying to send this token to?
    var destAddress = "0xE3A029F6cA0C32a9E6c9a2154790Ea0A92cb2621";
    // MineFIL Token (MFIL) is divisible to 3 decimal places, 1 = 0.001 of MFIL
    var transferAmount = 1;
    // Determine the nonce
    var count = await web3.eth.getTransactionCount(myAddress);
    console.log(`num transactions so far: ${count}`);
    // MineFILToekn contract ABI Array
    var abiArray = [{
        "constant": true,
        "inputs": [],
        "name": "name",
        "outputs": [{
            "name": "",
            "type": "string"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "constant": false,
        "inputs": [{
            "name": "_spender",
            "type": "address"
        }, {
            "name": "_value",
            "type": "uint256"
        }],
        "name": "approve",
        "outputs": [{
            "name": "",
            "type": "bool"
        }],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "constant": true,
        "inputs": [],
        "name": "totalSupply",
        "outputs": [{
            "name": "",
            "type": "uint256"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "constant": false,
        "inputs": [{
            "name": "_from",
            "type": "address"
        }, {
            "name": "_to",
            "type": "address"
        }, {
            "name": "_value",
            "type": "uint256"
        }],
        "name": "transferFrom",
        "outputs": [{
            "name": "",
            "type": "bool"
        }],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "constant": true,
        "inputs": [],
        "name": "INITIAL_SUPPLY",
        "outputs": [{
            "name": "",
            "type": "uint256"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "constant": true,
        "inputs": [],
        "name": "decimals",
        "outputs": [{
            "name": "",
            "type": "uint8"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "constant": false,
        "inputs": [{
            "name": "_spender",
            "type": "address"
        }, {
            "name": "_subtractedValue",
            "type": "uint256"
        }],
        "name": "decreaseApproval",
        "outputs": [{
            "name": "",
            "type": "bool"
        }],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "constant": true,
        "inputs": [{
            "name": "_owner",
            "type": "address"
        }],
        "name": "balanceOf",
        "outputs": [{
            "name": "balance",
            "type": "uint256"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "constant": true,
        "inputs": [],
        "name": "symbol",
        "outputs": [{
            "name": "",
            "type": "string"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "constant": false,
        "inputs": [{
            "name": "_to",
            "type": "address"
        }, {
            "name": "_value",
            "type": "uint256"
        }],
        "name": "transfer",
        "outputs": [{
            "name": "",
            "type": "bool"
        }],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "constant": false,
        "inputs": [{
            "name": "_spender",
            "type": "address"
        }, {
            "name": "_addedValue",
            "type": "uint256"
        }],
        "name": "increaseApproval",
        "outputs": [{
            "name": "",
            "type": "bool"
        }],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    }, {
        "constant": true,
        "inputs": [{
            "name": "_owner",
            "type": "address"
        }, {
            "name": "_spender",
            "type": "address"
        }],
        "name": "allowance",
        "outputs": [{
            "name": "",
            "type": "uint256"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }, {
        "inputs": [],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "constructor"
    }, {
        "anonymous": false,
        "inputs": [{
            "indexed": true,
            "name": "owner",
            "type": "address"
        }, {
            "indexed": true,
            "name": "spender",
            "type": "address"
        }, {
            "indexed": false,
            "name": "value",
            "type": "uint256"
        }],
        "name": "Approval",
        "type": "event"
    }, {
        "anonymous": false,
        "inputs": [{
            "indexed": true,
            "name": "from",
            "type": "address"
        }, {
            "indexed": true,
            "name": "to",
            "type": "address"
        }, {
            "indexed": false,
            "name": "value",
            "type": "uint256"
        }],
        "name": "Transfer",
        "type": "event"
    }]
    // The address of the contract which created MFIL
    var contractAddress = "0x1564A92a0870aF0eBf1F015f5FD223abaA3505CA";
    var contract = new web3.eth.Contract(abiArray, contractAddress, {
        from: myAddress
    });
    // How many tokens do I have before sending?
    var balance = await contract.methods.balanceOf(myAddress).call();
    console.log(`Balance before send: ${financialMfil(balance)} MFIL\n------------------------`);
    // I chose gas price and gas limit based on what ethereum wallet was recommending for a similar transaction. You may need to change the gas price!
    // Use Gwei for the unit of gas price
    var gasPriceGwei = 3;
    var gasLimit = 3000000;
    // Chain ID of Ropsten Test Net is 3, replace it to 1 for Main Net
    var chainId = 3;
    var rawTransaction = {
        "from": myAddress,
        "nonce": "0x" + count.toString(16),
        "gasPrice": web3.utils.toHex(gasPriceGwei * 1e9),
        "gasLimit": web3.utils.toHex(gasLimit),
        "to": contractAddress,
        "value": "0x0",
        "data": contract.methods.transfer(destAddress, transferAmount).encodeABI(),
        "chainId": chainId
    };
    console.log(`Raw of Transaction: \n${JSON.stringify(rawTransaction, null, '\t')}\n------------------------`);
    // The private key for myAddress in .env
    var privKey = new Buffer(process.env["PRIVATE_KEY"], 'hex');
    var tx = new Tx(rawTransaction);
    tx.sign(privKey);
    var serializedTx = tx.serialize();
    // Comment out these four lines if you don't really want to send the TX right now
    console.log(`Attempting to send signed tx:  ${serializedTx.toString('hex')}\n------------------------`);
    var receipt = await web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'));
    // The receipt info of transaction, Uncomment for debug
    console.log(`Receipt info: \n${JSON.stringify(receipt, null, '\t')}\n------------------------`);
    // The balance may not be updated yet, but let's check
    balance = await contract.methods.balanceOf(myAddress).call();
    console.log(`Balance after send: ${financialMfil(balance)} MFIL`);
}
main();
nickjuntilla commented 6 years ago

@FradSer I get "SyntaxError: await is only valid in async function" when I run your code.

nickjuntilla commented 6 years ago

Not sure how people are using data: Contract.methods.transfer(to, 1000).encodeABI()

My web3 version is '0.20.4'

nickjuntilla commented 6 years ago

So apparently FradSer through in async in there and then everything has changed to promises in the current web3, which may or may not be people have. To anyone else trying to figure out everything posted online is different try starting with this web3 version: "^1.0.0-beta.29"

neohq commented 6 years ago

@nickjuntilla That piece of code you mentioned is from web3 1.0.0 (beta).

The code from @FradSer helped me finish mine, so big thanks!

FradSer commented 6 years ago

@nickjuntilla The code is written by 1.0.0-beta.29 , update your web3.

ethan-deng commented 6 years ago

The issue in the original question is that

var data = contract.transfer.getData("0x2...", 10000, {from: "0x9..."});

should be

var data = contract.transfer.getData("to_user_account_address_not_the_contract_address", 10000);

Use to user account address here but not the contract address. No need to use {from: "...} here.

Use the contract address in the raw transaction.

sathyamlokare commented 6 years ago

How do I deploy a contract by signing the transaction and unlocking the account using web3 ? Can anybody give a code snippet ? @FradSer please ?

neohq commented 6 years ago

@sathyamlokare You don't need to unlock the account if you are signing the transaction using a privateKey. Here is a 100% functional code, if you have questions please ask.

PS: args is a JSON that is sent from the front-end UI. It's just how I did it on my dev code.


        // Get args from front-end
        const args = JSON.parse(req.body.data)

        const gasPrice = await eth.getGasPrice()
        const gasPriceHex = web3.utils.toHex(gasPrice)
        const nonce = await eth.getTransactionCount( args['account'] )
        const nonceHex = web3.utils.toHex(nonce)

        const privateKey = new Buffer( args['privateKey'], 'hex')

        // JsonInterface data
        const jsonInterface = fs.readFileSync("json/contract-jsonInterface.json", 'utf8');

        // Contract byteCode
        const contractByteCode = fs.readFileSync("json/contract-bytecode.txt", 'utf8');

        // Create contract
        let contract = new eth.Contract(JSON.parse( jsonInterface ), null, {
            data: contractByteCode,
        } );

        // Init contract deploy
        let contractDeploy = await contract.deploy({
            arguments: [ args['initialSupply'], args['tokenName'], args['tokenSymbol'] ]
        })

        // Get estimated gas
        const estimatedGas = await contractDeploy.estimateGas();

        const rawTx = {
            nonce: nonceHex,
            gasPrice: gasPriceHex,
            gasLimit: web3.utils.toHex( estimatedGas + 10000 ),
            data: contractDeploy.encodeABI()
        }

        let tx = new Tx(rawTx)
        tx.sign(privateKey)

        const serializedTx = tx.serialize()

        // Send signed transaction
        let receipt = await eth.sendSignedTransaction( '0x' + serializedTx.toString('hex'))
            .on('error', function(error){
                console.log("-> error")
                console.log(error.message)
            })
            .on('transactionHash', function(transactionHash){
                console.log("-> transactionHash")
                console.log(transactionHash)
            })
            .on('receipt', function(receipt){
                console.log("-> receipt")
                console.log(receipt.contractAddress) // contains the new contract address
            })
            .on('confirmation', function(confirmationNumber, receipt){
                console.log("-> confirmation " + confirmationNumber)
            })
sathyamlokare commented 6 years ago

@neohq can you help me with this , everything works fine here gets deployed. But it says TransactionReciept Status failed

var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider("https://rinkeby.infura.io/022KbD1NPdb2YQ0Wi6vC"));

var Tx = require('ethereumjs-tx');
const testHashCoinAdvanced = require('./build/TokenERC20.json');

var privateKey = new Buffer('f6da78c45601d9ae02fcdb161e44a15a99e5e1fb1aa931dd95366add5dec367e', 'hex')

const deploy = async()=>{

           var contract = new web3.eth.Contract(JSON.parse(testHashCoinAdvanced[':TokenERC20'].interface));
          const hexdata = contract.deploy({
              data: '0x' + testHashCoinAdvanced[':TokenERC20'].bytecode,
              arguments:[1000,"HashCoin","HC"]
           }).encodeABI()

           const nonce = await web3.eth.getTransactionCount( "0x7Fb11F6A52e20BDFfaa08c468cD4848b901b7B70" );
           const nonceHex = web3.utils.toHex(nonce)
const gasPriceHex = web3.utils.toHex(3 * 1e9);
// const estimatedGas = await testCoinContractDeploy.estimateGas();
  var rawTx = {
      nonce: nonceHex,
      gasPrice: web3.utils.toHex(30000000000),
      gasLimit: web3.utils.toHex(6100500),
      data: "0x"+hexdata
  }

  var tx = new Tx(rawTx);
  tx.sign(privateKey);

  var serializedTx = tx.serialize();

  console.log(serializedTx.toString('hex')); 

  web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'))
      .on('receipt', console.log);

};
deploy();

you can check the transactions here https://rinkeby.etherscan.io/address/0x7fb11f6a52e20bdffaa08c468cd4848b901b7b70

jdkanani commented 6 years ago

@sathyamlokare Increase gas limit and try again.

sathyamlokare commented 6 years ago

@jdkanani I did that also, still getting the error

neohq commented 6 years ago

@sathyamlokare If you are using Geth as a blockchain client, use 1.7.3 version, you are probably using the latest version 1.8.1 or 1.8.2 which has that problem you are describing. You can take if from here https://ethereum.github.io/go-ethereum/downloads/

Using geth parameter --datadir you should point this version to another folder, to prevent overriding the default one .ethereum. Point 1.7.3 to .ethereum_1.7.3 for example.

xntop commented 6 years ago

@neohq hello, i use your code, but has some errors when exec contract, this trans hash is https://rinkeby.etherscan.io/tx/0x77d854d47d65681e23f4780af45cb8cd7f935ee8a47a2249ac1fd7887cc21432 . and the code is let options = { from: from, gasPrice: self.web3.utils.toHex(results.gasPrice), gas: self.web3.utils.toHex(800000) } const erc20Contract = new self.web3.eth.Contract(erc20Abi, '0x95Ed5d52531a743F3776C784a07746d9FbfCFc5e', options) var tx = new Tx({ from : from, to: erc20Contract._address, nonce: results.nonce, gasPrice: self.web3.utils.toHex(results.gasPrice), gasLimit: self.web3.utils.toHex(800000),//results.gasEstimate value: 0x0, data: erc20Contract.methods.transfer(to, amount).encodeABI() }); tx.sign(new Buffer(privateKey, 'hex')); self.web3.eth.sendSignedTransaction('0x' + tx.serialize().toString('hex'), function (err, response) { if (err !== null) return reject(err) return resolve(response) })

can you help me ? thank you, i think is contract error, but i dont konw .

thontrancong commented 6 years ago

@greggmojica I try and success. Thank many.

shahzadthathal commented 6 years ago

var privKey = new Buffer(process.env["PRIVATE_KEY"], 'hex');

How can I use new Buffer(key) in browser application? where should I get this file and include in my web app page?

LF-DevJourney commented 6 years ago

Refer to Send ERC20 token with web3

ManUnit commented 6 years ago

I was deploy smart contract to my private network and then tested got output as below

node send.js web3 version: 1.0.0-beta.34 num transactions so far: 10 Balance before send: 9.99999e+22 MFIL

Raw of Transaction: { "from": "0x82378cf137F5dF4FA730529eB79a4583EA605FA9", "nonce": "0xa", "gasPrice": "0xb2d05e00", "gasLimit": "0x2dc6c0", "to": "0xf1d28bac210b14b75e6ce1d529a1221c17579bfe", "value": "0x0", "data": "0xa9059cbb0000000000000000000000002c29f4c04d9acf4878a52c786b440698748783580000000000000000000000000000000000000000000000000000000000000001", "chainId": 9559 }

(node:13335) UnhandledPromiseRejectionWarning: TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object. at Function.Buffer.from (buffer.js:183:11) at new Buffer (buffer.js:158:17) at main (/opt/tokens/send.js:42:19) at at process._tickCallback (internal/process/next_tick.js:188:7) (node:13335) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:13335) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

JS Code as below :

require('dotenv').config();
var path = require('path');
var fs = require('fs');
var Web3 = require('web3');
var Tx = require('ethereumjs-tx');
const web3 = new Web3(Web3.givenProvider || "http://202.xxx.xxx.xxx:8545")
function financialMfil(numMfil) {
    return Number.parseFloat(numMfil / 1e3).toFixed(3);
}
const main = async () => {
    console.log(`web3 version: ${web3.version}`)
    var myAddress = "0x82378cf137F5dF4FA730529eB79a4583EA605FA9";
    var destAddress = "0x2c29f4c04D9Acf4878A52C786B44069874878358";
    var transferAmount = 1;
    var count = await web3.eth.getTransactionCount(myAddress);
    console.log(`num transactions so far: ${count}`);
    var abiArray = JSON.parse(fs.readFileSync(path.resolve(__dirname, './erc20_abi.json'), 'utf-8'));
    var contractAddress = "0xf1d28bac210b14b75e6ce1d529a1221c17579bfe";
    var contract = new web3.eth.Contract(abiArray, contractAddress, {
        from: myAddress
    });
    var balance = await contract.methods.balanceOf(myAddress).call();
    console.log(`Balance before send: ${financialMfil(balance)} MFIL\n------------------------`);
    // I chose gas price and gas limit based on what ethereum wallet was recommending for a similar transaction. You may need to change the gas price!
    // Use Gwei for the unit of gas price
    var gasPriceGwei = 3;
    var gasLimit = 3000000;
    // Chain ID of Ropsten Test Net is 3, replace it to 1 for Main Net
    var chainId = 9559;
    var rawTransaction = {
        "from": myAddress,
        "nonce": "0x" + count.toString(16),
        "gasPrice": web3.utils.toHex(gasPriceGwei * 1e9),
        "gasLimit": web3.utils.toHex(gasLimit),
        "to": contractAddress,
        "value": "0x0",
        "data": contract.methods.transfer(destAddress, transferAmount).encodeABI(),
        "chainId": chainId
    };
    console.log(`Raw of Transaction: \n${JSON.stringify(rawTransaction, null, '\t')}\n------------------------`);
    // The private key for myAddress in .env
    var privKey = new Buffer(process.env["PRIVATE_KEY"], 'hex');
    var tx = new Tx(rawTransaction);
    tx.sign(privKey);
    var serializedTx = tx.serialize();
    // Comment out these four lines if you don't really want to send the TX right now
    console.log(`Attempting to send signed tx:  ${serializedTx.toString('hex')}\n------------------------`);
    var receipt = await web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'));
    // The receipt info of transaction, Uncomment for debug
    console.log(`Receipt info: \n${JSON.stringify(receipt, null, '\t')}\n------------------------`);
    // The balance may not be updated yet, but let's check
    balance = await contract.methods.balanceOf(myAddress).call();
    console.log(`Balance after send: ${financialMfil(balance)} MFIL`);
}
main();
PaulRBerg commented 6 years ago

Circumstance

I have followed all indications from here and StackOverflow, the transaction gets broadcasted but no tokens are transferred.

When I check the balance again, it's the same as before (10,000).

const Tx = require('ethereumjs-tx');

const config = require('../config');
const contract = require('../contract');
const web3 = require('../web3');

const main = async () => {
    try {
        const count = await web3.eth.getTransactionCount(config.accounts[0]);
        const nonce = web3.utils.toHex(count);
        const txValue = web3.utils.toHex(parseInt(process.argv[2], 10) || 10);

        const from = web3.utils.toChecksumAddress(config.accounts[0]);
        const to = web3.utils.toChecksumAddress(config.accounts[1]);

        const rawTx = {
            nonce: nonce,
            from: from,
            to: to,
            value: '0x0',
            gasLimit: '0x30D40', // 54,000
            gasPrice: '0x2CB417800', // 12 gwei
            data: contract.methods.transfer(to, txValue).encodeABI(),
            chainId: '0x03'
        };

        const privateKey = Buffer.from(config.private, 'hex');
        const tx = new Tx(rawTx);
        tx.sign(privateKey);
        const serializedTx = tx.serialize();

        const receipt = await web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'));
        console.log(`Receipt info:  ${JSON.stringify(receipt, null, '\t')}`);

        console.log(`From\'s balance after transfer: ${await contract.methods.balanceOf(from).call()}`);
        console.log(`To\'s balance after transfer: ${await contract.methods.balanceOf(to).call()}`);
    } catch (err) {
        console.log(err);
    }
};

main();

Tools

• node 9.3.0 • web3 1.0.0-beta.34 • os osx 13.13.3

Update

Solved. I was sending the tx to the other account by mistake, not to the contract. More details here.

ManUnit commented 6 years ago

My error fixed ! just put private key

ManUnit commented 6 years ago

@PaulRBerg you try use FradSer script above
seem to be you don't have ABI JSON

    var abiArray = JSON.parse(fs.readFileSync(path.resolve(__dirname, './erc20_abi.json'), 'utf-8'));
    var contract = new web3.eth.Contract(abiArray, contractAddress, {
        from: myAddress
    });
PaulRBerg commented 6 years ago

@hs1gab I have it at line 4 const contract = require('../contract'); Inside that file:

const path = require('path');

const config = require('./config');
const web3 = require('./web3');

const ABI = require(path.join(__dirname, '..', 'build', 'contracts', 'PaulCoin.json')).abi;
const contract = new web3.eth.Contract(ABI, config.contract, { from: config.accounts[0] });

module.exports = contract;

As I previously stated, I can read the balance. I also can transfer ETH, only when trying to move tokens there are problems.

ManUnit commented 6 years ago

@PaulRBerg Have you been move token by manual in Remix solidity by function transfer ? just for check account able to basic token move first

or in your code try change

 const txValue = web3.utils.toHex(parseInt(process.argv[2], 10) || 10); 

  // to

 const txValue = "12300000000000000000" ;

// or 

 var VALUE_TOKEN = "12300000000000000000" ; // cause of 18  decimal
  const txValue = web3.utils.toWei( VALUE_TOKEN , "ether") ;      
marknguyen85 commented 6 years ago

@greggmojica when call to

var data = contract.transfer.getData("0x2...", 10000, {from: "0x9..."});

then throw

RuntimeError: Function transfer is not constant: transfer, requires to sign transaction

tangjielong commented 6 years ago

thank you very mach!i get it.

srishidev10 commented 6 years ago

@PaulRBerg Your Code works For transfer . But I want to transfer between two externally Owned accounts. How to do that?

ManUnit commented 6 years ago

@greggmojica

try use var data = contract.methods.transfer(<to address>, <value>);

tangjielong commented 6 years ago

How do you use infura to get the user's key for (var private key = new Buffer ('f6da78c45601d9ae02fcdb161e44a15a99e1fb1aa931dd95366add5dec367e', hex'))

PaulRBerg commented 6 years ago

@srishidev10 You can't have a contract sign a tx between two parties. You have these options though:

  1. Transfer the ether from account A to the contract and then, based on some logic, let B withdraw the funds.
  2. Use a token or WETH to get access to ERC20's approve function.

More on that here. However, I think we diverged. @greggmojica should close this issue if the initial problems were solved.

nivida commented 6 years ago

Please ask further questions on https://ethereum.stackexchange.com/

grinsteindavid commented 5 years ago

// This is my code after one week trying a lot of tutorials. Thanks internet

const fs = require('fs'); const path = require('path'); const Web3API = require('web3'); const axios = require('axios');

/**

const main = async () => { const web3 = new Web3API(new Web3API.providers.HttpProvider('https://mainnet.infura.io')); const privateKey = "0x...."; const tokenAddress = "0x...."; const fromAddress = "0x...."; const toAddress = "0x....";

// ABI to transfer ERC20 Token
let abi = JSON.parse(fs.readFileSync(path.join(__dirname, '.', 'main_contract.json'), 'utf-8'));
// calculate ERC20 token amount ( 18 decimals )
let amount = 1;
let tokenAmount = web3.utils.toWei(amount.toString(), 'ether')
// Get ERC20 Token contract instance
let contract = new web3.eth.Contract(abi, tokenAddress, {
    from: fromAddress
});
// How many tokens do I have before sending?
let balance = await contract.methods.balanceOf(fromAddress).call();
console.log(`Balance before send: ${balance}`);
// EIP 155 - List of Chain ID's:
const chainList = {
    mainnet: 1,
    morden: 2,
    ropsten: 3,
    rinkeby: 4,
    ubiqMainnet: 8,
    ubiqTestnet: 9,
    rootstockMainnet: 30,
    rootstockTestnet: 31,
    kovan: 42,
    ethereumClassicMainnet: 61,
    ethereumClassicTestnet: 62,
    ewasmTestnet: 66,
    gethPrivateChains: 1337
};
// The gas price is determined by the last few blocks median gas price.
const avgGasPrice = await web3.eth.getGasPrice();
// current transaction gas prices from https://ethgasstation.info/
const currentGasPrices = await getCurrentGasPrices();
/**
 * With every new transaction you send using a specific wallet address,
 * you need to increase a nonce which is tied to the sender wallet.
 */
let nonce = web3.eth.getTransactionCount(fromAddress);
// Will call estimate the gas a method execution will take when executed in the EVM without.
let estimateGas = await web3.eth.estimateGas({
    "value": '0x0', // Only tokens
    "data": contract.methods.transfer(toAddress, tokenAmount).encodeABI(),
    "from": fromAddress,
    "to": toAddress
});
console.log({
    estimateGas: estimateGas
});
// Build a new transaction object.
const transaction = {
    "value": '0x0', // Only tokens
    "data": contract.methods.transfer(toAddress, tokenAmount).encodeABI(),
    "from": fromAddress,
    "to": toAddress,
    "gas": web3.utils.toHex(estimateGas * 1.10),
    "gasLimit": web3.utils.toHex(estimateGas * 1.10),
    "gasPrice": web3.utils.toHex(Math.trunc(currentGasPrices.medium * 1e9)),
    "chainId": web3.utils.toHex(chainList.mainnet)
};
// Creates an account object from a private key.
const senderAccount = web3.eth.accounts.privateKeyToAccount(privateKey);
/**
* This is where the transaction is authorized on your behalf.
* The private key is what unlocks your wallet.
*/
const signedTransaction = await senderAccount.signTransaction(transaction);
console.log({
    transaction: transaction,
    amount: amount,
    tokenAmount: tokenAmount,
    avgGasPrice: avgGasPrice,
    signedTransaction: signedTransaction
});

// We're ready! Submit the raw transaction details to the provider configured above.
try {
    const receipt = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);

    console.log({
        receipt: receipt
    });

} catch (error) {
    console.log({
        error: error.message
    });
}

};

main();

Cucak commented 3 years ago

What I dont understand is there any difference when you send token from one wallet address to other wallet address, and when you want to basically buy token with a wallet address from the smart contract of the token?