生活随笔
收集整理的這篇文章主要介紹了
Springboot+web3j(4.7)+实战+填坑
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
實(shí)現(xiàn)功能:獲取合約event數(shù)據(jù)(相當(dāng)于日志)。
中文文檔
目前我找的比較好的文檔是 匯智網(wǎng) 的,java以太坊庫web3j文檔
搭建項(xiàng)目
Springboot版本
<parent><groupId>org.springframework.boot
</groupId><artifactId>spring-boot-starter-parent
</artifactId><version>2.3.4.RELEASE
</version><relativePath/> </parent>
web3j依賴
<dependency><groupId>com.squareup.okhttp3
</groupId><artifactId>okhttp
</artifactId><version>4.3.1
</version></dependency><dependency><groupId>com.squareup.okhttp3
</groupId><artifactId>logging-interceptor
</artifactId><version>4.3.1
</version></dependency><dependency><groupId>org.web3j
</groupId><artifactId>core
</artifactId><version>4.7.0
</version></dependency>
fasterxml依賴
<dependency><groupId>com.fasterxml.jackson.core
</groupId><artifactId>jackson-core
</artifactId><version>2.11.2
</version></dependency><dependency><groupId>com.fasterxml.jackson.core
</groupId><artifactId>jackson-annotations
</artifactId><version>2.11.2
</version></dependency><dependency><groupId>com.fasterxml.jackson.core
</groupId><artifactId>jackson-databind
</artifactId><version>2.11.2
</version></dependency>
web3j maven plugin
我們把合約文件(.sol)放在resources目錄下,運(yùn)行插件,即可生成合約對(duì)應(yīng)的Java類。這個(gè)插件會(huì)根據(jù)你的合約版本自動(dòng)下載對(duì)應(yīng)的solidity編譯器,真正實(shí)現(xiàn)一鍵生成合約java類,非常好用,老外就是牛皮。
<plugin><groupId>org.web3j
</groupId><artifactId>web3j-maven-plugin
</artifactId><version>4.6.5
</version><configuration><packageName>com.contract
</packageName><sourceDestination>src/main/java/generated
</sourceDestination><nativeJavaType>true
</nativeJavaType><outputFormat>java,bin
</outputFormat><soliditySourceFiles><directory>src/main/resources
</directory><includes><include>**/*.sol
</include></includes></soliditySourceFiles><outputDirectory><java>src/java/generated
</java><bin>src/bin/generated
</bin><abi>src/abi/generated
</abi></outputDirectory><contract></contract><pathPrefixes><pathPrefix>dep=../dependencies
</pathPrefix></pathPrefixes></configuration></plugin>
創(chuàng)建event過濾器
package com
.fc
.task
.contract
.config
;import com
.fc
.task
.contract
.contract
.Chip
;
import org
.springframework
.context
.annotation
.Bean
;
import org
.springframework
.context
.annotation
.Configuration
;
import org
.springframework
.context
.annotation
.Scope
;
import org
.web3j
.crypto
.Credentials
;
import org
.web3j
.protocol
.Web3j
;
import org
.web3j
.protocol
.core
.DefaultBlockParameterName
;
import org
.web3j
.protocol
.core
.methods
.request
.EthFilter
;
import org
.web3j
.protocol
.http
.HttpService
;
import org
.web3j
.tx
.gas
.DefaultGasProvider
;import java
.io
.IOException
;
@Configuration
public class ContractConfigDemo {@Beanpublic Web3j
web3j() {String ip
= "https://mainnet.infura.io/v3/xxxxxxxxxxxxxxxxxxxx";Web3j web3j
= Web3j
.build(new HttpService(ip
));return web3j
;}@Bean(name
= "inviteFilter") @Scope("prototype") public EthFilter
ethFilter(Chip chip
, Web3j web3j
) throws IOException
{
String contractAddress
= "";String eventTopics
= "";return new EthFilter(DefaultBlockParameterName
.EARLIEST
,DefaultBlockParameterName
.LATEST
,contractAddress
).addSingleTopic(eventTopics
);}@Beanpublic Chip
chip(Web3j web3j
) throws IOException
{Chip chip
;String chipAddress
= "";
String privateKey
= "";Credentials credentials
= Credentials
.create(privateKey
);chip
= Chip
.load(chipAddress
, web3j
, credentials
, new DefaultGasProvider());return chip
;}
}
創(chuàng)建監(jiān)聽器
package com
.fc
.task
.contract
.listener
;import org
.springframework
.beans
.factory
.annotation
.Autowired
;
import org
.springframework
.beans
.factory
.annotation
.Qualifier
;
import org
.springframework
.boot
.ApplicationArguments
;
import org
.springframework
.boot
.ApplicationRunner
;
import org
.springframework
.stereotype
.Component
;
import org
.web3j
.protocol
.Web3j
;
import org
.web3j
.protocol
.core
.methods
.request
.EthFilter
;
@Component
public class ContractListenerDemo implements ApplicationRunner {@AutowiredWeb3j web3j
;@Autowired@Qualifier("inviteFilter") EthFilter inviteFilter
;@Overridepublic void run(ApplicationArguments args
) throws Exception
{this.inviteFilterHandle();}private void inviteFilterHandle() {web3j
.ethLogFlowable(inviteFilter
).subscribe(log
->{System
.out
.println("收到事件inviteFilter");});}
}
過濾器和監(jiān)聽器結(jié)合使即可完成監(jiān)聽合約event功能。
定時(shí)任務(wù)獲取event數(shù)據(jù)
當(dāng)我們使用監(jiān)聽器獲取數(shù)據(jù)時(shí),很有可能會(huì)漏數(shù)據(jù),這時(shí)我們需要補(bǔ)救措施,我這里使用的是定時(shí)器5秒獲取一次數(shù)據(jù)。
這里我們需要用到 https://etherscan.io/ 的api。首先你要去這個(gè)網(wǎng)站注冊(cè)賬號(hào),得到自己的apikey。主網(wǎng)API說明點(diǎn)這里
package com
.fc
.service
.mananger
;import com
.alibaba
.fastjson
.JSONObject
;
import org
.apache
.http
.HttpEntity
;
import org
.apache
.http
.NameValuePair
;
import org
.apache
.http
.client
.entity
.UrlEncodedFormEntity
;
import org
.apache
.http
.client
.methods
.CloseableHttpResponse
;
import org
.apache
.http
.client
.methods
.HttpGet
;
import org
.apache
.http
.client
.methods
.HttpPost
;
import org
.apache
.http
.client
.utils
.URIBuilder
;
import org
.apache
.http
.entity
.StringEntity
;
import org
.apache
.http
.impl
.client
.CloseableHttpClient
;
import org
.apache
.http
.impl
.client
.HttpClients
;
import org
.apache
.http
.message
.BasicNameValuePair
;
import org
.apache
.http
.util
.EntityUtils
;
import org
.springframework
.stereotype
.Component
;import java
.io
.IOException
;
import java
.net
.URI
;
import java
.util
.*
;
@Component
public class EtherscanApiDemo {public void getUserRelationship() {String startBlockNumber
= "";String inviteContractAddress
= "";String apiKey
= "";String inviteContractTopic
= ""; String url
= "";Map
<String, Object> parameters
= new HashMap<>(7);parameters
.put("module", "logs");parameters
.put("action", "getLogs");parameters
.put("fromBlock", startBlockNumber
);parameters
.put("toBlock", "latest");parameters
.put("address", inviteContractAddress
);parameters
.put("topic0", inviteContractTopic
);parameters
.put("apikey", apiKey
);String response
= HttpUtil
.doGet(url
, parameters
);TransactionsResponse tr
= JSONObject
.parseObject(response
, TransactionsResponse
.class);}
}import org
.apache
.http
.HttpEntity
;
import org
.apache
.http
.NameValuePair
;
import org
.apache
.http
.client
.entity
.UrlEncodedFormEntity
;
import org
.apache
.http
.client
.methods
.CloseableHttpResponse
;
import org
.apache
.http
.client
.methods
.HttpGet
;
import org
.apache
.http
.client
.methods
.HttpPost
;
import org
.apache
.http
.client
.utils
.URIBuilder
;
import org
.apache
.http
.entity
.StringEntity
;
import org
.apache
.http
.impl
.client
.CloseableHttpClient
;
import org
.apache
.http
.impl
.client
.HttpClients
;
import org
.apache
.http
.message
.BasicNameValuePair
;
import org
.apache
.http
.util
.EntityUtils
;import java
.io
.IOException
;
import java
.net
.URI
;
import java
.util
.ArrayList
;
import java
.util
.List
;
import java
.util
.Map
;
class HttpUtil {private final static int NORMAL_STATUS
= 200;public static String
doGet(String url
, Map
<String, Object>... args
) {CloseableHttpClient httpClient
= HttpClients
.createDefault();CloseableHttpResponse response
= null
;String resultString
= "";try {URIBuilder builder
= new URIBuilder(url
);if (args
.length
> 0) {args
[0].forEach((k
, v
) -> builder
.addParameter(k
, String
.valueOf(v
)));}URI uri
= builder
.build();HttpGet httpGet
= new HttpGet(uri
);response
= httpClient
.execute(httpGet
);if (response
!= null
&& response
.getStatusLine().getStatusCode() == NORMAL_STATUS
) {HttpEntity httpEntity
= response
.getEntity();resultString
= EntityUtils
.toString(httpEntity
, "UTF-8");}} catch (Exception e
) {e
.printStackTrace();} finally {try {if (response
!= null
) {response
.close();}httpClient
.close();} catch (IOException e
) {e
.printStackTrace();}}return resultString
;}public static String
doPost(String url
, Map
<String, Object>... args
) {CloseableHttpClient httpClient
= HttpClients
.createDefault();CloseableHttpResponse response
= null
;String resultString
= "";try {HttpPost httpPost
= new HttpPost(url
);if (args
.length
> 1) {args
[1].forEach((k
, v
) -> httpPost
.setHeader(k
, String
.valueOf(v
)));}if (args
.length
> 0) {List
<NameValuePair> formParams
= new ArrayList<NameValuePair>();args
[0].forEach((k
, v
) -> formParams
.add(new BasicNameValuePair(k
, String
.valueOf(v
))));UrlEncodedFormEntity entity
= new UrlEncodedFormEntity(formParams
, "UTF-8");httpPost
.setEntity(entity
);}response
= httpClient
.execute(httpPost
);if (response
!= null
&& response
.getStatusLine().getStatusCode() == NORMAL_STATUS
) {resultString
= EntityUtils
.toString(response
.getEntity(), "UTF-8");}} catch (Exception e
) {e
.printStackTrace();} finally {try {if (response
!= null
) {response
.close();}httpClient
.close();} catch (IOException e
) {e
.printStackTrace();}}return resultString
;}public static String
doPostJson(String url
, String json
) {CloseableHttpClient httpClient
= HttpClients
.createDefault();CloseableHttpResponse response
= null
;String resultString
= "";try {HttpPost httpPost
= new HttpPost(url
);httpPost
.setHeader("Content-Type", "application/json;charset=UTF-8");StringEntity se
= new StringEntity(json
, "UTF-8");se
.setContentType("application/json");httpPost
.setEntity(se
);response
= httpClient
.execute(httpPost
);if (response
!= null
&& response
.getStatusLine().getStatusCode() == NORMAL_STATUS
) {resultString
= EntityUtils
.toString(response
.getEntity(), "UTF-8");}} catch (Exception e
) {e
.printStackTrace();} finally {try {if (response
!= null
) {response
.close();}httpClient
.close();} catch (IOException e
) {e
.printStackTrace();}}return resultString
;}
}class TransactionsResponse {private String status
;private String message
;private List
<Transactions> result
= new ArrayList<Transactions>();public TransactionsResponse() {}public String
getStatus() {return status
;}public void setStatus(String status
) {this.status
= status
;}public String
getMessage() {return message
;}public void setMessage(String message
) {this.message
= message
;}public List
<Transactions> getResult() {return result
;}public void setResult(List
<Transactions> result
) {this.result
= result
;}@Overridepublic String
toString() {return "TransactionsResponse [status=" + status
+ ", message=" + message
+ ", result=" + result
+ "]";}}class Transactions {private String blockNumber
;private String timeStamp
;private String hash
;private String nonce
;private String blockHash
;private String transactionIndex
;private String from
;private String to
;private String value
;private String gas
;private String gasPrice
;private String isError
;private String txreceipt_status
;private String input
;private String contractAddress
;private String cumulativeGasUsed
;private String gasUsed
;private String confirmations
;private String address
;private String
[] topics
;private String data
;private String logIndex
;private String transactionHash
;public String
getAddress() {return address
;}public void setAddress(String address
) {this.address
= address
;}public String
[] getTopics() {return topics
;}public void setTopics(String
[] topics
) {this.topics
= topics
;}public String
getData() {return data
;}public void setData(String data
) {this.data
= data
;}public String
getLogIndex() {return logIndex
;}public void setLogIndex(String logIndex
) {this.logIndex
= logIndex
;}public String
getTransactionHash() {return transactionHash
;}public void setTransactionHash(String transactionHash
) {this.transactionHash
= transactionHash
;}public Transactions() {}public String
getBlockNumber() {return blockNumber
;}public void setBlockNumber(String blockNumber
) {this.blockNumber
= blockNumber
;}public String
getTimeStamp() {return timeStamp
;}public void setTimeStamp(String timeStamp
) {this.timeStamp
= timeStamp
;}public String
getHash() {return hash
;}public void setHash(String hash
) {this.hash
= hash
;}public String
getNonce() {return nonce
;}public void setNonce(String nonce
) {this.nonce
= nonce
;}public String
getBlockHash() {return blockHash
;}public void setBlockHash(String blockHash
) {this.blockHash
= blockHash
;}public String
getTransactionIndex() {return transactionIndex
;}public void setTransactionIndex(String transactionIndex
) {this.transactionIndex
= transactionIndex
;}public String
getFrom() {return from
;}public void setFrom(String from
) {this.from
= from
;}public String
getTo() {return to
;}public void setTo(String to
) {this.to
= to
;}public String
getValue() {return value
;}public void setValue(String value
) {this.value
= value
;}public String
getGas() {return gas
;}public void setGas(String gas
) {this.gas
= gas
;}public String
getGasPrice() {return gasPrice
;}public void setGasPrice(String gasPrice
) {this.gasPrice
= gasPrice
;}public String
getIsError() {return isError
;}public void setIsError(String isError
) {this.isError
= isError
;}public String
getTxreceipt_status() {return txreceipt_status
;}public void setTxreceipt_status(String txreceipt_status
) {this.txreceipt_status
= txreceipt_status
;}public String
getInput() {return input
;}public void setInput(String input
) {this.input
= input
;}public String
getContractAddress() {return contractAddress
;}public void setContractAddress(String contractAddress
) {this.contractAddress
= contractAddress
;}public String
getCumulativeGasUsed() {return cumulativeGasUsed
;}public void setCumulativeGasUsed(String cumulativeGasUsed
) {this.cumulativeGasUsed
= cumulativeGasUsed
;}public String
getGasUsed() {return gasUsed
;}public void setGasUsed(String gasUsed
) {this.gasUsed
= gasUsed
;}public String
getConfirmations() {return confirmations
;}public void setConfirmations(String confirmations
) {this.confirmations
= confirmations
;}@Overridepublic String
toString() {return "Transactions{" +"blockNumber='" + blockNumber
+ '\'' +", timeStamp='" + timeStamp
+ '\'' +", hash='" + hash
+ '\'' +", nonce='" + nonce
+ '\'' +", blockHash='" + blockHash
+ '\'' +", transactionIndex='" + transactionIndex
+ '\'' +", from='" + from
+ '\'' +", to='" + to
+ '\'' +", value='" + value
+ '\'' +", gas='" + gas
+ '\'' +", gasPrice='" + gasPrice
+ '\'' +", isError='" + isError
+ '\'' +", txreceipt_status='" + txreceipt_status
+ '\'' +", input='" + input
+ '\'' +", contractAddress='" + contractAddress
+ '\'' +", cumulativeGasUsed='" + cumulativeGasUsed
+ '\'' +", gasUsed='" + gasUsed
+ '\'' +", confirmations='" + confirmations
+ '\'' +", address='" + address
+ '\'' +", topics=" + Arrays
.toString(topics
) +", data='" + data
+ '\'' +", logIndex='" + logIndex
+ '\'' +", transactionHash='" + transactionHash
+ '\'' +'}';}
}
本文有引用這篇文章 web3j 的 Infura Http 客戶端
總結(jié)
以上是生活随笔為你收集整理的Springboot+web3j(4.7)+实战+填坑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。