Transfer token
transfer token from miner 2 on Geth console by contract object
> eth.accounts
["0x4d0362700bcdc69e2e4e083c3f098ca55efd1119"]
> var contract = web3.eth.contract(abi)
undefined
> var instance = contract.at('0xf13c9660190749124ad90c8defc77cc6c5d36494');
undefined
> instance.symbol()
"YEN"
> instance.balanceOf('0xaeF72A6461e5392e9fa1537372b98701780a1819')
0
> instance.transfer('0xaeF72A6461e5392e9fa1537372b98701780a1819', web3.toWei(999, 'ether'))
Error: invalid address
at web3.js:3930:15
at web3.js:3756:20
at web3.js:5025:28
at map (<native code>)
at web3.js:5024:12
at web3.js:5050:18
at web3.js:5075:23
at web3.js:4137:16
at apply (<native code>)
at web3.js:4223:16
> instance.transfer('0xaeF72A6461e5392e9fa1537372b98701780a1819', web3.toWei(999, 'ether'), { from: eth.coinbase })
INFO [12-25|11:16:16] Submitted transaction fullhash=0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031 recipient=0xf13C9660190749124AD90C8dEfC77cC6c5D36494
"0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031"
> instance.balanceOf('0xaeF72A6461e5392e9fa1537372b98701780a1819')
999000000000000000000
> eth.getTransaction("0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031")
{
blockHash: "0xa05f41a144e500df9d235b483fa8112df706b44fbcea1f40bdfd2dee7fde9722",
blockNumber: 44,
from: "0x4d0362700bcdc69e2e4e083c3f098ca55efd1119",
gas: 90000,
gasPrice: 18000000000,
hash: "0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031",
input: "0xa9059cbb000000000000000000000000aef72a6461e5392e9fa1537372b98701780a181900000000000000000000000000000000000000000000003627e8f712373c0000",
nonce: 8,
r: "0x5972ba41a88e662aca23d3324aa73244226a1f40b7a55861fab77222a49f6935",
s: "0x1ad21dc1f96e288fd15284376ed4ee298363e4954fe41468dfdf232bfdca712",
to: "0xf13c9660190749124ad90c8defc77cc6c5d36494",
transactionIndex: 0,
v: "0x11ba9",
value: 0
}
> eth.getTransactionReceipt("0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031")
{
blockHash: "0xa05f41a144e500df9d235b483fa8112df706b44fbcea1f40bdfd2dee7fde9722",
blockNumber: 44,
contractAddress: null,
cumulativeGasUsed: 52111,
from: "0x4d0362700bcdc69e2e4e083c3f098ca55efd1119",
gasUsed: 52111,
logs: [{
address: "0xf13c9660190749124ad90c8defc77cc6c5d36494",
blockHash: "0xa05f41a144e500df9d235b483fa8112df706b44fbcea1f40bdfd2dee7fde9722",
blockNumber: 44,
data: "0x00000000000000000000000000000000000000000000003627e8f712373c0000",
logIndex: 0,
removed: false,
topics: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000004d0362700bcdc69e2e4e083c3f098ca55efd1119", "0x000000000000000000000000aef72a6461e5392e9fa1537372b98701780a1819"],
transactionHash: "0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031",
transactionIndex: 0
}],
logsBloom: "0x00000200000000000000000500000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000002000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000",
root: "0x0fc99e552cbeb92d44d8986a81631dabe3503c35a4eee7330f91d02832c57a1b",
to: "0xf13c9660190749124ad90c8defc77cc6c5d36494",
transactionHash: "0x4a1d5b4de007e5232962ebd63976d24290295b6e00189b9a15a928bb17a47031",
transactionIndex: 0
}
using send raw transaction of JSON-RPC API
First, I have to hash the transfer(address _to, uint256 _value)
and then take first ten letters to be the method Id.
> web3.sha3('transfer(address,uint256)').substring(0,10)
"0xa9059cbb"
And prefix to
address with zero, hex the value.
> web3.toHex(web3.toWei(2.345, "ether"))
"0x208b1d135e4a8000"
Then append them to method id, to makes the input data.
static final String PLACEHOLDER = "000000000000000000000000";
String TRANSFER = "0xa9059cbb";
public static byte[] makeInputDataForTransferMethod(@NonNull String toAddress, @NonNull BigInteger valueInWei) {
final String hexWithoutPrefix0x = removePrefix0x(toAddress);
final String valueHaxWithoutPrefix0x = prefix0In64Digital(toHexWithoutPrefix0x(valueInWei));
return ByteString.decodeHex(removePrefix0x(TRANSFER) + PLACEHOLDER + hexWithoutPrefix0x + valueHaxWithoutPrefix0x).toByteArray();
}
Second, I have to sign below transaction.
{
"chain": 36291,
"nonce": 2,
"from": "0xaeF72A6461e5392e9fa1537372b98701780a1819",
"to": "0xf13C9660190749124AD90C8dEfC77cC6c5D36494",
"gas": 60000,
"gasPrice": 20000000000,
"value": 0,
"input": "0xa9059cbb00000000000000000000000088dd6b191d4bca6b059dd35ac0cffb2ffd072d62000000000000000000000000000000000000000000000000208b1d135e4a8000"
}
@NonNull
private Transaction makeSignedTxForTransferToken(@NonNull String password, @IntRange(from = 0) long nonce, @NonNull String toAddress, long gasLimit, long gasPrice, @NonNull BigInteger amount)
throws Exception {
final Transaction tx = Geth.newTransaction(
nonce,
new Address(contractAddress),
new BigInt(0),
new BigInt(gasLimit),
new BigInt(gasPrice),
makeInputDataForTransferMethod(toAddress, amount)
);
unlock(password);
final Transaction result = keyStore.signTx(getFirstAccount(), tx, new BigInt(networkId));
lock();
return result;
}
Then getting the RLP encoded transaction by below Java program.
@NonNull
private String makeSignedRlpTxHex(@NonNull Transaction signedTx) throws Exception {
return PREFIX_HEX + ByteString.of(signedTx.encodeRLP()).hex();
}
Finally, doing the HTTP POST
request with below body.
request
{ "jsonrpc":"2.0", "method":"eth_sendRawTransaction", "params":["0xf8ac028504a817c80082ea6094f13c9660190749124ad90c8defc77cc6c5d3649480b844a9059cbb00000000000000000000000088dd6b191d4bca6b059dd35ac0cffb2ffd072d62000000000000000000000000000000000000000000000000208b1d135e4a800083011ba9a0daf4a5ea69c253de73bee8dc39ac9d1bf671feba59a54773841ed77552ee3df5a065ee2c9f6ea2014efa19d5998bb61b3a88cd358d798046dc5ef5c9b4fdaa7a78"], "id":63 }
response
{ "jsonrpc": "2.0", "id": 63, "result": "0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc" }
miner 2 console
> INFO [01-02|16:14:29] Submitted transaction fullhash=0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc recipient=0xf13C9660190749124AD90C8dEfC77cC6c5D36494 > INFO [01-02|16:17:42] Starting mining operation INFO [01-02|16:17:42] Commit new mining work number=110 txs=1 uncles=0 elapsed=3.189ms > eth.getTransaction("0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc") { blockHash: "0x5383b71065dadf8fb7b91bdecf65cefd771f0ae4487e2d559fece25e6e011bd4", blockNumber: 110, from: "0xaef72a6461e5392e9fa1537372b98701780a1819", gas: 60000, gasPrice: 20000000000, hash: "0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc", input: "0xa9059cbb00000000000000000000000088dd6b191d4bca6b059dd35ac0cffb2ffd072d62000000000000000000000000000000000000000000000000208b1d135e4a8000", nonce: 2, r: "0xdaf4a5ea69c253de73bee8dc39ac9d1bf671feba59a54773841ed77552ee3df5", s: "0x65ee2c9f6ea2014efa19d5998bb61b3a88cd358d798046dc5ef5c9b4fdaa7a78", to: "0xf13c9660190749124ad90c8defc77cc6c5d36494", transactionIndex: 0, v: "0x11ba9", value: 0 } > eth.getTransactionReceipt("0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc") { blockHash: "0x5383b71065dadf8fb7b91bdecf65cefd771f0ae4487e2d559fece25e6e011bd4", blockNumber: 110, contractAddress: null, cumulativeGasUsed: 37111, from: "0xaef72a6461e5392e9fa1537372b98701780a1819", gasUsed: 37111, logs: [{ address: "0xf13c9660190749124ad90c8defc77cc6c5d36494", blockHash: "0x5383b71065dadf8fb7b91bdecf65cefd771f0ae4487e2d559fece25e6e011bd4", blockNumber: 110, data: "0x000000000000000000000000000000000000000000000000208b1d135e4a8000", logIndex: 0, removed: false, topics: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x000000000000000000000000aef72a6461e5392e9fa1537372b98701780a1819", "0x00000000000000000000000088dd6b191d4bca6b059dd35ac0cffb2ffd072d62"], transactionHash: "0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc", transactionIndex: 0 }], logsBloom: "0x00000200000000000000000100000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000040040000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000002000000000000000000000000000002000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0xdcf34557c3394cc93a8c4dba07613db353f8e496b18506d3d99cee787e1059c5", to: "0xf13c9660190749124ad90c8defc77cc6c5d36494", transactionHash: "0x7f1d6a78768486177360b19f2fdcc5cfcb1663030c64f55a832700c5fe27abcc", transactionIndex: 0 }
using Geth mobile SDK
GoEthereum.java
import org.ethereum.geth.Transaction; public class GoEthereum implements Ethereum { public boolean transferToken(@NonNull String password, @NonNull Address toAddress, long amount, long gasLimit, long gasPrice) { try { unlock(password); new TokenTransfer(contractAddress, abi, getAccount(), ethClient, ethContext, new MySigner(keyStore, networkId)) .sendTransaction(password, toAddress, amount, gasLimit, gasPrice); lock(); return true; } catch (Exception e) { e.printStackTrace(); } return false; } }
TokenTransfer.java
import org.ethereum.geth.Account; import org.ethereum.geth.Address; import org.ethereum.geth.BigInt; import org.ethereum.geth.BoundContract; import org.ethereum.geth.Context; import org.ethereum.geth.Geth; import org.ethereum.geth.Interface; import org.ethereum.geth.Interfaces; import org.ethereum.geth.Signer; import org.ethereum.geth.TransactOpts; import org.ethereum.geth.Transaction; public class TokenTransfer { @TokenAddress @NonNull private final String contractAddress; @NonNull private final String abi; @NonNull private final Account account; @NonNull private final EthereumClient client; @NonNull private final Context context; @NonNull private final Signer signer; TokenTransfer(@TokenAddress @NonNull String contractAddress, @NonNull String abi, @NonNull Account account, @NonNull EthereumClient client, @NonNull Context context, @NonNull Signer signer) { this.contractAddress = contractAddress; this.abi = abi; this.account = account; this.client = client; this.account = account; this.context = context; this.signer = signer; } @NonNull public Transaction sendTransaction (@NonNull String password, @NonNull Address toAddress, long amount, long gasLimit, long gasPrice) { try { final long nonce = client.getPendingNonceAt(context, account.getAddress()); final BoundContract boundContract = Geth.bindContract(contractAddress, abi, client); final TransactOpts transactOpts = new TransactOpts(); transactOpts.setContext(context); transactOpts.setGasLimit(Geth.newBigInt(gasLimit)); transactOpts.setGasPrice(Geth.newBigInt(gasPrice)); transactOpts.setNonce(nonce); transactOpts.setFrom(account.getAddress()); transactOpts.setSigner(signer); final Interface paramToAddress = Geth.newInterface(); paramToAddress.setAddress(toAddress); final Interface paramAmount = Geth.newInterface(); paramAmount.setBigInt(Geth.newBigInt(amount)); final Interfaces params = Geth.newInterfaces(2); params.set(0, paramToAddress); params.set(1, paramAmount); return boundContract.transact(transactOpts, "transfer", params); } catch (Exception e) { throw new RuntimeException(e); } } }
MySigner.java
public class MySigner implements Signer { @NonNull private final KeyStore keyStore; @NonNull private final BigInt networkId; MySigner(@NonNull KeyStore keyStore, @IntRange(from = 0) int networkId) { this.keyStore = keyStore; this.networkId = Geth.newBigInt(networkId); } @NonNull @Override public Transaction sign(Address address, Transaction transaction) throws Exception { return keyStore.signTx(address, transaction, networkId); } }
Nonce too low issue
request
{ "jsonrpc":"2.0", "method":"eth_sendRawTransaction", "params":["0xf86b808223288275309488dd6b191d4bca6b059dd35ac0cffb2ffd072d6287038d7ea4c680008083011baaa02f5786edffdf79d5c67302e357cd674434d6e81b592180231fc5e030887e2e23a005d6102da7d01c725dc909a6306e97b750b4c9bdf846aa6d7b678c15cc2db12a"], "id":63 }
response
{ "jsonrpc": "2.0", "id": 63, "error": { "code": -32000, "message": "nonce too low" } }
Needs to increase the nonce
.