public class Erc20BlockChainNode extends Contract {
//说明web3j和contractAddress在项目初始化时候,调用Contract类里面的构造方法,已经赋值
public Erc20BlockChainNode(String contractBinary, String contractAddress, Web3j web3j, Credentials credentials,
BigInteger gasPrice, BigInteger gasLimit) {
super(contractBinary, contractAddress, web3j, credentials, gasPrice, gasLimit);
}
private Erc20BlockChainNode(String contractBinary, String contractAddress, Web3j web3j,TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
super(contractBinary, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
public static Erc20BlockChainNode load(String contractBinary, String contractAddress, Web3j web3j,
TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
return new Erc20BlockChainNode(contractBinary, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
//获取交易的随机数
public BigInteger getNonce(String address) throws Exception {
return web3j.ethGetTransactionCount(address, DefaultBlockParameterName.PENDING).send().getTransactionCount();
}
//监听代币Erc20的交易,订阅
public Erc20Block getBlock(long blockNum) throws Exception {
List<TransferEventResponse> result = new ArrayList<>();
//监听链上的代币交易
this.transferEventObservable(DefaultBlockParameter.valueOf(BigInteger.valueOf(blockNum)),
DefaultBlockParameter.valueOf(BigInteger.valueOf(blockNum))).subscribe(observer -> {
result.add(observer);
});
return Erc20Block.fromWeb3(result);//fromWeb3()这个方法只是做了一个对象的转换
}
//根据地址获取代币余额
public BigInteger getBalance(String address) throws Exception {
String checkedAddr = EthUtils.checkAddress(address);
if (StringUtils.isBlank(checkedAddr)) {
return BigInteger.ZERO;
}
Function balanceOf = new Function("balanceOf", Arrays.<Type>asList(new Address(address)),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {
}));
String value = web3j.ethCall(Transaction.createEthCallTransaction(address, contractAddress, FunctionEncoder.encode(balanceOf)),
DefaultBlockParameterName.PENDING).send().getValue();
return new BigInteger(value.substring(2), 16);
}
//发送代币交易
public SendTransaction transfer(String sourceAddr, String sourcePriKey, String targetAddr, BigInteger amount,
BigInteger gasPrice, boolean amountIncludeFee) throws Exception {
sourceAddr = EthUtils.checkAddress(sourceAddr);
targetAddr = EthUtils.checkAddress(targetAddr);
if (StringUtils.isAnyBlank(sourceAddr, targetAddr, sourcePriKey)) {
return null;
}
if (gasPrice == null || gasPrice.compareTo(BigInteger.ZERO) < 0 || amount == null || amount.compareTo(BigInteger.ZERO) < 0) {
return null;
}
//获取交易的油费
BigInteger gas = EthUtils.calculateGas(null, gasPrice);
BigInteger payAmount = amount;
if (amountIncludeFee) {
payAmount = amount.subtract(gas);
if (payAmount.compareTo(BigInteger.ZERO) < 0) {
return null;
}
}
// 检查余额
BigInteger balance = this.getBalance(sourceAddr);
if (balance.compareTo(payAmount.add(gas)) < 0) {
return null;
}
//创建地址和密钥对象
Credentials credentials = Credentials.create(sourcePriKey);
BigInteger nonce = this.getNonce(sourceAddr);
//创建交易对象
Function function = new Function("transfer", Arrays.<Type>asList(new Address(targetAddr), new Uint256(amount)),
Collections.<TypeReference<?>>emptyList());
String encodedFunction = FunctionEncoder.encode(function);
RawTransaction rawTransaction = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, contractAddress,encodedFunction);
byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
//发送交易
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(Numeric.toHexString(signMessage)).sendAsync().get();
return new SendTransaction(ethSendTransaction.getTransactionHash(), nonce,Convert.fromWei(gasPrice.toString(), Unit.ETHER));
}
// 根据块号监听代币交易信息
public Observable<TransferEventResponse> transferEventObservable(DefaultBlockParameter startBlock,DefaultBlockParameter endBlock) {
//创建交易事件
final Event event = new Event("Transfer", Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {
}, new TypeReference<Address>() {
}), Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {
}));
EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
filter.addSingleTopic(EventEncoder.encode(event));
return web3j.ethLogObservable(filter).map(new Func1<Log, TransferEventResponse>() {
@Override
public TransferEventResponse call(Log log) {
EventValues eventValues = extractEventParameters(event, log);
TransferEventResponse typedResponse = new TransferEventResponse();
eventValues.getIndexedValues().size();
eventValues.getNonIndexedValues().size();
typedResponse._from = (Address) eventValues.getIndexedValues().get(0);
typedResponse._to = (Address) eventValues.getIndexedValues().get(1);
typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
typedResponse.log = log;
return typedResponse;
}
});
}
public static class TransferEventResponse {
public Address _from;
public Address _to;
public Uint256 _value;
public Log log;
}