以太坊入门(三)用web3j进行以太转账及代币转账

上章讲到账户的查询,本章讲述账户转账。

  1. 以太坊转账 We3j web3j = Web3j.build(new HttpService(ConstantLibs.WEB3_ADDRESS)); Credentials credentials = WalletTool.loadCredentials(fromAddress); EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount( fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get(); BigInteger nonce = ethGetTransactionCount.getTransactionCount(); RawTransaction rawTransaction = RawTransaction.createEtherTransaction( nonce, Convert.toWei("18", Convert.Unit.GWEI).toBigInteger(), Convert.toWei("45000", Convert.Unit.WEI).toBigInteger(), toAddress, new BigInteger(amount)); byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); String hexValue = Numeric.toHexString(signedMessage); EthSendTransaction ethSendTransaction = web3.ethSendRawTransaction(hexValue).sendAsync().get(); if (ethSendTransaction.hasError()) { log.info("transfer error:", ethSendTransaction.getError().getMessage()); } else { String transactionHash = ethSendTransaction.getTransactionHash(); log.info("Transfer transactionHash:" + transactionHash); }
  2. 以太坊代币转账 Web3j web3j = Web3j.build(new HttpService(ConstantLibs.WEB3_ADDRESS)); Credentials credentials = WalletTool.loadCredentials(fromAddress); EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount( fromAddress, DefaultBlockParameterName.LATEST).sendAsync().get(); BigInteger nonce = ethGetTransactionCount.getTransactionCount(); Function function = new Function( "transfer", Arrays.asList(new Address(toAddress), new Uint256(new BigInteger(amount))), Arrays.asList(new TypeReference<Type>() { })); String encodedFunction = FunctionEncoder.encode(function); RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, Convert.toWei("18", Convert.Unit.GWEI).toBigInteger(), Convert.toWei("100000", Convert.Unit.WEI).toBigInteger(), contractAddress, encodedFunction); byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials); String hexValue = Numeric.toHexString(signedMessage); log.debug("transfer hexValue:" + hexValue); EthSendTransaction ethSendTransaction = web3.ethSendRawTransaction(hexValue).sendAsync().get(); if (ethSendTransaction.hasError()) { log.info("transfer error:", ethSendTransaction.getError().getMessage()); } else { String transactionHash = ethSendTransaction.getTransactionHash(); log.info("Transfer transactionHash:" + transactionHash); }

代币转账和以太转账的区别在于,to地址是合约地址,而input是有三部分数据构成:transfer方法的哈希+收款人的地址+转账金额。此处比较难理解的正是Function部分,设置好参数以后,调用rawTransaction就可以了。

本站始发,转载于 https://www.jianshu.com/p/8ae984e6bafc

以太坊入门(二)用web3j进行以太查询及通证查询

以太坊的开发,基本都是go语言和nodejs的天下,web3j出现给java开发人员提供了很大的便利。本文会对一些以太坊的基本操作用java语言来实现。

本章会讲述通过web3j进行账户余额的查询。

  1. 以太余额查询
    以太的余额查询比较简单,直接调用web3j的ethGetBalance就可以。 Web3j web3j = Web3j.build(new HttpService(ConstantLibs.WEB3_ADDRESS)); EthGetBalance ethGetBalance = web3j.ethGetBalance( address, DefaultBlockParameterName.LATEST).sendAsync().get(); BigInteger balance = ethGetBalance.getBalance();
  2. 通证的余额查询
    代币的查询就比较复杂一些,研究了好长时间,最后发现每个代币合约都会实现balanceOf方法,可以通过这个方法来查询通证的余额。 Web3j web3j = Web3j.build(new HttpService(ConstantLibs.WEB3_ADDRESS)); Function function = new Function( "balanceOf", Arrays.asList(new Address(address)), // Solidity Types in smart contract functions Arrays.asList(new TypeReference<Type>() { })); String encodedFunction = FunctionEncoder.encode(function); org.web3j.protocol.core.methods.response.EthCall response = web3j.ethCall( org.web3j.protocol.core.methods.request.Transaction.createEthCallTransaction(address, contract, encodedFunction), DefaultBlockParameterName.LATEST) .sendAsync().get(); String returnValue = response.getValue(); //返回16进制余额 returnValue = returnValue.substring(2); BigInteger balance = new BigInteger(returnValue, 16);

本站始发,转载于https://www.jianshu.com/p/0f3e65622d65

以太坊入门(一)账户和nonce的关系

什么是nonce?

在以太坊的交易数据中,大家都可以看到一个数字,nonce,从0开始,一直向上递增,这个代表什么意思呢?

以太坊所有的交易都是基于account的,不同于基于utxo的比特币,因此需要对每次交易都按顺序记录,nonce值就是这个顺序,主要用来防止重放攻击。

发起一笔交易,nonce就会加一。对于发起的解释:

1.外部账户每发送一笔交易;

2.合约账户每创建一个合约

而转入交易、合约调用其他合约等属于内部调用,因此nonce值不变。

如何使用nonce

发起转账或者创建合约的时候,通过web3从以太坊网络查询当前的nonce(ethGetTransactionCount)值,使用此值作为当前交易的nonce值,发送到以太坊网络即可。

nonce使用的几条规则

1. 当nonce太小(小于当前的nonce值),交易会被直接拒绝,Transactions with too low a nonce get immediately rejected;

2. 当nonce太大,大于当前nonce,交易会一直处于队列之中,Transactions with too high a nonce get placed in the transaction pool queue;

3.当发送一个比较大的nonce值,然后补齐开始nonce到那个值之间的nonce,那么交易依旧可以被执行,If transactions with nonces that fill the gap between the last valid nonce and the too high nonce are sent and the nonce sequence is complete, all the transactions in the sequence will get processed and mined.

4. 交易队列只保存最多64个从同一个账户发出的交易,The transaction pool queue will only hold a maximum of 64 transactions with the same From:address with nonces out of sequence. 也就是说,如果要批量转账,同一节点不要发出超过64笔交易。

5.当某节点queue中还有交易,但此时停止geth客户端,queue中的交易会被清除掉,When the geth instances are shut down and restarted, transactions in the transaction pool queue disappear.

6.当前nonce合适,但是账户余额不足时,会被以太坊拒绝;

7.如果发起一笔交易,但是因为gwei比较低或者网络比较忙的时候,该交易还没矿工挖出,可以通过使用相同的nonce和较高的gas费用,从而“覆盖”前一笔交易;

Nginx反向代理跨域option问题解决

CORS on Nginx

The following Nginx configuration enables CORS, with support for preflight requests.

#
# Wide-open CORS config for nginx
#
location / {
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
}

First is tricking Nginx that a 405 status is actually a 200 OK and then proxy_pass it to your HAProxy like this:

error_page 405 =200 @405;
location @405 {
    root /;
    proxy_pass http://yourproxy:8080;
}

The second solution is just to catch the OPTIONS request and build a response for those requests:

location / {
    if ($request_method = OPTIONS ) {
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }
}