├── .github └── workflows │ ├── gradle.yml │ └── maven-publish.yml ├── .gitignore ├── CHANGELOG.md ├── README.md ├── build.gradle ├── docs ├── GLDToken.json ├── account-management.md ├── batch-rpc.md ├── cfx-address.md ├── contract-interaction.md ├── getting-started.md ├── how-to-publish.md └── sending-tx.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main └── java │ └── conflux │ └── web3j │ ├── AMNAccount.java │ ├── Account.java │ ├── AccountManager.java │ ├── Cfx.java │ ├── CfxPubSub.java │ ├── CfxUnit.java │ ├── Debug.java │ ├── HasValue.java │ ├── Request.java │ ├── RpcException.java │ ├── Trace.java │ ├── Web3.java │ ├── Web3j.java │ ├── contract │ ├── ContractCall.java │ ├── ERC1155.java │ ├── ERC20.java │ ├── ERC721.java │ ├── ERC777.java │ ├── abi │ │ ├── DecodeUtil.java │ │ └── TupleDecoder.java │ ├── diagnostics │ │ └── Recall.java │ └── internals │ │ ├── AdminControl.java │ │ ├── CrossSpaceCall.java │ │ ├── PoSRegister.java │ │ ├── SponsorWhitelistControl.java │ │ └── Staking.java │ ├── crypto │ ├── ConfluxBase32.java │ ├── ConfluxBase32Exception.java │ ├── Sign.java │ ├── StructuredData.java │ └── StructuredDataEncoder.java │ ├── request │ ├── Call.java │ ├── Epoch.java │ ├── LogFilter.java │ └── TraceFilter.java │ ├── response │ ├── AccountInfo.java │ ├── AccountPendingInfo.java │ ├── AccountPendingTransactions.java │ ├── Action.java │ ├── BigIntNullableResponse.java │ ├── BigIntResponse.java │ ├── Block.java │ ├── BlockHeader.java │ ├── BlockRevertRateResponse.java │ ├── BlockSummary.java │ ├── BlockTxInnerTrace.java │ ├── BlockTxTrace.java │ ├── CfxResponse.java │ ├── DepositInfo.java │ ├── FeeHistory.java │ ├── LocalizedBlockTrace.java │ ├── LocalizedTrace.java │ ├── Log.java │ ├── ParamsOfVote.java │ ├── PoSAccountReward.java │ ├── PoSEconomics.java │ ├── PoSEpochRewards.java │ ├── Receipt.java │ ├── RevertLog.java │ ├── RewardInfo.java │ ├── SponsorInfo.java │ ├── Status.java │ ├── StorageChange.java │ ├── StorageRoot.java │ ├── StringListResponse.java │ ├── StringNullableResponse.java │ ├── StringResponse.java │ ├── Subscribe.java │ ├── SupplyInfo.java │ ├── Transaction.java │ ├── Unsubscribe.java │ ├── UsedGasAndCollateral.java │ ├── VoteStakeInfo.java │ └── events │ │ ├── Epoch.java │ │ ├── EpochNotification.java │ │ ├── LogNotification.java │ │ ├── NewHead.java │ │ └── NewHeadsNotification.java │ ├── types │ ├── AccessListEntry.java │ ├── Address.java │ ├── AddressException.java │ ├── AddressType.java │ ├── CfxAddress.java │ ├── RawTransaction.java │ ├── SendTransactionError.java │ ├── SendTransactionResult.java │ └── TransactionBuilder.java │ └── utils │ └── Utils.java └── test ├── java └── conflux │ └── web3j │ ├── crypto │ ├── ECRecoverTest.java │ ├── SampleKeys.java │ ├── SignDataTests.java │ └── StructuredDataTests.java │ └── types │ ├── AddressTests.java │ ├── CfxBase32Tests.java │ ├── RPCTests.java │ └── RawTransactionTests.java └── resources └── structured_data_json_files └── ValidStructuredData.json /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Gradle 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle 3 | 4 | name: Java CI with Gradle 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Grant execute permission for gradlew 24 | run: chmod +x gradlew 25 | - name: Build with Gradle 26 | run: ./gradlew build 27 | - name: Build doc Gradle 28 | run: ./gradlew javadoc 29 | -------------------------------------------------------------------------------- /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up JDK 1.8 18 | uses: actions/setup-java@v1 19 | with: 20 | java-version: 1.8 21 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 22 | settings-path: ${{ github.workspace }} # location for the settings.xml file 23 | 24 | - name: Build with Maven 25 | run: mvn -B package --file pom.xml 26 | 27 | - name: Publish to GitHub Packages Apache Maven 28 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 29 | env: 30 | GITHUB_TOKEN: ${{ github.token }} 31 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} 32 | MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Java template 2 | *.class 3 | 4 | # Package Files # 5 | *.jar 6 | *.war 7 | *.ear 8 | 9 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 10 | hs_err_pid* 11 | ### Gradle template 12 | .gradle 13 | /build 14 | /out 15 | */build/ 16 | */out/ 17 | 18 | # Ignore Gradle GUI config 19 | gradle-app.setting 20 | 21 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 22 | !gradle-wrapper.jar 23 | 24 | # Cache of project 25 | .gradletasknamecache 26 | 27 | # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 28 | # gradle/wrapper/gradle-wrapper.properties 29 | 30 | # Eclipse 31 | .classpath 32 | .settings/ 33 | bin 34 | .idea 35 | docs/tmp.md 36 | docs/how-to-publish.md 37 | .vscode -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ### 1.3.0 4 | 5 | This version add support for [Conflux hardfork v2.4.0](https://doc.confluxnetwork.org/docs/general/hardforks/v2.4), including: 6 | 7 | 1. New added RPC methods: cfx_maxPriorityFeePerGas, cfx_feeHistory, cfx_getFeeBurnt 8 | 2. Support for CIP-1559 transaction 9 | 10 | ### 1.2.10 11 | 12 | 1. Fix SendTransactionError parse method to handle data is null 13 | 14 | ### 1.2.6 15 | * Add support for Batch Requests 16 | 17 | ### 1.2.5 18 | 19 | 1. Add support for internal contract CrossSpaceCall and PoSRegister 20 | 2. Adapt for [CIP-23](https://github.com/Conflux-Chain/CIPs/blob/master/CIPs/cip-23.md) 21 | 3. Fix `blockHead` event subscribe loss bug 22 | 4. Add `random` and `getPrivateKey` to `Account` class 23 | 24 | ### 1.2.0 25 | 26 | * Add support for standard token ERC721, ERC1155 27 | 28 | ### 1.1.1 29 | 30 | * Default gasPrice changed to 1GDrip 31 | * When sending transaction, will get `chainId` from Cfx instance, and using txpool nonce 32 | * blockHeader add two new fields `custom`, `posReference` 33 | * status add two new fields `latestFinalized`, `ethereumSpaceChainId` 34 | 35 | #### Add more RPC methods 36 | 37 | Add support for new methods imported from Conflux v2.0 38 | 39 | 1. `txpool_nextNonce` 40 | 2. `cfx_openedMethodGroups` 41 | 3. `cfx_getPoSEconomics` 42 | 4. `cfx_getPoSRewardByEpoch` 43 | 44 | #### Account 45 | 46 | Several Account method has been removed. 47 | 48 | * getNonce 49 | * setNonce 50 | * waitForNonceUpdated 51 | * waitForNonceUpdated 52 | 53 | ### 1.1.0 54 | 55 | #### Add more RPC methods 56 | 1. `cfx_getEpochReceipts` 57 | 2. `cfx_getAccountPendingInfo` 58 | 3. `cfx_getAccountPendingTransactions` 59 | 4. `trace_block` 60 | 5. `trace_transaction` 61 | 6. `trace_filter` 62 | 7. `cfx_getLogs`'s filter param add one more field 'offset' 63 | 8. `cfx_subscribe epochs` add one more optional tag parameter, available options: `latest_mined`(default value), `latest_state` 64 | 65 | Note: the required RPC service version is `1.1.4` or above. 66 | 67 | #### MISC 68 | 69 | 1. `Account` added method `deploy`, which can used to deploy contract. 70 | 2. `Account` added method `deployFile` which supports to deploy contract with truffle compiled json file. 71 | 3. Internal contract's constructor method omit a parameter `networkId` 72 | 73 | ### 1.0.0 74 | 75 | 1. Class Address support new CIP37 address 76 | 2. Where ever need an address, you should pass an `Address` instance, String address will not work 77 | 3. `getStatus` return a new field `networkId` 78 | 4. `getSupplyInfo` return a new field `totalCirculating` 79 | 5. `Address.validate` has been moved to `AddressType.validateHexAddress` 80 | 6. ERC20Call, ERC20Executor, ERC777Call, ERC777Executor has been removed, you can use the new ERC20, ERC777 81 | 7. AccountManager's constructor add a new parameter `networkId` 82 | 8. `org.web3j:core` updated to version 4.8.4 83 | 84 | 85 | ### 0.9.0 86 | 87 | 1. Tx receipts return more info: txExecErrorMsg, gasCoveredBySponsor, storageCoveredBySponsor, storageCollateralized, storageReleased 88 | 2. Add new RPC methods: cfx_getDepositList, cfx_getVoteList, cfx_getSupplyInfo 89 | 3. Add support for InternalContracts 90 | 4. Merge ERC20, ERC777 call and executor 91 | 5. Update default gasPrice to 1 Drip 92 | 6. Update RawTransaction default chainId to 1029(mainnet) -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Java Library project to get you started. 5 | * For more details take a look at the Java Libraries chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/5.6.1/userguide/java_library_plugin.html 7 | */ 8 | 9 | plugins { 10 | id 'java-library' // Apply the java-library plugin to add support for Java Library 11 | id 'maven-publish' 12 | id 'signing' 13 | } 14 | 15 | group = 'io.github.conflux-chain' 16 | version = '1.3.0' // SNAPSHOT 17 | 18 | repositories { 19 | // jcenter() 20 | mavenCentral() 21 | } 22 | 23 | dependencies { 24 | // This dependency is exported to consumers, that is to say found on their compile classpath. 25 | api 'org.apache.commons:commons-math3:3.6.1' 26 | 27 | // This dependency is used internally, and not exposed to consumers on their own compile classpath. 28 | implementation 'com.google.guava:guava:28.0-jre' 29 | 30 | compile 'org.web3j:core:4.9.3' 31 | 32 | // Use JUnit test framework 33 | testImplementation 'junit:junit:4.12' 34 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2' 35 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2' 36 | } 37 | 38 | test { 39 | useJUnitPlatform() 40 | } 41 | 42 | tasks.register('sourcesJar', Jar) { 43 | archiveClassifier = 'sources' 44 | from sourceSets.main.allJava 45 | } 46 | tasks.register('javadocJar', Jar) { 47 | archiveClassifier = 'javadoc' 48 | from javadoc.destinationDir 49 | } 50 | 51 | tasks.register('printEnvironmentVariable') { 52 | doLast { 53 | println "MY_ENV_VAR: " + findProperty("signing.secretKey") as String 54 | } 55 | } 56 | 57 | signing { 58 | useInMemoryPgpKeys( 59 | findProperty("signing.secretKey") as String, 60 | findProperty("signing.password") as String 61 | ) 62 | sign publishing.publications; 63 | } 64 | 65 | publishing { 66 | publications { 67 | mavenJava(MavenPublication) { 68 | from components.java 69 | artifactId = 'conflux.web3j' 70 | artifact sourcesJar 71 | artifact javadocJar 72 | 73 | versionMapping { 74 | usage('java-api') { 75 | fromResolutionOf('runtimeClasspath') 76 | } 77 | usage('java-runtime') { 78 | fromResolutionResult() 79 | } 80 | } 81 | 82 | pom { 83 | name = 'java-conflux-sdk' 84 | description = 'Java SDK for conflux network' 85 | url = 'https://github.com/Conflux-Chain/java-conflux-sdk' 86 | properties = [ 87 | tags: "blockchain, conflux" 88 | ] 89 | licenses { 90 | license { 91 | name = 'GNU General Public License v3.0' 92 | url = 'https://github.com/Conflux-Chain/conflux-rust/blob/master/LICENSE' 93 | } 94 | } 95 | developers { 96 | developer { 97 | id = 'Pana' 98 | name = 'Pana.W' 99 | email = 'pana.wang@outlook.com' 100 | } 101 | } 102 | scm { 103 | connection = 'scm:https://github.com/Conflux-Chain/java-conflux-sdk.git' 104 | developerConnection = 'scm:git://github.com/Conflux-Chain/java-conflux-sdk.git' 105 | url = 'https://github.com/conflux-chain/java-conflux-sdk' 106 | } 107 | } 108 | } 109 | } 110 | 111 | repositories { 112 | maven { 113 | def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" 114 | def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots" 115 | url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl 116 | name = "OSSRH" 117 | credentials { 118 | username = findProperty("maven.username") 119 | password = findProperty("maven.password") 120 | } 121 | } 122 | } 123 | } 124 | 125 | // ref https://docs.github.com/en/actions/guides/publishing-java-packages-with-gradle 126 | -------------------------------------------------------------------------------- /docs/account-management.md: -------------------------------------------------------------------------------- 1 | # Account Management 2 | 3 | `java-conflux-sdk` provide basic account management function. Developer can create or import their account(privateKey or keystore file) with class [`Account`](https://javadoc.io/doc/io.github.conflux-chain/conflux.web3j/latest/conflux/web3j/Account.html) or [`AccountManager`](https://javadoc.io/doc/io.github.conflux-chain/conflux.web3j/latest/conflux/web3j/AccountManager.html). 4 | After import accounts can be used to sign transaction (or message) and send them into blockchain network. 5 | 6 | ## AccountManager 7 | 8 | `AccountMananger` can be used to manager all accounts saved in one folder. Accounts are saved in keystore file. 9 | Normal operations are: 10 | 11 | * Initialize AccountManager 12 | * Create new account 13 | * Import account by privateKey or keystore file 14 | * List accounts 15 | * Export account in private key 16 | * Delete account 17 | * Sign transaction or message 18 | * Lock/Unlock 19 | 20 | When working with keystore file, a relative password is required. 21 | 22 | ### Initialize AccountManager 23 | 24 | ```java 25 | import conflux.web3j.AccountManager; 26 | 27 | int testNetChainId = 1; 28 | // create AccountManager instance from the default keystore folder 29 | AccountManager ac = new AccountManager(testNetChainId); 30 | // or create AccountManager install from specify folder 31 | AccountManager ac1 = new AccountManager("/path/tothe/keystore/", testNetChainId); 32 | ``` 33 | 34 | ### Create new account 35 | 36 | ```java 37 | Address newCreatedAccountAddress = ac.create("account-pwd"); 38 | // The new created account will be saved in a keystore file, encrypted by password 39 | ``` 40 | 41 | ### Import account 42 | 43 | ```java 44 | // import private key 45 | Optional
importedAddress = ac.imports("account-private-key", "new-pwd"); 46 | // import keystore file 47 | Optoinal
importedAddress = ac.imports("keystore-file-path", "origin-pwd", "new-pwd"); 48 | ``` 49 | 50 | ### Export account privateKey 51 | 52 | ```java 53 | Address addr = new Address("cfxtest:aak2rra2njvd77ezwjvx04kkds9fzagfe6d5r8e957"); 54 | String privatekey = ac.exportPrivateKey(addr, "account-pwd"); 55 | ``` 56 | 57 | ### Sign transaction 58 | 59 | ```java 60 | import conflux.web3j.types.RawTransaction; 61 | 62 | // Construct a rawTx by specify transaction parameters 63 | RawTransaction rawTx = RawTransaction.create( 64 | nonce, // nonce 65 | CfxUnit.DEFAULT_GAS_LIMIT, // gas 66 | to, // to 67 | value, // value 68 | BigInteger.valueOf(0), // storageLimit 69 | currentEpochNumber, // epochHeight 70 | "" // data 71 | ); 72 | 73 | Address addr = new Address("cfxtest:aak2rra2njvd77ezwjvx04kkds9fzagfe6d5r8e957"); 74 | String signedTx = ac.signTransaction(rawTx, addr, "account-pwd"); 75 | 76 | // The signedTx can ben send to blockchain network by calling `cfx_sendRawTransaction` method 77 | ``` 78 | 79 | ## Account 80 | 81 | The `Account` class instance can be used to sign and send transactions, it provides several tx send utility methods: 82 | 83 | * transfer 84 | * send 85 | * deploy 86 | * call 87 | 88 | ### Create Account 89 | 90 | ```java 91 | import conflux.web3j.Account; 92 | // create from privateKey 93 | Cfx cfx = Cfx.create("https://test.confluxrpc.com"); 94 | Account a1 = Account.create(cfx, "your-private-key"); 95 | // Or unlock from AccountManager 96 | Account a2 = Account.unlock(cfx, am, addr, "password"); 97 | ``` 98 | 99 | ### Sending transactions 100 | 101 | Check [sending transactions](./sending-tx.md) for detail example about sending tx. -------------------------------------------------------------------------------- /docs/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | The `java-conflux-sdk` can be used to interact with ConfluxNetwork and is very easy to use. 4 | 5 | ## Invoke RPC methods 6 | 7 | `Conflux` node(or client) provide `JSON-RPC` to enable developer get chain info and send transactions. 8 | The `java-conflux-sdk` provide methods to talk with `Conflux` node JSON-RPC method. 9 | 10 | ### Init client 11 | 12 | To interact with `Conflux` node, an RPC endpoint is needed. You can run your own a node with RPC opened, or use the public RPC 13 | endpoint provide by `Conflux` fund: 14 | 15 | * MainNet(1029): https://main.confluxrpc.com 16 | * TestNet(1): https://test.confluxrpc.com 17 | 18 | Then create a java [`Cfx`](https://javadoc.io/doc/io.github.conflux-chain/conflux.web3j/latest/conflux/web3j/Cfx.html) client, which can be used to invoke RPC methods. 19 | 20 | ```java 21 | import conflux.web3j.Cfx; 22 | import java.math.BigInteger; 23 | 24 | public class Main { 25 | public static void main(String[] args) throws Exception { 26 | try { 27 | System.out.println("Hello conflux-web3j"); 28 | Cfx cfx = Cfx.create("https://test.confluxrpc.com"); 29 | BigInteger currentEpochNumber = cfx.getEpochNumber().sendAndGet(); 30 | System.out.printf("Current epoch number %d \n", currentEpochNumber); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | ### Common RPC methods 39 | 40 | The `Cfx` client can be used to get a lot of blockchain info from node, including the latest epochNumber, block, account balance and nonce, 41 | transaction, receipt etc. 42 | 43 | #### Get account balance and nonce 44 | ```java 45 | import conflux.web3j.types.Address; 46 | 47 | Address addr = new Address("cfxtest:aak2rra2njvd77ezwjvx04kkds9fzagfe6d5r8e957"); 48 | BigInteger balance = cfx.getBalance(addr).sendAndGet(); 49 | // nonce will be used when sending transaction 50 | BigInteger nonce = cfx.getNonce(addr).sendAndGet(); 51 | ``` 52 | 53 | #### Get block 54 | 55 | ```java 56 | import conflux.web3j.request.Epoch; 57 | import conflux.web3j.response.Block; 58 | import conflux.web3j.response.BlockSummary; 59 | 60 | Epoch epoch = Epoch.numberOf(1000000); 61 | Optional b1 = cfx.getBlockSummaryByEpoch(epoch).sendAndGet(); 62 | // block may get failed 63 | boolean blockRetriveSuccess = b1.isPresent(); 64 | Optional blockWithTxDetail = cfx.getBlockByEpoch(epoch).sendAndGet(); 65 | 66 | String blockHash = "0xe27f5f566d3f450855e0455ae84c6723ebb477891ffa3ee68af9be518d5b150c"; 67 | Optional b3 = cfx.getBlockSummaryByHash(blockHash).sendAndGet(); 68 | ``` 69 | 70 | #### Get transaction and receipt 71 | 72 | ```java 73 | import conflux.web3j.response.Receipt; 74 | import conflux.web3j.response.Transaction; 75 | 76 | String txhash = "0x1aed92e97aa70dbc629ae37879915340f47b936a15529bd1e3952783a2efbfcd"; 77 | Optional tx = cfx.getTransactionByHash(txhash).sendAndGet(); 78 | Optional receipt = cfx.getTransactionReceipt(txhash).sendAndGet(); 79 | ``` 80 | 81 | For complete methods check [fullnode JSONRPC](https://developer.confluxnetwork.org/conflux-doc/docs/json_rpc) doc and [Cfx API](https://javadoc.io/doc/io.github.conflux-chain/conflux.web3j/latest/conflux/web3j/Cfx.html) doc 82 | 83 | ## Base32 address 84 | 85 | `Conflux` use base32 encoded address like `cfxtest:aak2rra2njvd77ezwjvx04kkds9fzagfe6d5r8e957`. The java SDK provide a class `conflux.web3j.types.Address` which can be used to construct, encode, decode address. 86 | For detail usage check [here](./cfx-address.md) 87 | -------------------------------------------------------------------------------- /docs/how-to-publish.md: -------------------------------------------------------------------------------- 1 | # How to publish 2 | 3 | 1. Update version in build.gradle 4 | 2. 使用 gradle publish 发布到 OSSRH 5 | 3. 到 oss.sonatype.org 的 Staging repositories 把将要发布的版本 close 掉 6 | 4. 待状态变为 closed 后,进行 Release 操作 7 | 8 | ## Configure 9 | 10 | 1. 在发布新版本 artifact 到 maven 之前, 需要对他们进行 sign, 签名需要用到 signingPassword 和 signingKey(pgp key); (PS 忘记如何生成了🤣) 11 | 2. 在发布到 maven 的时候, 需要通过 `oss.sonatype.org` 生成的 accessToken 来登录, 之前是 userName 和 password, 2024.6 后不再支持 -------------------------------------------------------------------------------- /docs/sending-tx.md: -------------------------------------------------------------------------------- 1 | # Sending Transaction 2 | 3 | Sending transaction is the only way to transfer CFX to another account, or change contract's state. 4 | To send a transaction the first step is assemble the necessary info of a tx, including: 5 | 6 | * to 7 | * value 8 | * nonce 9 | * gas 10 | * gasPrice 11 | * storageLimit 12 | * chainId 13 | * epochHeight 14 | * data 15 | 16 | Check [this doc](https://developer.confluxnetwork.org/sending-tx/en/transaction_explain) for detail introduction about transaction. 17 | 18 | Second the tx need to be signed by the sender's private key, and got a signed tx. 19 | 20 | Finally, the signed tx need to be sent to blockchain network by calling the `sendRawTransaction` RPC method. 21 | 22 | `java-conflux-sdk` provide a lot of methods to help developer send transactions. 23 | 24 | ## Quick transfer CFX 25 | 26 | The `account.transfer` method can be used to quickly send CFX to another account by specify the receiver address and amount. 27 | 28 | ```java 29 | import conflux.web3j.CfxUnit; 30 | 31 | Address addr = new Address("cfxtest:aak2rra2njvd77ezwjvx04kkds9fzagfe6d5r8e957"); 32 | // transfer 1 CFX to addr, the transaction hash will returned 33 | String hash = account.transfer(addr, CfxUnit.cfx2Drip(1)); 34 | 35 | // An optional parameter can be used to specify other fields of a transaction 36 | Account.Option op = new Account.Option(); 37 | op.withGasPrice(CfxUnit.DEFAULT_GAS_PRICE); // specify a bigger gasPrice to accelerate transaction 38 | // gas, storageLimit etc can also be specified through op 39 | String hash2 = account.transfer(op, addr, CfxUnit.cfx2Drip(1)); 40 | ``` 41 | 42 | ## Build tx manually and send 43 | 44 | If developer want more control on the transaction, they can create the RawTransaction and send it by account. 45 | 46 | ```java 47 | import conflux.web3j.types.RawTransaction; 48 | BigInteger nonce = cfx.getNonce(account.getAddress()).sendAndGet(); 49 | BigInteger value = CfxUnit.cfx2Drip(1); 50 | BigInteger currentEpochNumber = cfx.getEpochNumber().sendAndGet(); 51 | 52 | RawTransaction rawTx = new RawTransaction(); 53 | rawTx.setTo(to); 54 | rawTx.setValue(value); 55 | rawTx.setGasPrice(CfxUnit.DEFAULT_GAS_PRICE); 56 | // set all the rest field: nonce, gas, storageLimit ... 57 | // send it with account.send 58 | SendTransactionResult resp1 = account.send(rawTx); 59 | 60 | // or sign it and send 61 | String signedTx = account.sign(rawTx); 62 | SendTransactionResult resp2 = account.send(signedTx); 63 | ``` 64 | 65 | [`RawTransaction`](https://javadoc.io/static/io.github.conflux-chain/conflux.web3j/1.1.1/conflux/web3j/types/RawTransaction.html) also provide several methods to help quick build tx: 66 | 67 | `call`, `transfer`, `deploy` 68 | 69 | ## TransactionBuilder 70 | 71 | The [`TransactionBuilder`](https://javadoc.io/doc/io.github.conflux-chain/conflux.web3j/latest/conflux/web3j/types/TransactionBuilder.html) can be used to build a RawTransaction. 72 | 73 | ```java 74 | TransactionBuilder txBuilder = new TransactionBuilder(addr); 75 | txBuilder.withValue(CfxUnit.cfx2Drip(1)); 76 | txBuilder.withTo(addr); 77 | // ... other options can goes here 78 | RawTransaction rawTx = txBuilder.build(cfx); // the build method can automatically fill tx fields: nonce, gasPrice, gas, storageLimit, chainId, epochHeight 79 | ``` 80 | 81 | ## Deploy contract 82 | 83 | To deploy a contract, a deployment transaction is needed to sent to blockchain, contract's bytecode and constructor parameter(if it has) should be ABI encoded and set as tx's data field. 84 | 85 | ```java 86 | String bytecode = "0x123123..."; 87 | String hash = account.deploy(bytecode, arg1, arg2); // pass args if contract constructor has 88 | // an Account.Option also can be specified here 89 | String hash2 = account.deploy(op, bytecode, arg1, arg2); 90 | ``` 91 | 92 | ## Change contract's state by calling its method 93 | 94 | To update contract's state a transaction is also needed to be sent. For example if you want transfer your erc20 tokens to another address. 95 | With account.call method we can achieve this. 96 | 97 | ```java 98 | import org.web3j.abi.datatypes.generated.Uint256; 99 | 100 | String hash = account.call(contractAddr, "transfer", addr.getABIAddress(), new Uint256(100)); 101 | ``` 102 | 103 | There is detail introduction about [how to interact with contract](./contract-interaction.md) 104 | 105 | ## Common errors when sending tx 106 | 107 | Check [here](https://developer.confluxnetwork.org/conflux-doc/docs/RPCs/send_tx_error) for common sending tx error 108 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Conflux-Chain/java-conflux-sdk/e6fd0212960eab506e7f0d5dcb54969bd40b1c45/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/5.6.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'conflux-web3j' 11 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/AMNAccount.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import conflux.web3j.types.Address; 4 | import conflux.web3j.types.RawTransaction; 5 | import conflux.web3j.types.SendTransactionError; 6 | import conflux.web3j.types.SendTransactionResult; 7 | import org.web3j.crypto.ECKeyPair; 8 | 9 | import java.math.BigInteger; 10 | 11 | // Auto manage nonce account 12 | public class AMNAccount extends Account { 13 | 14 | private BigInteger nonce; 15 | public AMNAccount(Cfx cfx, Address address, ECKeyPair ecKeyPair) { 16 | super(cfx, address, ecKeyPair); 17 | this.nonce = this.getPoolNonce(); 18 | } 19 | 20 | public void setNonce(BigInteger nonce) { 21 | this.nonce = nonce; 22 | } 23 | 24 | public BigInteger getNonce() { 25 | return this.nonce; 26 | } 27 | 28 | private RawTransaction buildRawTransaction(Option option, Address to, String data) { 29 | return super.buildRawTransaction(option, to, data, this.nonce); 30 | } 31 | 32 | public SendTransactionResult send(String signedTx) throws Exception { 33 | SendTransactionResult result = super.send(signedTx); 34 | if (result.getRawError() == null 35 | || result.getErrorType().equals(SendTransactionError.TxAlreadyExists) 36 | || result.getErrorType().equals(SendTransactionError.InvalidNonceAlreadyUsed)) { 37 | this.nonce = this.nonce.add(BigInteger.ONE); 38 | } 39 | return result; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/Cfx.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import java.io.Closeable; 4 | import java.math.BigDecimal; 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | import conflux.web3j.response.*; 10 | import conflux.web3j.types.Address; 11 | import org.web3j.protocol.Web3jService; 12 | import org.web3j.protocol.core.Response; 13 | import org.web3j.protocol.http.HttpService; 14 | 15 | import conflux.web3j.request.Call; 16 | import conflux.web3j.request.Epoch; 17 | import conflux.web3j.request.LogFilter; 18 | import conflux.web3j.types.SendTransactionResult; 19 | 20 | /** Core Conflux JSON-RPC API. */ 21 | public interface Cfx extends Closeable, CfxPubSub { 22 | 23 | static Cfx create(String url) { 24 | return new Web3j(new HttpService(url)); 25 | } 26 | 27 | static Cfx create(String url, int retry) { 28 | return new Web3j(new HttpService(url), retry, 0); 29 | } 30 | 31 | static Cfx create(String url, int retry, long intervalMillis) { 32 | return new Web3j(new HttpService(url), retry, intervalMillis); 33 | } 34 | 35 | static Cfx create(Web3jService service) { 36 | return new Web3j(service); 37 | } 38 | 39 | static Cfx create(Web3jService service, int retry, long intervalMillis) { 40 | return new Web3j(service, retry, intervalMillis); 41 | } 42 | 43 | BigInteger getNetworkId(); 44 | 45 | int getIntNetworkId(); 46 | 47 | BigInteger getChainId(); 48 | 49 | Request getGasPrice(); 50 | 51 | Request getMaxPriorityFeePerGas(); 52 | 53 | Request getFeeBurnt(); 54 | 55 | Request getEpochNumber(Epoch... epoch); 56 | 57 | Request getBalance(Address address, Epoch... epoch); 58 | 59 | Request, StringNullableResponse> getAdmin(Address address, Epoch... epoch); 60 | 61 | Request getSponsorInfo(Address address, Epoch... epoch); 62 | 63 | Request getStakingBalance(Address address, Epoch... epoch); 64 | 65 | Request getCollateralForStorage(Address address, Epoch... epoch); 66 | 67 | Request getCode(Address address, Epoch... epoch); 68 | 69 | Request, StringNullableResponse> getStorageAt(Address address, String pos, Epoch... epoch); 70 | 71 | Request, StorageRoot.Response> getStorageRoot(Address address, Epoch... epoch); 72 | 73 | Request, BlockSummary.Response> getBlockSummaryByHash(String blockHash); 74 | 75 | Request, Block.Response> getBlockByHash(String blockHash); 76 | 77 | Request, BlockSummary.Response> getBlockSummaryByEpoch(Epoch epoch); 78 | 79 | Request, Block.Response> getBlockByEpoch(Epoch epoch); 80 | 81 | Request getBestBlockHash(); 82 | 83 | Request getNonce(Address address, Epoch... epoch); 84 | 85 | Request txpoolNextNonce(Address address); 86 | 87 | Request sendRawTransaction(String hexEncoded); 88 | 89 | Request call(Call request, Epoch... epoch); 90 | 91 | Request, Log.Response> getLogs(LogFilter filter); 92 | 93 | Request, Transaction.Response> getTransactionByHash(String txHash); 94 | 95 | Request estimateGasAndCollateral(Call request, Epoch... epoch); 96 | 97 | Request, Block.ListResponse> getBlocksByEpoch(Epoch epoch); 98 | 99 | Request, Block.ListResponse> getSkippedBlocksByEpoch(Epoch epoch); 100 | 101 | Request, Receipt.Response> getTransactionReceipt(String txHash); 102 | 103 | Request getAccount(Address address, Epoch... epoch); 104 | 105 | Request getInterestRate(Epoch... epoch); 106 | 107 | Request getAccumulateInterestRate(Epoch... epoch); 108 | 109 | Request, BigIntNullableResponse> getConfirmationRisk(String blockHash); 110 | 111 | Request getBlockRevertRate(String blockHash); 112 | 113 | Request getStatus(); 114 | 115 | Request, RewardInfo.Response> getReward(Epoch epoch); 116 | 117 | Request getClientVersion(); 118 | 119 | Request, DepositInfo.ListResponse> getDepositList(Address address, Epoch... epoch); 120 | 121 | Request, VoteStakeInfo.ListResponse> getVoteList(Address address, Epoch... epoch); 122 | 123 | Request getSupplyInfo(Epoch... epoch); 124 | 125 | Request, AccountPendingInfo.Response> getAccountPendingInfo(Address address); 126 | 127 | Request getAccountPendingTransactions(Address address); 128 | 129 | Request, StringListResponse.Response> rpcModules(); 130 | 131 | Request getPoSEconomics(); 132 | 133 | Request getPoSRewardByEpoch(Address address, Epoch epoch); 134 | 135 | Request getParamsFromVote(Epoch... epoch); 136 | 137 | Request getFeeHistory(int count, Epoch epoch, List percentiles); 138 | 139 | & HasValue> Request getCustomizedRequest(Class responseType, String method, Object... params); 140 | 141 | default Receipt waitForReceipt(String txHash) throws InterruptedException { 142 | return this.waitForReceipt(txHash, 1000); 143 | } 144 | 145 | default Receipt waitForReceipt(String txHash, long intervalMillis) throws InterruptedException { 146 | Optional receipt = Optional.empty(); 147 | 148 | while (!receipt.isPresent()) { 149 | Thread.sleep(intervalMillis); 150 | receipt = this.getTransactionReceipt(txHash).sendAndGet(); 151 | } 152 | 153 | return receipt.get(); 154 | } 155 | 156 | default void waitForNonce(Address address, BigInteger nonceUntil) throws InterruptedException { 157 | this.waitForNonce(address, nonceUntil, 1000); 158 | } 159 | 160 | default void waitForNonce(Address address, BigInteger nonceUntil, long intervalMillis) throws InterruptedException { 161 | while (this.getNonce(address).sendAndGet().compareTo(nonceUntil) < 0) { 162 | Thread.sleep(intervalMillis); 163 | } 164 | } 165 | 166 | default SendTransactionResult sendRawTransactionAndGet(String hexEncoded) throws RpcException { 167 | StringResponse response = this.sendRawTransaction(hexEncoded).sendWithRetry(); 168 | 169 | return response.getError() == null 170 | ? new SendTransactionResult(response.getValue()) 171 | : new SendTransactionResult(response.getError()); 172 | } 173 | 174 | } 175 | 176 | 177 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/CfxPubSub.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import conflux.web3j.request.Epoch; 4 | import conflux.web3j.request.LogFilter; 5 | import io.reactivex.Flowable; 6 | import conflux.web3j.response.events.*; 7 | 8 | public interface CfxPubSub { 9 | /** 10 | * Creates a {@link Flowable} instance that emits a notification when a new header is appended 11 | * to a chain, including chain reorganizations. 12 | * 13 | * @return a {@link Flowable} instance that emits a notification for every new header 14 | */ 15 | Flowable subscribeNewHeads(); 16 | 17 | /** 18 | * Creates a {@link Flowable} instance that emits notifications for logs included in new 19 | * imported blocks. 20 | * 21 | * @param filter only return logs match this filter 22 | * @return a {@link Flowable} instance that emits logs included in new blocks 23 | */ 24 | Flowable subscribeLogs(LogFilter filter); 25 | 26 | /** 27 | * Creates a {@link Flowable} instance that emits notifications for epochs 28 | * 29 | * @return a {@link Flowable} instance that emits new epochs 30 | */ 31 | Flowable subscribeEpochs(Epoch... epoch); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/CfxUnit.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.BigInteger; 5 | 6 | public class CfxUnit { 7 | 8 | private static final BigInteger DRIPS_PER_CFX_INT = BigInteger.TEN.pow(18); 9 | private static final BigDecimal DRIPS_PER_CFX_DECIMAL = new BigDecimal(DRIPS_PER_CFX_INT); 10 | private static final BigInteger DRIPS_PER_GDRIP = BigInteger.TEN.pow(9); 11 | 12 | public static final BigInteger GDRIP_ONE = BigInteger.TEN.pow(9); 13 | public static final BigInteger GDRIP_TEN = BigInteger.TEN.pow(10); 14 | public static final BigInteger CFX_ONE = BigInteger.TEN.pow(18); 15 | 16 | public static final BigInteger DEFAULT_GAS_PRICE = DRIPS_PER_GDRIP; 17 | public static final BigInteger DEFAULT_GAS_LIMIT = BigInteger.valueOf(21000); 18 | 19 | public static BigInteger cfx2Drip(long cfx) { 20 | return BigInteger.valueOf(cfx).multiply(DRIPS_PER_CFX_INT); 21 | } 22 | 23 | public static BigInteger cfx2Drip(double cfx) { 24 | return BigDecimal.valueOf(cfx).multiply(DRIPS_PER_CFX_DECIMAL).toBigIntegerExact(); 25 | } 26 | 27 | public static BigInteger gdrip2Drip(long gdrip) { 28 | return BigInteger.valueOf(gdrip).multiply(DRIPS_PER_GDRIP); 29 | } 30 | 31 | public static BigDecimal drip2Cfx(BigInteger drip) { 32 | return new BigDecimal(drip).divide(DRIPS_PER_CFX_DECIMAL); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/Debug.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import conflux.web3j.request.Epoch; 4 | import conflux.web3j.response.AccountPendingInfo; 5 | import conflux.web3j.response.AccountPendingTransactions; 6 | import conflux.web3j.response.Receipt; 7 | import conflux.web3j.types.Address; 8 | 9 | import java.io.Closeable; 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | // debug RPC methods 14 | public interface Debug extends Closeable { 15 | Request>>, Receipt.ListResponse> getEpochReceipts(Epoch epoch); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/HasValue.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | public interface HasValue { 4 | T getValue(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/Request.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import java.io.IOException; 4 | import java.util.Arrays; 5 | 6 | import org.web3j.protocol.Web3jService; 7 | import org.web3j.protocol.core.Response; 8 | 9 | public class Request & HasValue> extends org.web3j.protocol.core.Request { 10 | 11 | private int retry; 12 | private long intervalMillis; 13 | 14 | public Request() { 15 | } 16 | 17 | public Request(Web3jService service, String method, Class responseType, Object... params) { 18 | super(method, Arrays.asList(params), service, responseType); 19 | } 20 | 21 | public Request withRetry(int retry, long intervalMillis) { 22 | this.retry = retry; 23 | this.intervalMillis = intervalMillis; 24 | return this; 25 | } 26 | 27 | public R sendWithRetry() throws RpcException { 28 | return this.sendWithRetry(this.retry); 29 | } 30 | 31 | public R sendWithRetry(int retry) throws RpcException { 32 | return this.sendWithRetry(retry, this.intervalMillis); 33 | } 34 | 35 | public R sendWithRetry(int retry, long intervalMills) throws RpcException { 36 | while (true) { 37 | try { 38 | return this.send(); 39 | } catch (IOException e) { 40 | if (retry <= 0) { 41 | throw RpcException.sendFailure(e); 42 | } 43 | 44 | retry--; 45 | 46 | if (intervalMills > 0) { 47 | try { 48 | Thread.sleep(intervalMills); 49 | } catch (InterruptedException e1) { 50 | throw RpcException.interrupted(e1); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | public T sendAndGet() throws RpcException { 58 | return this.sendAndGet(this.retry); 59 | } 60 | 61 | public T sendAndGet(int retry) throws RpcException { 62 | return this.sendAndGet(retry, this.intervalMillis); 63 | } 64 | 65 | public T sendAndGet(int retry, long intervalMills) throws RpcException { 66 | R response = this.sendWithRetry(retry, intervalMills); 67 | 68 | if (response.getError() != null) { 69 | throw new RpcException(response.getError()); 70 | } 71 | 72 | return response.getValue(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/RpcException.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import java.io.IOException; 4 | 5 | import org.web3j.protocol.core.Response.Error; 6 | 7 | public class RpcException extends RuntimeException { 8 | 9 | private static final long serialVersionUID = 4965906647640407824L; 10 | 11 | public static final Error ERROR_IO_SEND = new Error(-1, "failed to send RPC request (IO error)"); 12 | public static final Error ERROR_INTERRUPTED = new Error(-2, "failed to send RPC request (interrupted)"); 13 | 14 | private Error error; 15 | 16 | public RpcException() { 17 | } 18 | 19 | public RpcException(Error error) { 20 | super(buildErrorMessage(error)); 21 | 22 | this.error = error; 23 | } 24 | 25 | public RpcException(Error error, Throwable cause) { 26 | super(buildErrorMessage(error), cause); 27 | 28 | this.error = error; 29 | } 30 | 31 | private static String buildErrorMessage(Error error) { 32 | return String.format("RPC error: code = %d, message = %s, data = %s", error.getCode(), error.getMessage(), error.getData()); 33 | } 34 | 35 | private static RpcException predefined(Error template, Throwable e) { 36 | Error error = new Error(template.getCode(), template.getMessage()); 37 | error.setData(e.getMessage()); 38 | return new RpcException(error, e); 39 | } 40 | 41 | public static RpcException sendFailure(IOException e) { 42 | return predefined(ERROR_IO_SEND, e); 43 | } 44 | 45 | public static RpcException interrupted(InterruptedException e) { 46 | return predefined(ERROR_INTERRUPTED, e); 47 | } 48 | 49 | public Error getError() { 50 | return error; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/Trace.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import conflux.web3j.request.TraceFilter; 4 | import conflux.web3j.response.LocalizedBlockTrace; 5 | import conflux.web3j.response.LocalizedTrace; 6 | 7 | import java.io.Closeable; 8 | import java.util.List; 9 | import java.util.Optional; 10 | 11 | public interface Trace extends Closeable { 12 | Request>, LocalizedTrace.Response> traceTransaction(String txHash); 13 | 14 | Request, LocalizedBlockTrace.Response> traceBlock(String blockHash); 15 | 16 | Request>, LocalizedTrace.Response> traceFilter(TraceFilter filter); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/Web3.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j; 2 | 3 | import org.web3j.protocol.Web3jService; 4 | import org.web3j.protocol.http.HttpService; 5 | 6 | public interface Web3 extends Cfx, Trace, Debug { 7 | static Web3 create(String url) { 8 | return new Web3j(new HttpService(url)); 9 | } 10 | 11 | static Web3 create(String url, int retry) { 12 | return new Web3j(new HttpService(url), retry, 0); 13 | } 14 | 15 | static Web3 create(String url, int retry, long intervalMillis) { 16 | return new Web3j(new HttpService(url), retry, intervalMillis); 17 | } 18 | static Web3 create(Web3jService service) { 19 | return new Web3j(service); 20 | } 21 | 22 | static Web3 create(Web3jService service, int retry, long intervalMillis) { 23 | return new Web3j(service, retry, intervalMillis); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/ContractCall.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | 7 | import org.web3j.abi.FunctionEncoder; 8 | import org.web3j.abi.datatypes.Function; 9 | import org.web3j.abi.datatypes.Type; 10 | 11 | import conflux.web3j.Cfx; 12 | import conflux.web3j.Request; 13 | import conflux.web3j.types.Address; 14 | import conflux.web3j.contract.abi.DecodeUtil; 15 | import conflux.web3j.request.Call; 16 | import conflux.web3j.request.Epoch; 17 | import conflux.web3j.response.StringResponse; 18 | import conflux.web3j.response.UsedGasAndCollateral; 19 | 20 | public class ContractCall { 21 | 22 | private Call call = new Call(); 23 | 24 | private Cfx cfx; 25 | private Epoch epoch; 26 | 27 | public ContractCall(Cfx cfx, Address contractAddress) { 28 | this.cfx = cfx; 29 | this.call.setTo(contractAddress); 30 | } 31 | 32 | public ContractCall buildFrom(Address from) { 33 | this.call.setFrom(from); 34 | BigInteger nonce = this.epoch == null 35 | ? this.cfx.getNonce(from).sendAndGet() 36 | : this.cfx.getNonce(from, this.epoch).sendAndGet(); 37 | this.call.setNonce(nonce); 38 | return this; 39 | } 40 | 41 | public ContractCall buildGasPrice(BigInteger price) { 42 | this.call.setGasPrice(price); 43 | return this; 44 | } 45 | 46 | public ContractCall buildGasLimit(BigInteger gas) { 47 | this.call.setGas(gas); 48 | return this; 49 | } 50 | 51 | public ContractCall buildValue(BigInteger value) { 52 | this.call.setValue(value); 53 | return this; 54 | } 55 | 56 | public ContractCall buildEpoch(Epoch epoch) { 57 | this.epoch = epoch; 58 | return this; 59 | } 60 | 61 | public Request estimateGasAndCollateral(String method, Type... args) { 62 | this.buildData(method, args); 63 | 64 | return this.epoch == null 65 | ? this.cfx.estimateGasAndCollateral(this.call) 66 | : this.cfx.estimateGasAndCollateral(this.call, this.epoch); 67 | } 68 | 69 | private void buildData(String method, Type... args) { 70 | if (method == null || method.isEmpty()) { 71 | this.call.setData(null); 72 | return; 73 | } 74 | 75 | Function function = new Function(method, Arrays.asList(args), Collections.emptyList()); 76 | String data = FunctionEncoder.encode(function); 77 | this.call.setData(data); 78 | } 79 | 80 | public Request call(String method, Type... args) { 81 | this.buildData(method, args); 82 | 83 | return this.epoch == null 84 | ? this.cfx.call(this.call) 85 | : this.cfx.call(this.call, this.epoch); 86 | } 87 | 88 | public > D callAndGet(Class returnType, String method, Type... args) { 89 | String rawData = this.call(method, args).sendAndGet(); 90 | return DecodeUtil.decode(rawData, returnType); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/ERC20.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.abi.datatypes.generated.Uint256; 6 | import org.web3j.abi.datatypes.Address; 7 | import org.web3j.abi.datatypes.Utf8String; 8 | 9 | import conflux.web3j.Account; 10 | import conflux.web3j.Cfx; 11 | import conflux.web3j.RpcException; 12 | import conflux.web3j.types.CfxAddress; 13 | import org.web3j.abi.datatypes.generated.Uint8; 14 | 15 | public class ERC20 extends ContractCall{ 16 | private Account account; 17 | private CfxAddress contract; 18 | 19 | public ERC20(Cfx cfx, CfxAddress address) { 20 | super(cfx, address); 21 | } 22 | 23 | public ERC20(Cfx cfx, CfxAddress address, Account account) { 24 | super(cfx, address); 25 | this.account = account; 26 | this.contract = address; 27 | } 28 | 29 | public BigInteger totalSupply() throws RpcException { 30 | return this.callAndGet(Uint256.class, "totalSupply"); 31 | } 32 | 33 | public String name() throws RpcException { 34 | return this.callAndGet(Utf8String.class, "name"); 35 | } 36 | 37 | public String symbol() throws RpcException { 38 | return this.callAndGet(Utf8String.class, "symbol"); 39 | } 40 | 41 | public BigInteger decimals() throws RpcException { 42 | return this.callAndGet(Uint8.class, "decimals"); 43 | } 44 | 45 | public BigInteger balanceOf(Address account) throws RpcException { 46 | return this.callAndGet(Uint256.class, "balanceOf", account); 47 | } 48 | 49 | public BigInteger balanceOf(CfxAddress account) throws RpcException { 50 | return this.balanceOf(account.getABIAddress()); 51 | } 52 | 53 | public BigInteger balanceOf(String account) throws RpcException { 54 | return this.balanceOf(new Address(account)); 55 | } 56 | 57 | public BigInteger allowance(Address owner, Address spender) throws RpcException { 58 | return this.callAndGet(Uint256. class, "allowance", owner, spender); 59 | } 60 | 61 | public BigInteger allowance(CfxAddress owner, CfxAddress spender) throws RpcException { 62 | return this.allowance(owner.getABIAddress(), spender.getABIAddress()); 63 | } 64 | 65 | public BigInteger allowance(String owner, String spender) throws RpcException { 66 | return this.allowance(new Address(owner), new Address(spender)); 67 | } 68 | 69 | public String transfer(Account.Option option, Address recipient, BigInteger amount) throws Exception { 70 | return this.account.call(option, this.contract, "transfer", recipient, new Uint256(amount)); 71 | } 72 | 73 | public String transfer(Account.Option option, CfxAddress recipient, BigInteger amount) throws Exception { 74 | return this.transfer(option, recipient.getABIAddress(), amount); 75 | } 76 | 77 | public String transfer(Account.Option option, String recipient, BigInteger amount) throws Exception { 78 | return this.transfer(option, new Address(recipient), amount); 79 | } 80 | 81 | public String approve(Account.Option option, Address spender, BigInteger amount) throws Exception { 82 | return this.account.call(option, this.contract, "approve", spender, new Uint256(amount)); 83 | } 84 | 85 | public String approve(Account.Option option, CfxAddress spender, BigInteger amount) throws Exception { 86 | return this.approve(option, spender.getABIAddress(), amount); 87 | } 88 | 89 | public String approve(Account.Option option, String spender, BigInteger amount) throws Exception { 90 | return this.approve(option, new Address(spender), amount); 91 | } 92 | 93 | public String transferFrom(Account.Option option, Address sender, Address recipient, BigInteger amount) throws Exception { 94 | return this.account.call(option, this.contract, "transferFrom", sender, recipient, new Uint256(amount)); 95 | } 96 | 97 | public String transferFrom(Account.Option option, CfxAddress sender, CfxAddress recipient, BigInteger amount) throws Exception { 98 | return this.transferFrom(option, sender.getABIAddress(), recipient.getABIAddress(), amount); 99 | } 100 | 101 | public String transferFrom(Account.Option option, String sender, String recipient, BigInteger amount) throws Exception { 102 | return this.transferFrom(option, new Address(sender), new Address(recipient), amount); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/ERC721.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract; 2 | 3 | import conflux.web3j.Account; 4 | import conflux.web3j.Cfx; 5 | import conflux.web3j.RpcException; 6 | import conflux.web3j.types.CfxAddress; 7 | 8 | import org.web3j.abi.datatypes.Address; 9 | import org.web3j.abi.datatypes.Bool; 10 | import org.web3j.abi.datatypes.DynamicBytes; 11 | import org.web3j.abi.datatypes.Utf8String; 12 | import org.web3j.abi.datatypes.generated.Uint256; 13 | 14 | import java.math.BigInteger; 15 | 16 | public class ERC721 extends ContractCall { 17 | private Account account; 18 | private CfxAddress contract; 19 | 20 | public ERC721(Cfx cfx, CfxAddress address) { 21 | super(cfx, address); 22 | } 23 | 24 | public ERC721(Cfx cfx, CfxAddress address, Account account) { 25 | super(cfx, address); 26 | this.account = account; 27 | this.contract = address; 28 | } 29 | 30 | public String name() throws RpcException { 31 | return this.callAndGet(Utf8String.class, "name"); 32 | } 33 | 34 | public String symbol() throws RpcException { 35 | return this.callAndGet(Utf8String.class, "symbol"); 36 | } 37 | 38 | public String tokenURI(BigInteger tokenId) throws RpcException { 39 | return this.callAndGet(Utf8String.class, "tokenURI", new Uint256(tokenId)); 40 | } 41 | 42 | public BigInteger balanceOf(Address account) throws RpcException { 43 | return this.callAndGet(Uint256.class, "balanceOf", account); 44 | } 45 | 46 | public BigInteger balanceOf(CfxAddress account) throws RpcException { 47 | return this.balanceOf(account.getABIAddress()); 48 | } 49 | 50 | // pass a hex40 address 51 | public BigInteger balanceOf(String account) throws RpcException { 52 | return this.balanceOf(new Address(account)); 53 | } 54 | 55 | public String ownerOf(BigInteger tokenId) throws RpcException { 56 | return this.callAndGet(Address.class, "ownerOf", new Uint256(tokenId)); 57 | } 58 | 59 | public String getApproved(BigInteger tokenId) throws RpcException { 60 | return this.callAndGet(Address.class, "getApproved", new Uint256(tokenId)); 61 | } 62 | 63 | public Boolean isApprovedForAll(Address owner, Address operator) throws RpcException { 64 | return this.callAndGet(Bool.class, "isApprovedForAll", owner, operator); 65 | } 66 | 67 | public Boolean isApprovedForAll(CfxAddress owner, CfxAddress operator) throws RpcException { 68 | return this.isApprovedForAll(owner.getABIAddress(), operator.getABIAddress()); 69 | } 70 | 71 | public Boolean isApprovedForAll(String owner, String operator) throws RpcException { 72 | return this.isApprovedForAll(new Address(owner), new Address(operator)); 73 | } 74 | 75 | public String _mint(Account.Option option, Address to, BigInteger tokenId) throws Exception { 76 | return this.account.call(option, this.contract, "_mint", to, new Uint256(tokenId)); 77 | } 78 | 79 | public String _mint(Account.Option option, CfxAddress to, BigInteger tokenId) throws Exception { 80 | return this._mint(option, to.getABIAddress(), tokenId); 81 | } 82 | 83 | public String _mint(Account.Option option, String to, BigInteger tokenId) throws Exception { 84 | return this._mint(option, new Address(to), tokenId); 85 | } 86 | 87 | public String transferFrom(Account.Option option, Address sender, Address recipient, BigInteger tokenId) throws Exception { 88 | return this.account.call(option, this.contract, "transferFrom", sender, recipient, new Uint256(tokenId)); 89 | } 90 | 91 | public String transferFrom(Account.Option option, CfxAddress sender, CfxAddress recipient, BigInteger tokenId) throws Exception { 92 | return this.transferFrom(option, sender.getABIAddress(), recipient.getABIAddress(), tokenId); 93 | } 94 | 95 | public String transferFrom(Account.Option option, String sender, String recipient, BigInteger tokenId) throws Exception { 96 | return this.transferFrom(option, new Address(sender), new Address(recipient), tokenId); 97 | } 98 | 99 | public String safeTransferFrom(Account.Option option, Address sender, Address recipient, BigInteger tokenId) throws Exception { 100 | return this.account.call(option, this.contract, "safeTransferFrom", sender, recipient, new Uint256(tokenId)); 101 | } 102 | 103 | public String safeTransferFrom(Account.Option option, CfxAddress sender, CfxAddress recipient, BigInteger tokenId) throws Exception { 104 | return this.safeTransferFrom(option, sender.getABIAddress(), recipient.getABIAddress(), tokenId); 105 | } 106 | 107 | public String safeTransferFrom(Account.Option option, String sender, String recipient, BigInteger tokenId) throws Exception { 108 | return this.safeTransferFrom(option, new Address(sender), new Address(recipient), tokenId); 109 | } 110 | 111 | public String safeTransferFrom(Account.Option option, Address from, Address to, BigInteger tokenId, byte[] data) throws Exception { 112 | return this.account.call(option, this.contract, "safeTransferFrom", from, to, new Uint256(tokenId), new DynamicBytes(data)); 113 | } 114 | 115 | public String safeTransferFrom(Account.Option option, CfxAddress from, CfxAddress to, BigInteger tokenId, byte[] data) throws Exception { 116 | return this.safeTransferFrom(option, from.getABIAddress(), to.getABIAddress(), tokenId, data); 117 | } 118 | 119 | public String safeTransferFrom(Account.Option option, String from, String to, BigInteger tokenId, byte[] data) throws Exception { 120 | return this.safeTransferFrom(option, new Address(from), new Address(to), tokenId, data); 121 | } 122 | 123 | public String approve(Account.Option option, Address to, BigInteger tokenId) throws Exception { 124 | return this.account.call(option, this.contract, "approve", to, new Uint256(tokenId)); 125 | } 126 | 127 | public String approve(Account.Option option, CfxAddress to, BigInteger tokenId) throws Exception { 128 | return this.approve(option, to.getABIAddress(), tokenId); 129 | } 130 | 131 | public String approve(Account.Option option, String to, BigInteger tokenId) throws Exception { 132 | return this.approve(option, new Address(to), tokenId); 133 | } 134 | 135 | public String setApprovalForAll(Account.Option option, Address operator, boolean approved) throws Exception { 136 | return this.account.call(option, this.contract, "setApprovalForAll", operator, new Bool(approved)); 137 | } 138 | 139 | public String setApprovalForAll(Account.Option option, CfxAddress operator, boolean approved) throws Exception { 140 | return this.setApprovalForAll(option, operator.getABIAddress(), approved); 141 | } 142 | 143 | public String setApprovalForAll(Account.Option option, String operator, boolean approved) throws Exception { 144 | return this.setApprovalForAll(option, new Address(operator), approved); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/ERC777.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract; 2 | 3 | import conflux.web3j.Account; 4 | import conflux.web3j.Cfx; 5 | import conflux.web3j.RpcException; 6 | import conflux.web3j.contract.abi.DecodeUtil; 7 | import conflux.web3j.types.CfxAddress; 8 | import org.web3j.abi.TypeReference; 9 | import org.web3j.abi.datatypes.Utf8String; 10 | import org.web3j.abi.datatypes.generated.Uint256; 11 | import org.web3j.abi.datatypes.DynamicArray; 12 | import org.web3j.abi.datatypes.DynamicBytes; 13 | import org.web3j.abi.datatypes.Bool; 14 | import org.web3j.abi.datatypes.Address; 15 | 16 | import java.math.BigInteger; 17 | import java.util.List; 18 | 19 | public class ERC777 extends ContractCall { 20 | private Account account; 21 | private CfxAddress contract; 22 | 23 | private static final TypeReference> TYPE_DYNAMIC_ARRAY_ADDRESS = new TypeReference>() {}; 24 | 25 | public ERC777(Cfx cfx, CfxAddress erc777Address) { 26 | super(cfx, erc777Address); 27 | } 28 | 29 | public ERC777(Cfx cfx, CfxAddress address, Account account) { 30 | super(cfx, address); 31 | this.account = account; 32 | this.contract = address; 33 | } 34 | 35 | public String name() throws RpcException { 36 | return this.callAndGet(Utf8String.class, "name"); 37 | } 38 | 39 | public String symbol() throws RpcException { 40 | return this.callAndGet(Utf8String.class, "symbol"); 41 | } 42 | 43 | public BigInteger granularity() throws RpcException { 44 | return this.callAndGet(Uint256.class, "granularity"); 45 | } 46 | 47 | public BigInteger totalSupply() throws RpcException { 48 | return this.callAndGet(Uint256.class, "totalSupply"); 49 | } 50 | 51 | public BigInteger balanceOf(Address owner) throws RpcException { 52 | return this.callAndGet(Uint256.class, "balanceOf", owner); 53 | } 54 | 55 | public BigInteger balanceOf(CfxAddress owner) throws RpcException { 56 | return this.balanceOf(owner.getABIAddress()); 57 | } 58 | 59 | public BigInteger balanceOf(String owner) throws RpcException { 60 | return this.balanceOf(new Address(owner)); 61 | } 62 | 63 | public boolean isOperatorFor(Address operator, Address tokenHolder) throws RpcException { 64 | return this.callAndGet(Bool.class, "isOperatorFor", operator, tokenHolder); 65 | } 66 | 67 | public boolean isOperatorFor(String operator, String tokenHolder) throws RpcException { 68 | return this.isOperatorFor(new Address(operator), new Address(tokenHolder)); 69 | } 70 | 71 | public boolean isOperatorFor(CfxAddress operator, CfxAddress tokenHolder) throws RpcException { 72 | return this.isOperatorFor(operator.getABIAddress(), tokenHolder.getABIAddress()); 73 | } 74 | 75 | public List
defaultOperators() throws RpcException { 76 | String encodedResult = this.call("defaultOperators").sendAndGet(); 77 | return DecodeUtil.decode(encodedResult, TYPE_DYNAMIC_ARRAY_ADDRESS); 78 | } 79 | 80 | public String send(Account.Option option, Address recipient, BigInteger amount, byte[] data) throws Exception { 81 | return this.account.call(option, this.contract, "send", recipient, new Uint256(amount), new DynamicBytes(data)); 82 | } 83 | 84 | public String send(Account.Option option, CfxAddress recipient, BigInteger amount, byte[] data) throws Exception { 85 | return this.send(option, recipient.getABIAddress(), amount, data); 86 | } 87 | 88 | public String send(Account.Option option, String recipient, BigInteger amount, byte[] data) throws Exception { 89 | return this.send(option, new Address(recipient), amount, data); 90 | } 91 | 92 | public String burn(Account.Option option, BigInteger amount, byte[] data) throws Exception { 93 | return this.account.call(option, this.contract, "burn", new Uint256(amount), new DynamicBytes(data)); 94 | } 95 | 96 | public String authorizeOperator(Account.Option option, Address operator) throws Exception { 97 | return this.account.call(option, this.contract, "authorizeOperator", operator); 98 | } 99 | 100 | public String authorizeOperator(Account.Option option, CfxAddress operator) throws Exception { 101 | return this.authorizeOperator(option, operator.getABIAddress()); 102 | } 103 | 104 | public String authorizeOperator(Account.Option option, String operator) throws Exception { 105 | return this.authorizeOperator(option, new Address(operator)); 106 | } 107 | 108 | public String revokeOperator(Account.Option option, Address operator) throws Exception { 109 | return this.account.call(option, this.contract, "revokeOperator", operator); 110 | } 111 | 112 | public String revokeOperator(Account.Option option, CfxAddress operator) throws Exception { 113 | return this.revokeOperator(option, operator.getABIAddress()); 114 | } 115 | 116 | public String revokeOperator(Account.Option option, String operator) throws Exception { 117 | return this.revokeOperator(option, new Address(operator)); 118 | } 119 | 120 | public String operatorSend(Account.Option option, Address sender, Address recipient, BigInteger amount, byte[] data, byte[] operatorData) throws Exception { 121 | return this.account.call(option, this.contract, "operatorSend", sender, recipient, new Uint256(amount), new DynamicBytes(data), new DynamicBytes(operatorData)); 122 | } 123 | 124 | public String operatorSend(Account.Option option, CfxAddress sender, CfxAddress recipient, BigInteger amount, byte[] data, byte[] operatorData) throws Exception { 125 | return this.operatorSend(option, sender.getABIAddress(), recipient.getABIAddress(), amount, data, operatorData); 126 | } 127 | 128 | public String operatorSend(Account.Option option, String sender, String recipient, BigInteger amount, byte[] data, byte[] operatorData) throws Exception { 129 | return this.operatorSend(option, new Address(sender), new Address(recipient), amount, data, operatorData); 130 | } 131 | 132 | public String operatorBurn(Account.Option option, Address account, BigInteger amount, byte[] data, byte[] operatorData) throws Exception { 133 | return this.account.call(option, this.contract, "operatorBurn", account, new Uint256(amount), new DynamicBytes(data), new DynamicBytes(operatorData)); 134 | } 135 | 136 | public String operatorBurn(Account.Option option, CfxAddress account, BigInteger amount, byte[] data, byte[] operatorData) throws Exception { 137 | return this.operatorBurn(option, account.getABIAddress(), amount, data, operatorData); 138 | } 139 | 140 | public String operatorBurn(Account.Option option, String account, BigInteger amount, byte[] data, byte[] operatorData) throws Exception { 141 | return this.operatorBurn(option, new Address(account), amount, data, operatorData); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/abi/DecodeUtil.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.abi; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.web3j.abi.FunctionReturnDecoder; 7 | import org.web3j.abi.TypeReference; 8 | import org.web3j.abi.TypeReference.StaticArrayTypeReference; 9 | import org.web3j.abi.datatypes.DynamicArray; 10 | import org.web3j.abi.datatypes.StaticArray; 11 | import org.web3j.abi.datatypes.Type; 12 | import org.web3j.abi.datatypes.Utf8String; 13 | import org.web3j.utils.Numeric; 14 | 15 | public class DecodeUtil { 16 | 17 | @SuppressWarnings({ "rawtypes", "unchecked" }) 18 | public static > D decode(String encodedResult, Class returnType) { 19 | TypeReference returnTypeRef = TypeReference.create(returnType); 20 | List decoded = FunctionReturnDecoder.decode(encodedResult, Arrays.asList(returnTypeRef)); 21 | 22 | if (decoded == null || decoded.isEmpty()) { 23 | return null; 24 | } 25 | 26 | return ((T) decoded.get(0)).getValue(); 27 | } 28 | 29 | @SuppressWarnings({ "rawtypes", "unchecked" }) 30 | public static > List decode(String encodedResult, StaticArrayTypeReference> returnType) { 31 | List decoded = FunctionReturnDecoder.decode(encodedResult, Arrays.asList((TypeReference) returnType)); 32 | 33 | if (decoded == null || decoded.isEmpty()) { 34 | return null; 35 | } 36 | 37 | return ((StaticArray) decoded.get(0)).getValue(); 38 | } 39 | 40 | @SuppressWarnings({ "rawtypes", "unchecked" }) 41 | public static > List decode(String encodedResult, TypeReference> returnType) { 42 | List decoded = FunctionReturnDecoder.decode(encodedResult, Arrays.asList((TypeReference) returnType)); 43 | 44 | if (decoded == null || decoded.isEmpty()) { 45 | return null; 46 | } 47 | 48 | return ((DynamicArray) decoded.get(0)).getValue(); 49 | } 50 | 51 | public static String decodeErrorData(String data) { 52 | if (data == null || data.isEmpty()) { 53 | return data; 54 | } 55 | 56 | // remove the leading/trailing quote 57 | data = data.replace("\"", "").replace("\\", ""); 58 | 59 | if (data.length() <= 10 || ((data.length() - 10) % 64 != 0)) { 60 | // decode as normal string 61 | return new String(Numeric.hexStringToByteArray(data)); 62 | } 63 | 64 | try { 65 | // skip the 0x prefix and method signature (4 bytes) 66 | data = data.substring(10); 67 | 68 | return decode(data, Utf8String.class); 69 | } catch (Exception e) { 70 | // decode as normal string 71 | return new String(Numeric.hexStringToByteArray(data)); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/abi/TupleDecoder.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.abi; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.abi.datatypes.Type; 6 | import org.web3j.utils.Numeric; 7 | 8 | public class TupleDecoder { 9 | 10 | private static final int MAX_BYTE_LENGTH_FOR_HEX_STRING = Type.MAX_BYTE_LENGTH << 1; 11 | private static final BigInteger OFFSET_DYNAMIC_ARRAY = BigInteger.valueOf(Type.MAX_BYTE_LENGTH); 12 | 13 | private String encoded; 14 | 15 | public TupleDecoder(String encoded) { 16 | this.encoded = Numeric.cleanHexPrefix(encoded); 17 | } 18 | 19 | public static TupleDecoder[] decodeDynamicArray(String encoded) { 20 | encoded = Numeric.cleanHexPrefix(encoded); 21 | 22 | TupleDecoder decoder = new TupleDecoder(encoded); 23 | 24 | BigInteger offset = decoder.nextUint256(); 25 | if (offset.compareTo(OFFSET_DYNAMIC_ARRAY) != 0) { 26 | throw new RuntimeException("invalid offset: " + offset); 27 | } 28 | 29 | int length = decoder.nextUint256().intValueExact(); 30 | int tupleLen = decoder.encoded.length() / length; 31 | TupleDecoder[] tuples = new TupleDecoder[length]; 32 | 33 | for (int i = 0; i < length; i++) { 34 | String encodedTuple = decoder.next(tupleLen); 35 | tuples[i] = new TupleDecoder(encodedTuple); 36 | } 37 | 38 | return tuples; 39 | } 40 | 41 | public String next() { 42 | return this.next(MAX_BYTE_LENGTH_FOR_HEX_STRING); 43 | } 44 | 45 | private String next(int len) { 46 | if (this.encoded.length() < len) { 47 | throw new RuntimeException("the length of encoded data is not enough"); 48 | } 49 | 50 | String field = this.encoded.substring(0, len); 51 | this.encoded = this.encoded.substring(len); 52 | 53 | return field; 54 | } 55 | 56 | public String nextAddress() { 57 | return Numeric.prependHexPrefix(this.next().substring(24)); 58 | } 59 | 60 | public BigInteger nextUint256() { 61 | return new BigInteger(this.next(), 16); 62 | } 63 | 64 | public boolean nextBool() { 65 | return this.nextUint256().equals(BigInteger.ONE); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/diagnostics/Recall.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.diagnostics; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Optional; 5 | 6 | import conflux.web3j.Cfx; 7 | import conflux.web3j.RpcException; 8 | import conflux.web3j.contract.abi.DecodeUtil; 9 | import conflux.web3j.request.Call; 10 | import conflux.web3j.request.Epoch; 11 | import conflux.web3j.response.Receipt; 12 | import conflux.web3j.response.StringResponse; 13 | import conflux.web3j.response.Transaction; 14 | import conflux.web3j.response.UsedGasAndCollateral; 15 | 16 | // @deprecated 17 | public class Recall { 18 | 19 | private Cfx cfx; 20 | 21 | public Recall(Cfx cfx) { 22 | this.cfx = cfx; 23 | } 24 | 25 | public String diagnoseFailure(String txHash) throws RpcException { 26 | Optional tx = this.cfx.getTransactionByHash(txHash).sendAndGet(); 27 | if (!tx.isPresent()) { 28 | return "tx not found"; 29 | } 30 | 31 | Optional receipt = this.cfx.getTransactionReceipt(txHash).sendAndGet(); 32 | if (!receipt.isPresent()) { 33 | return "receipt not found"; 34 | } 35 | 36 | if (receipt.get().getOutcomeStatus() == 0) { 37 | return "tx not failed"; 38 | } 39 | 40 | Call call = this.convert(tx.get()); 41 | 42 | return this.execute(tx.get(), receipt.get(), call); 43 | } 44 | 45 | private Call convert(Transaction tx) { 46 | Call call = new Call(); 47 | 48 | call.setFrom(tx.getFrom()); 49 | call.setNonce(tx.getNonce()); 50 | 51 | if (tx.getTo().isPresent()) { 52 | call.setTo(tx.getTo().get()); 53 | } 54 | 55 | call.setValue(tx.getValue()); 56 | call.setGasPrice(tx.getGasPrice()); 57 | call.setGas(tx.getGas()); 58 | call.setData(tx.getData()); 59 | call.setStorageLimit(tx.getStorageLimit()); 60 | 61 | return call; 62 | } 63 | 64 | private String execute(Transaction tx, Receipt receipt, Call call) { 65 | BigInteger execEpoch = receipt.getEpochNumber().subtract(BigInteger.ONE); 66 | 67 | StringResponse response = this.cfx.call(call, Epoch.numberOf(execEpoch)).sendWithRetry(); 68 | 69 | if (response.getError() == null) { 70 | return "Execution succeeded: " + response.getValue(); 71 | } else { 72 | return DecodeUtil.decodeErrorData(response.getError().getData()); 73 | } 74 | } 75 | 76 | public UsedGasAndCollateral estimate(String txHash) throws RpcException { 77 | Transaction tx = this.cfx.getTransactionByHash(txHash).sendAndGet().get(); 78 | Receipt receipt = this.cfx.getTransactionReceipt(txHash).sendAndGet().get(); 79 | 80 | Call call = this.convert(tx); 81 | call.setGas(null); 82 | call.setStorageLimit(null); 83 | 84 | BigInteger execEpoch = receipt.getEpochNumber().subtract(BigInteger.ONE); 85 | return this.cfx.estimateGasAndCollateral(call, Epoch.numberOf(execEpoch)).sendAndGet(); 86 | } 87 | 88 | public void diagnoseEstimation(String txHash) throws RpcException { 89 | Transaction tx = this.cfx.getTransactionByHash(txHash).sendAndGet().get(); 90 | Receipt receipt = this.cfx.getTransactionReceipt(txHash).sendAndGet().get(); 91 | 92 | Call call = this.convert(tx); 93 | call.setGas(null); 94 | call.setStorageLimit(null); 95 | 96 | BigInteger execEpoch = receipt.getEpochNumber().subtract(BigInteger.ONE); 97 | UsedGasAndCollateral estimation = this.cfx.estimateGasAndCollateral(call, Epoch.numberOf(execEpoch)).sendAndGet(); 98 | 99 | System.out.printf("Transaction: gas = %s, storage = %s\n", tx.getGas(), tx.getStorageLimit()); 100 | System.out.printf("Estimation : gas = %s, storage = %s\n", estimation.getGasUsed(), estimation.getStorageCollateralized()); 101 | 102 | if (tx.getGas().compareTo(estimation.getGasUsed()) < 0) { 103 | System.err.println("ERROR: gas not enough"); 104 | } 105 | 106 | if (tx.getStorageLimit().compareTo(estimation.getStorageCollateralized()) < 0) { 107 | System.err.println("ERROR: storage not enough"); 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/internals/AdminControl.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.internals; 2 | 3 | import conflux.web3j.Account; 4 | import conflux.web3j.Account.Option; 5 | import conflux.web3j.Cfx; 6 | import conflux.web3j.RpcException; 7 | import conflux.web3j.contract.ContractCall; 8 | import org.web3j.abi.datatypes.Address; 9 | import conflux.web3j.types.CfxAddress; 10 | 11 | public class AdminControl extends ContractCall { 12 | private final static String contract = "0x0888000000000000000000000000000000000000"; 13 | private Account account; // if account not set, can only use getAdmin method 14 | private CfxAddress contractAddress; 15 | 16 | public AdminControl(Account account) { 17 | super(account.getCfx(), new CfxAddress(AdminControl.contract, account.getCfx().getIntNetworkId())); 18 | this.contractAddress = new CfxAddress(AdminControl.contract, account.getCfx().getIntNetworkId()); 19 | this.account = account; 20 | } 21 | 22 | public AdminControl(Cfx cfx) { 23 | super(cfx, new CfxAddress(AdminControl.contract, cfx.getIntNetworkId())); 24 | this.contractAddress = new CfxAddress(AdminControl.contract, cfx.getIntNetworkId()); 25 | } 26 | 27 | public void setAccount(Account account) { 28 | this.account = account; 29 | } 30 | 31 | public Address getAdmin(Address contractAddr) throws RpcException { 32 | String hexAddress = this.callAndGet(Address.class, "getAdmin", contractAddr); 33 | return new Address(hexAddress); 34 | } 35 | 36 | public String destroy (Option option, Address contractAddr) throws Exception { 37 | Address admin = getAdmin(contractAddr); 38 | if (!admin.getValue().equalsIgnoreCase(account.getAddress().getHexAddress())) { 39 | throw new Exception("Administrator privilege required"); 40 | } 41 | return this.account.call(option, this.contractAddress, "destroy", contractAddr); 42 | } 43 | 44 | public String setAdmin(Option option, Address contractAddr, Address newAdmin) throws Exception { 45 | Address admin = getAdmin(contractAddr); 46 | if (!admin.getValue().equalsIgnoreCase(account.getAddress().getHexAddress())) { 47 | throw new Exception("Administrator privilege required"); 48 | } 49 | return this.account.call(option, this.contractAddress, "setAdmin", contractAddr, newAdmin); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/internals/CrossSpaceCall.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.internals; 2 | 3 | import conflux.web3j.Account; 4 | import conflux.web3j.Cfx; 5 | import conflux.web3j.RpcException; 6 | import conflux.web3j.contract.ContractCall; 7 | import conflux.web3j.types.CfxAddress; 8 | 9 | import java.math.BigInteger; 10 | 11 | import org.web3j.abi.datatypes.Address; 12 | import org.web3j.abi.datatypes.DynamicBytes; 13 | import org.web3j.abi.datatypes.generated.Uint256; 14 | import org.web3j.utils.Numeric; 15 | import org.web3j.abi.datatypes.generated.Bytes20; 16 | 17 | public class CrossSpaceCall extends ContractCall{ 18 | private final static String contract = "0x0888000000000000000000000000000000000006"; 19 | private Account account; // if account not set, can only use read method 20 | private CfxAddress contractAddress; 21 | 22 | public CrossSpaceCall(Account account) { 23 | super(account.getCfx(), new CfxAddress(CrossSpaceCall.contract, account.getCfx().getIntNetworkId())); 24 | this.contractAddress = new CfxAddress(CrossSpaceCall.contract, account.getCfx().getIntNetworkId()); 25 | this.account = account; 26 | } 27 | 28 | public CrossSpaceCall(Cfx cfx) { 29 | super(cfx, new CfxAddress(CrossSpaceCall.contract, cfx.getIntNetworkId())); 30 | this.contractAddress = new CfxAddress(CrossSpaceCall.contract, cfx.getIntNetworkId()); 31 | } 32 | 33 | public void setAccount(Account account) { 34 | this.account = account; 35 | } 36 | 37 | public String createEVM(Account.Option option, byte[] init)throws Exception{ 38 | return account.call(option, this.contractAddress, "createEVM", new DynamicBytes(init)); 39 | } 40 | 41 | public String createEVM(Account.Option option, String init)throws Exception{ 42 | return account.call(option, this.contractAddress, "createEVM", new DynamicBytes(Numeric.hexStringToByteArray(init))); 43 | } 44 | 45 | public String transferEVM(Account.Option option, byte[] to)throws Exception{ 46 | return account.call(option, this.contractAddress, "transferEVM", new Bytes20(to)); 47 | } 48 | 49 | public String transferEVM(Account.Option option, String to)throws Exception{ 50 | return account.call(option, this.contractAddress, "transferEVM", new Bytes20(Numeric.hexStringToByteArray(to))); 51 | } 52 | 53 | public String callEVM(Account.Option option, byte[] to, byte[] data)throws Exception{ 54 | return account.call(option, this.contractAddress, "callEVM", new Bytes20(to), new DynamicBytes(data)); 55 | } 56 | 57 | public String callEVM(Account.Option option, String to, String data)throws Exception{ 58 | return account.call(option, this.contractAddress, "callEVM", new Bytes20(Numeric.hexStringToByteArray(to)), new DynamicBytes(Numeric.hexStringToByteArray(data))); 59 | } 60 | 61 | public String staticCallEVM(Account.Option option, byte[] to, byte[] data)throws Exception{ 62 | return account.call(option, this.contractAddress, "staticCallEVM", new Bytes20(to), new DynamicBytes(data)); 63 | } 64 | 65 | public String staticCallEVM(Account.Option option, String to, String data)throws Exception{ 66 | return account.call(option, this.contractAddress, "staticCallEVM", new Bytes20(Numeric.hexStringToByteArray(to)), new DynamicBytes(Numeric.hexStringToByteArray(data))); 67 | } 68 | 69 | public String withdrawFromMapped(Account.Option option, BigInteger value)throws Exception{ 70 | return account.call(option, this.contractAddress, "withdrawFromMapped", new Uint256(value)); 71 | } 72 | 73 | public BigInteger mappedBalance(Address addr)throws RpcException{ 74 | return this.callAndGet(Uint256.class, "mappedBalance", addr); 75 | } 76 | 77 | public BigInteger mappedNonce(Address addr)throws RpcException{ 78 | return this.callAndGet(Uint256.class, "mappedNonce", addr); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/internals/PoSRegister.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.internals; 2 | 3 | import conflux.web3j.Account; 4 | import conflux.web3j.Cfx; 5 | import conflux.web3j.RpcException; 6 | import conflux.web3j.contract.ContractCall; 7 | import conflux.web3j.types.CfxAddress; 8 | import conflux.web3j.contract.abi.TupleDecoder; 9 | 10 | import java.math.BigInteger; 11 | 12 | import org.web3j.abi.datatypes.Address; 13 | import org.web3j.abi.datatypes.generated.Uint64; 14 | import org.web3j.abi.datatypes.generated.Bytes32; 15 | import org.web3j.utils.Numeric; 16 | 17 | 18 | 19 | public class PoSRegister extends ContractCall{ 20 | private final static String contract = "0x0888000000000000000000000000000000000005"; 21 | private Account account; // if account not set, can only use read method 22 | private CfxAddress contractAddress; 23 | 24 | public PoSRegister(Account account) { 25 | super(account.getCfx(), new CfxAddress(PoSRegister.contract, account.getCfx().getIntNetworkId())); 26 | this.contractAddress = new CfxAddress(PoSRegister.contract, account.getCfx().getIntNetworkId()); 27 | this.account = account; 28 | } 29 | 30 | public PoSRegister(Cfx cfx) { 31 | super(cfx, new CfxAddress(PoSRegister.contract, cfx.getIntNetworkId())); 32 | this.contractAddress = new CfxAddress(PoSRegister.contract, cfx.getIntNetworkId()); 33 | } 34 | 35 | public void setAccount(Account account) { 36 | this.account = account; 37 | } 38 | 39 | public String increaseStake(Account.Option option, BigInteger votePower)throws Exception{ 40 | return account.call(option, this.contractAddress, "increaseStake", new Uint64(votePower)); 41 | } 42 | 43 | public String register(Account.Option option, byte[] registerData) throws Exception { 44 | return account.callWithData(option, this.contractAddress, Numeric.toHexString(registerData)); 45 | } 46 | 47 | public String register(Account.Option option, String registerData) throws Exception { 48 | return account.callWithData(option, this.contractAddress, registerData); 49 | } 50 | 51 | public String retire(Account.Option option, BigInteger votePower)throws Exception{ 52 | return account.call(option, this.contractAddress, "retire", new Uint64(votePower)); 53 | } 54 | 55 | public BigInteger[] getVotes(byte[] identifier)throws RpcException{ 56 | BigInteger[] res = new BigInteger[2]; 57 | 58 | String rawData = this.call("getVotes", new Bytes32(identifier)).sendAndGet(); 59 | rawData = Numeric.cleanHexPrefix(rawData); 60 | TupleDecoder decoder = new TupleDecoder(rawData); 61 | 62 | res[0] = decoder.nextUint256(); 63 | res[1] = decoder.nextUint256(); 64 | return res; 65 | } 66 | 67 | public BigInteger[] getVotes(String identifier)throws RpcException{ 68 | BigInteger[] res = new BigInteger[2]; 69 | 70 | String rawData = this.call("getVotes", new Bytes32(Numeric.hexStringToByteArray(identifier))).sendAndGet(); 71 | rawData = Numeric.cleanHexPrefix(rawData); 72 | TupleDecoder decoder = new TupleDecoder(rawData); 73 | 74 | res[0] = decoder.nextUint256(); 75 | res[1] = decoder.nextUint256(); 76 | return res; 77 | } 78 | 79 | public Address identifierToAddress(byte[] identifier)throws RpcException{ 80 | String hexAddress = this.callAndGet(Address.class, "identifierToAddress", new Bytes32(identifier)); 81 | return new Address(hexAddress); 82 | } 83 | 84 | public Address identifierToAddress(String identifier)throws RpcException{ 85 | String hexAddress = this.callAndGet(Address.class, "identifierToAddress", new Bytes32(Numeric.hexStringToByteArray(identifier))); 86 | return new Address(hexAddress); 87 | } 88 | 89 | public Bytes32 addressToIdentifier(Address addr)throws RpcException{ 90 | byte[] bytes = this.callAndGet(Bytes32.class, "addressToIdentifier", addr); 91 | return new Bytes32(bytes); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/internals/SponsorWhitelistControl.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.internals; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.abi.datatypes.Bool; 6 | import org.web3j.abi.datatypes.DynamicArray; 7 | import org.web3j.abi.datatypes.generated.Uint256; 8 | import org.web3j.abi.datatypes.Address; 9 | 10 | import conflux.web3j.Account; 11 | import conflux.web3j.Cfx; 12 | import conflux.web3j.RpcException; 13 | import conflux.web3j.contract.ContractCall; 14 | import conflux.web3j.types.CfxAddress; 15 | 16 | 17 | public class SponsorWhitelistControl extends ContractCall { 18 | private final static String contract = "0x0888000000000000000000000000000000000001"; 19 | private Account account; 20 | private final CfxAddress contractAddress; 21 | 22 | public SponsorWhitelistControl(Account account) { 23 | super(account.getCfx(), new CfxAddress(SponsorWhitelistControl.contract, account.getCfx().getIntNetworkId())); 24 | this.contractAddress = new CfxAddress(SponsorWhitelistControl.contract, account.getCfx().getIntNetworkId()); 25 | this.account = account; 26 | } 27 | 28 | public SponsorWhitelistControl(Cfx cfx) { 29 | super(cfx, new CfxAddress(SponsorWhitelistControl.contract, cfx.getIntNetworkId())); 30 | this.contractAddress = new CfxAddress(SponsorWhitelistControl.contract, cfx.getIntNetworkId()); 31 | } 32 | 33 | public void setAccount(Account account) { 34 | this.account = account; 35 | } 36 | 37 | public Address getSponsorForGas(Address contractAddr) throws RpcException { 38 | String hexAddress = this.callAndGet(Address.class, "getSponsorForGas", contractAddr); 39 | return new Address(hexAddress); 40 | } 41 | 42 | public BigInteger getSponsoredBalanceForGas(Address contractAddr) throws RpcException { 43 | return this.callAndGet(Uint256.class, "getSponsoredBalanceForGas", contractAddr); 44 | } 45 | 46 | public BigInteger getSponsoredGasFeeUpperBound(Address contractAddr) throws RpcException { 47 | return this.callAndGet(Uint256.class, "getSponsoredGasFeeUpperBound", contractAddr); 48 | } 49 | 50 | public Address getSponsorForCollateral(Address contractAddr) throws RpcException { 51 | String hexAddress = this.callAndGet(Address.class, "getSponsorForCollateral", contractAddr); 52 | return new Address(hexAddress); 53 | } 54 | 55 | public BigInteger getSponsoredBalanceForCollateral(Address contractAddr) throws RpcException { 56 | return this.callAndGet(Uint256.class, "getSponsoredBalanceForCollateral", contractAddr); 57 | } 58 | 59 | public boolean isWhitelisted(Address contractAddr, Address user) throws RpcException { 60 | return this.callAndGet(Bool.class, "isWhitelisted", contractAddr, user); 61 | } 62 | 63 | public boolean isAllWhitelisted(Address contractAddr) throws RpcException { 64 | return this.callAndGet(Bool.class, "isAllWhitelisted", contractAddr); 65 | } 66 | 67 | // public void addPrivilege(Account.Option option, String[] addresses) throws Exception { 68 | // List
list = Arrays.stream(addresses).map(a -> new Address(a)).collect(Collectors.toList()); 69 | // account.call(option, contract, "addPrivilege", new DynamicArray
(Address.class, list)); 70 | // } 71 | // 72 | // public void removePrivilege(Account.Option option, String[] addresses) throws Exception { 73 | // List
list = Arrays.stream(addresses).map(a -> new Address(a)).collect(Collectors.toList()); 74 | // account.call(option, contract, "removePrivilege", new DynamicArray
(Address.class, list)); 75 | // } 76 | 77 | public String setSponsorForCollateral(Account.Option option, Address contractAddr) throws Exception { 78 | return account.call(option, this.contractAddress, "setSponsorForCollateral", contractAddr); 79 | } 80 | 81 | public String setSponsorForGas(Account.Option option, Address contractAddr, BigInteger upperBound) throws Exception { 82 | return account.call(option, this.contractAddress, "setSponsorForGas", contractAddr, new Uint256(upperBound)); 83 | } 84 | 85 | public String addPrivilegeByAdmin(Account.Option option, Address contractAddr, Address[] addresses) throws Exception { 86 | return account.call(option, this.contractAddress, "addPrivilegeByAdmin", contractAddr, new DynamicArray<>(Address.class, addresses)); 87 | } 88 | 89 | public String removePrivilegeByAdmin(Account.Option option, Address contractAddr, Address[] addresses) throws Exception { 90 | return account.call(option, this.contractAddress, "removePrivilegeByAdmin", contractAddr, new DynamicArray<>(Address.class, addresses)); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/contract/internals/Staking.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.contract.internals; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.abi.datatypes.generated.Uint256; 6 | import org.web3j.abi.datatypes.Address; 7 | 8 | import conflux.web3j.Account; 9 | import conflux.web3j.Cfx; 10 | import conflux.web3j.RpcException; 11 | import conflux.web3j.contract.ContractCall; 12 | import conflux.web3j.types.CfxAddress; 13 | 14 | public class Staking extends ContractCall { 15 | private final static String contract = "0x0888000000000000000000000000000000000002"; 16 | private Account account; 17 | private final CfxAddress contractAddress; 18 | 19 | public Staking(Account account) { 20 | super(account.getCfx(), new CfxAddress(Staking.contract, account.getCfx().getIntNetworkId())); 21 | this.contractAddress = new CfxAddress(Staking.contract, account.getCfx().getIntNetworkId()); 22 | this.account = account; 23 | } 24 | 25 | public Staking(Cfx cfx) { 26 | super(cfx, new CfxAddress(Staking.contract, cfx.getIntNetworkId())); 27 | this.contractAddress = new CfxAddress(Staking.contract, cfx.getIntNetworkId()); 28 | } 29 | 30 | public void setAccount(Account account) { 31 | this.account = account; 32 | } 33 | 34 | public BigInteger getStakingBalance(Address user) throws RpcException { 35 | return this.callAndGet(Uint256.class, "getStakingBalance", user); 36 | } 37 | 38 | public BigInteger getLockedStakingBalance(Address user, BigInteger blockNumber) throws RpcException { 39 | return this.callAndGet(Uint256.class,"getLockedStakingBalance", user, new Uint256(blockNumber)); 40 | } 41 | 42 | public BigInteger getVotePower(Address user, BigInteger blockNumber) throws RpcException { 43 | return this.callAndGet(Uint256.class, "getVotePower", user, new Uint256(blockNumber)); 44 | } 45 | 46 | public String deposit(Account.Option option, BigInteger amount) throws Exception { 47 | return account.call(option, this.contractAddress, "deposit", new Uint256(amount)); 48 | } 49 | 50 | public String voteLock(Account.Option option, BigInteger amount, BigInteger unlockBlockNumber) throws Exception { 51 | return account.call(option, this.contractAddress, "voteLock", new Uint256(amount), new Uint256(unlockBlockNumber)); 52 | } 53 | 54 | public String withdraw(Account.Option option, BigInteger amount) throws Exception { 55 | return account.call(option, this.contractAddress, "withdraw", new Uint256(amount)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/crypto/ConfluxBase32.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | import com.google.common.io.BaseEncoding; 3 | import java.util.HashMap; 4 | 5 | /** 6 | * CIP37 specification: https://github.com/Conflux-Chain/CIPs/blob/master/CIPs/cip-37.md 7 | */ 8 | 9 | public class ConfluxBase32 { 10 | private static final String CONFLUX_CHARSET = "abcdefghjkmnprstuvwxyz0123456789"; 11 | private static final String STANDARD_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 12 | private static final char PADDING_CHAR = '='; 13 | 14 | private static final HashMap CONFLUX_CHAR_MAP = new HashMap<>(); 15 | static { 16 | for (int i = 0; i < CONFLUX_CHARSET.length(); i++) { 17 | CONFLUX_CHAR_MAP.put(CONFLUX_CHARSET.charAt(i), i); 18 | } 19 | } 20 | 21 | private static final HashMap STANDARD_CHAR_MAP = new HashMap<>(); 22 | static { 23 | for (int i = 0; i < STANDARD_CHARSET.length(); i++) { 24 | STANDARD_CHAR_MAP.put(STANDARD_CHARSET.charAt(i), i); 25 | } 26 | } 27 | 28 | public static String encode(byte[] buffer) throws ConfluxBase32Exception { 29 | if (buffer == null) { 30 | throw new ConfluxBase32Exception("buffer is null or empty"); 31 | } 32 | return fromStandard(BaseEncoding.base32().encode(buffer)); 33 | } 34 | 35 | public static byte[] decode(String base32Str) throws ConfluxBase32Exception { 36 | if (!isValid(base32Str)) { 37 | throw new ConfluxBase32Exception(ConfluxBase32Exception.INVALID_BASE32_STR); 38 | } 39 | return BaseEncoding.base32().decode(toStandard(base32Str)); 40 | } 41 | 42 | public static byte[] decodeWords(String base32Words) throws ConfluxBase32Exception { 43 | if (!isValid(base32Words)) { 44 | throw new ConfluxBase32Exception(ConfluxBase32Exception.INVALID_BASE32_STR); 45 | } 46 | byte[] result = new byte[base32Words.length()]; 47 | for(int i = 0; i < base32Words.length(); i++) { 48 | int num = CONFLUX_CHAR_MAP.get(base32Words.charAt(i)); 49 | result[i] = (byte)num; 50 | } 51 | return result; 52 | } 53 | 54 | public static String encodeWords(byte[] words) throws ConfluxBase32Exception { 55 | if (words == null) { 56 | throw new ConfluxBase32Exception("buffer is null or empty"); 57 | } 58 | StringBuilder result = new StringBuilder(words.length); 59 | for (byte word : words) { 60 | if (word < 0 || word > 31) { 61 | throw new ConfluxBase32Exception(ConfluxBase32Exception.INVALID_BASE32_WORDS); 62 | } 63 | result.append(CONFLUX_CHARSET.charAt(word)); 64 | } 65 | return result.toString(); 66 | } 67 | 68 | public static boolean isValid(String base32Str) { 69 | if (base32Str == null) return false; 70 | for (int i = 0; i < base32Str.length(); i++) { 71 | if(!CONFLUX_CHAR_MAP.containsKey(base32Str.charAt(i))) { 72 | return false; 73 | } 74 | } 75 | return true; 76 | } 77 | 78 | private static String toStandard(String base32Str) { 79 | StringBuilder result = new StringBuilder(base32Str.length()); 80 | for(int i = 0; i < base32Str.length(); i++) { 81 | char c = base32Str.charAt(i); 82 | int index = CONFLUX_CHAR_MAP.get(c); 83 | result.append(STANDARD_CHARSET.charAt(index)); 84 | } 85 | return result.toString(); 86 | } 87 | 88 | private static String fromStandard(String standardBase32Str) { 89 | StringBuilder result = new StringBuilder(standardBase32Str.length()); 90 | for(int i = 0; i < standardBase32Str.length(); i++) { 91 | char c = standardBase32Str.charAt(i); 92 | if (c == PADDING_CHAR) { 93 | break; 94 | } 95 | int index = STANDARD_CHAR_MAP.get(c); 96 | result.append(CONFLUX_CHARSET.charAt(index)); 97 | } 98 | return result.toString(); 99 | } 100 | } 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/crypto/ConfluxBase32Exception.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | 3 | @SuppressWarnings("serial") 4 | class ConfluxBase32Exception extends RuntimeException { 5 | public static final String INVALID_BASE32_STR = "include invalid char"; 6 | public static final String INVALID_BASE32_WORDS = "word should in range [0-31]"; 7 | 8 | private String reason; 9 | 10 | public ConfluxBase32Exception(String reason) { 11 | super(String.format("Conflux base32 exception: (%s)", reason)); 12 | this.reason = reason; 13 | } 14 | 15 | public String getReason() { 16 | return reason; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/crypto/Sign.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | 3 | import org.web3j.crypto.ECDSASignature; 4 | import org.web3j.crypto.ECKeyPair; 5 | import org.web3j.crypto.Hash; 6 | import org.web3j.crypto.Keys; 7 | import org.web3j.utils.Numeric; 8 | 9 | import java.math.BigInteger; 10 | 11 | import static org.web3j.crypto.Sign.signMessage; 12 | import static org.web3j.crypto.Sign.SignatureData; 13 | 14 | public class Sign { 15 | static final String MESSAGE_PREFIX = "\u0019Conflux Signed Message:\n"; 16 | 17 | static byte[] getConfluxMessagePrefix(int messageLength) { 18 | return MESSAGE_PREFIX.concat(String.valueOf(messageLength)).getBytes(); 19 | } 20 | 21 | public static byte[] getConfluxMessageHash(byte[] message) { 22 | byte[] prefix = getConfluxMessagePrefix(message.length); 23 | 24 | byte[] result = new byte[prefix.length + message.length]; 25 | System.arraycopy(prefix, 0, result, 0, prefix.length); 26 | System.arraycopy(message, 0, result, prefix.length, message.length); 27 | 28 | return Hash.sha3(result); 29 | } 30 | 31 | public static SignatureData signPrefixedMessage(byte[] message, ECKeyPair keyPair) { 32 | return signMessage(getConfluxMessageHash(message), keyPair, false); 33 | } 34 | 35 | public static String recoverSignature(SignatureData sd, byte[] data, String address) { 36 | String addressRecovered = null; 37 | 38 | // Iterate for each possible key to recover 39 | for (int i = 0; i < 4; i++) { 40 | BigInteger publicKey = 41 | org.web3j.crypto.Sign.recoverFromSignature( 42 | (byte) i, 43 | new ECDSASignature( 44 | new BigInteger(1, sd.getR()), new BigInteger(1, sd.getS())), 45 | data); 46 | 47 | if (publicKey != null) { 48 | addressRecovered = Numeric.prependHexPrefix(Keys.getAddress(publicKey.toString())); 49 | 50 | if (addressRecovered.equals(address)) { 51 | break; 52 | } 53 | } 54 | } 55 | 56 | return addressRecovered; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/crypto/StructuredData.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | 3 | import java.math.BigInteger; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | 7 | import com.fasterxml.jackson.annotation.JsonCreator; 8 | import com.fasterxml.jackson.annotation.JsonProperty; 9 | 10 | import org.web3j.abi.datatypes.Address; 11 | import org.web3j.abi.datatypes.generated.Uint256; 12 | 13 | public class StructuredData { 14 | static class Entry { 15 | private final String name; 16 | private final String type; 17 | 18 | @JsonCreator 19 | public Entry( 20 | @JsonProperty(value = "name") String name, 21 | @JsonProperty(value = "type") String type) { 22 | this.name = name; 23 | this.type = type; 24 | } 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public String getType() { 31 | return type; 32 | } 33 | } 34 | 35 | static class CIP23Domain { 36 | private final String name; 37 | private final String version; 38 | private final Uint256 chainId; 39 | private final Address verifyingContract; 40 | private final String salt; 41 | 42 | @JsonCreator 43 | public CIP23Domain( 44 | @JsonProperty(value = "name") String name, 45 | @JsonProperty(value = "version") String version, 46 | @JsonProperty(value = "chainId") String chainId, 47 | @JsonProperty(value = "verifyingContract") Address verifyingContract, 48 | @JsonProperty(value = "salt") String salt) { 49 | this.name = name; 50 | this.version = version; 51 | this.chainId = chainId != null ? new Uint256(new BigInteger(chainId)) : null; 52 | this.verifyingContract = verifyingContract; 53 | this.salt = salt; 54 | } 55 | 56 | public String getName() { 57 | return name; 58 | } 59 | 60 | public String getVersion() { 61 | return version; 62 | } 63 | 64 | public Uint256 getChainId() { 65 | return chainId; 66 | } 67 | 68 | public Address getVerifyingContract() { 69 | return verifyingContract; 70 | } 71 | 72 | public String getSalt() { 73 | return salt; 74 | } 75 | } 76 | 77 | static class CIP23Message { 78 | private final HashMap> types; 79 | private final String primaryType; 80 | private final Object message; 81 | private final conflux.web3j.crypto.StructuredData.CIP23Domain domain; 82 | 83 | @JsonCreator 84 | public CIP23Message( 85 | @JsonProperty(value = "types") HashMap> types, 86 | @JsonProperty(value = "primaryType") String primaryType, 87 | @JsonProperty(value = "message") Object message, 88 | @JsonProperty(value = "domain") conflux.web3j.crypto.StructuredData.CIP23Domain domain) { 89 | this.types = types; 90 | this.primaryType = primaryType; 91 | this.message = message; 92 | this.domain = domain; 93 | } 94 | 95 | public HashMap> getTypes() { 96 | return types; 97 | } 98 | 99 | public String getPrimaryType() { 100 | return primaryType; 101 | } 102 | 103 | public Object getMessage() { 104 | return message; 105 | } 106 | 107 | public conflux.web3j.crypto.StructuredData.CIP23Domain getDomain() { 108 | return domain; 109 | } 110 | 111 | @Override 112 | public String toString() { 113 | return "CIP23Message{" 114 | + "primaryType='" 115 | + this.primaryType 116 | + '\'' 117 | + ", message='" 118 | + this.message 119 | + '\'' 120 | + '}'; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/request/Call.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.request; 2 | 3 | import java.math.BigInteger; 4 | 5 | import conflux.web3j.types.AccessListEntry; 6 | import conflux.web3j.types.Address; 7 | import org.web3j.utils.Numeric; 8 | import java.util.List; 9 | 10 | public class Call { 11 | private Address from; 12 | private Address to; 13 | private BigInteger gasPrice; 14 | private BigInteger gas; 15 | private BigInteger value; 16 | private String data; 17 | private BigInteger nonce; 18 | private BigInteger storageLimit; 19 | private BigInteger type; 20 | private BigInteger maxFeePerGas; 21 | private BigInteger maxPriorityFeePerGas; 22 | private List accessList; 23 | 24 | public Address getFrom() { 25 | return from; 26 | } 27 | 28 | public void setFrom(Address from) { 29 | this.from = from; 30 | } 31 | 32 | public Address getTo() { 33 | return to; 34 | } 35 | 36 | public void setTo(Address to) { 37 | this.to = to; 38 | } 39 | 40 | public String getGasPrice() { 41 | return this.gasPrice == null ? null : Numeric.encodeQuantity(this.gasPrice); 42 | } 43 | 44 | public String getMaxFeePerGas() { 45 | return this.maxFeePerGas == null ? null : Numeric.encodeQuantity(this.maxFeePerGas); 46 | } 47 | 48 | public void setMaxFeePerGas(BigInteger maxFeePerGas) { 49 | this.maxFeePerGas = maxFeePerGas; 50 | } 51 | 52 | public String getMaxPriorityFeePerGas() { 53 | return this.maxPriorityFeePerGas == null ? null : Numeric.encodeQuantity(this.maxPriorityFeePerGas); 54 | } 55 | 56 | public void setMaxPriorityFeePerGas(BigInteger maxPriorityFeePerGas) { 57 | this.maxPriorityFeePerGas = maxPriorityFeePerGas; 58 | } 59 | 60 | public void setType(BigInteger type) { 61 | this.type = type; 62 | } 63 | 64 | public String getType() { 65 | return this.type == null ? null : Numeric.encodeQuantity(this.type); 66 | } 67 | 68 | public List getAccessList() { 69 | return accessList; 70 | } 71 | 72 | public void setAccessList(List accessList) { 73 | this.accessList = accessList; 74 | } 75 | 76 | public void setGasPrice(BigInteger gasPrice) { 77 | this.gasPrice = gasPrice; 78 | } 79 | 80 | public String getGas() { 81 | return this.gas == null ? null : Numeric.encodeQuantity(this.gas); 82 | } 83 | 84 | public void setGas(BigInteger gas) { 85 | this.gas = gas; 86 | } 87 | 88 | public String getValue() { 89 | return this.value == null ? null : Numeric.encodeQuantity(this.value); 90 | } 91 | 92 | public void setValue(BigInteger value) { 93 | this.value = value; 94 | } 95 | 96 | public String getData() { 97 | return this.data == null ? null : Numeric.prependHexPrefix(this.data); 98 | } 99 | 100 | public void setData(String data) { 101 | this.data = data; 102 | } 103 | 104 | public String getNonce() { 105 | return this.nonce == null ? null : Numeric.encodeQuantity(this.nonce); 106 | } 107 | 108 | public void setNonce(BigInteger nonce) { 109 | this.nonce = nonce; 110 | } 111 | 112 | public String getStorageLimit() { 113 | return this.storageLimit == null ? null : Numeric.encodeQuantity(this.storageLimit); 114 | } 115 | 116 | public void setStorageLimit(BigInteger storageLimit) { 117 | this.storageLimit = storageLimit; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/request/Epoch.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.request; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.utils.Numeric; 6 | 7 | import com.fasterxml.jackson.annotation.JsonValue; 8 | 9 | import conflux.web3j.HasValue; 10 | 11 | public interface Epoch extends HasValue { 12 | static Epoch earliest() { 13 | return DefaultEpoch.EARLIEST; 14 | } 15 | 16 | static Epoch latestState() { 17 | return DefaultEpoch.LATEST_STATE; 18 | } 19 | 20 | static Epoch latestMined() { 21 | return DefaultEpoch.LATEST_MINED; 22 | } 23 | 24 | static Epoch latestCheckpoint() { 25 | return DefaultEpoch.LATEST_CHECKPOINT; 26 | } 27 | 28 | static Epoch latestConfirmed() { 29 | return DefaultEpoch.LATEST_CONFIRMED; 30 | } 31 | 32 | static Epoch latestFinalized() { 33 | return DefaultEpoch.LATEST_FINALIZED; 34 | } 35 | 36 | static Epoch numberOf(long number) { 37 | String value = Numeric.encodeQuantity(BigInteger.valueOf(number)); 38 | return new EpochByValue(value); 39 | } 40 | 41 | static Epoch numberOf(BigInteger number) { 42 | String value = Numeric.encodeQuantity(number); 43 | return new EpochByValue(value); 44 | } 45 | 46 | static Epoch hashOf(String blockHash) { 47 | return new EpochByValue(blockHash); 48 | } 49 | } 50 | 51 | enum DefaultEpoch implements Epoch { 52 | EARLIEST("earliest"), 53 | LATEST_STATE("latest_state"), 54 | LATEST_MINED("latest_mined"), 55 | LATEST_CHECKPOINT("latest_checkpoint"), 56 | LATEST_CONFIRMED("latest_confirmed"), 57 | LATEST_FINALIZED("latest_finalized"); 58 | 59 | private String value; 60 | 61 | DefaultEpoch(String value) { 62 | this.value = value; 63 | } 64 | 65 | @JsonValue 66 | @Override 67 | public String getValue() { 68 | return this.value; 69 | } 70 | } 71 | 72 | class EpochByValue implements Epoch { 73 | private String value; 74 | 75 | public EpochByValue(String value) { 76 | this.value = value; 77 | } 78 | 79 | @JsonValue 80 | @Override 81 | public String getValue() { 82 | return this.value; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/request/LogFilter.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.request; 2 | 3 | import java.math.BigInteger; 4 | import java.util.List; 5 | 6 | import org.web3j.utils.Numeric; 7 | 8 | import conflux.web3j.types.Address; 9 | 10 | public class LogFilter { 11 | private Epoch fromEpoch; 12 | private Epoch toEpoch; 13 | private List blockHashes; 14 | private List
address; 15 | private List> topics; 16 | private Long limit; 17 | private Long offset; 18 | 19 | public Epoch getFromEpoch() { 20 | return fromEpoch; 21 | } 22 | 23 | public void setFromEpoch(Epoch fromEpoch) { 24 | this.fromEpoch = fromEpoch; 25 | } 26 | 27 | public Epoch getToEpoch() { 28 | return toEpoch; 29 | } 30 | 31 | public void setToEpoch(Epoch toEpoch) { 32 | this.toEpoch = toEpoch; 33 | } 34 | 35 | public List getBlockHashes() { 36 | return blockHashes; 37 | } 38 | 39 | public void setBlockHashes(List blockHashes) { 40 | this.blockHashes = blockHashes; 41 | } 42 | 43 | public List
getAddress() { 44 | return address; 45 | } 46 | 47 | public void setAddress(List
address) { 48 | this.address = address; 49 | } 50 | 51 | public List> getTopics() { 52 | return topics; 53 | } 54 | 55 | public void setTopics(List> topics) { 56 | this.topics = topics; 57 | } 58 | 59 | public String getLimit() { 60 | if (this.limit == null) { 61 | return null; 62 | } else { 63 | return Numeric.encodeQuantity(BigInteger.valueOf(this.limit)); 64 | } 65 | } 66 | 67 | public void setLimit(Long limit) { 68 | this.limit = limit; 69 | } 70 | 71 | public String getOffset() { 72 | if (this.offset == null) { 73 | return null; 74 | } else { 75 | return Numeric.encodeQuantity(BigInteger.valueOf(this.offset)); 76 | } 77 | } 78 | 79 | public void setOffset(Long offset) { 80 | this.offset = offset; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/request/TraceFilter.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.request; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | 8 | public class TraceFilter { 9 | private Epoch fromEpoch; 10 | private Epoch toEpoch; 11 | private List blockHashes; 12 | private List actionTypes; 13 | private Long after; 14 | private Long count; 15 | 16 | public List getActionTypes() { 17 | return actionTypes; 18 | } 19 | 20 | public void setActionTypes(List actionTypes) { 21 | this.actionTypes = actionTypes; 22 | } 23 | 24 | public Epoch getFromEpoch() { 25 | return fromEpoch; 26 | } 27 | 28 | public void setFromEpoch(Epoch fromEpoch) { 29 | this.fromEpoch = fromEpoch; 30 | } 31 | 32 | public Epoch getToEpoch() { 33 | return toEpoch; 34 | } 35 | 36 | public void setToEpoch(Epoch toEpoch) { 37 | this.toEpoch = toEpoch; 38 | } 39 | 40 | public List getBlockHashes() { 41 | return blockHashes; 42 | } 43 | 44 | public void setBlockHashes(List blockHashes) { 45 | this.blockHashes = blockHashes; 46 | } 47 | 48 | public String getAfter() { 49 | if (this.after == null) { 50 | return null; 51 | } else { 52 | return Numeric.encodeQuantity(BigInteger.valueOf(this.after)); 53 | } 54 | } 55 | 56 | public void setAfter(Long limit) { 57 | this.after = limit; 58 | } 59 | 60 | public String getCount() { 61 | if (this.count == null) { 62 | return null; 63 | } else { 64 | return Numeric.encodeQuantity(BigInteger.valueOf(this.count)); 65 | } 66 | } 67 | 68 | public void setCount(Long offset) { 69 | this.count = offset; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/AccountInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | 5 | import conflux.web3j.types.Address; 6 | import org.web3j.utils.Numeric; 7 | 8 | public class AccountInfo { 9 | 10 | public static class Response extends CfxResponse {} 11 | 12 | private Address address; 13 | private String balance; 14 | private String nonce; 15 | private String codeHash; 16 | private String stakingBalance; 17 | private String collateralForStorage; 18 | private String accumulatedInterestReturn; 19 | private Address admin; 20 | 21 | public Address getAddress() { 22 | return address; 23 | } 24 | 25 | public void setAddress(Address address) { 26 | this.address = address; 27 | } 28 | 29 | public BigInteger getBalance() { 30 | return Numeric.decodeQuantity(this.balance); 31 | } 32 | 33 | public void setBalance(String balance) { 34 | this.balance = balance; 35 | } 36 | 37 | public BigInteger getNonce() { 38 | return Numeric.decodeQuantity(this.nonce); 39 | } 40 | 41 | public void setNonce(String nonce) { 42 | this.nonce = nonce; 43 | } 44 | 45 | public String getCodeHash() { 46 | return codeHash; 47 | } 48 | 49 | public void setCodeHash(String codeHash) { 50 | this.codeHash = codeHash; 51 | } 52 | 53 | public BigInteger getStakingBalance() { 54 | return Numeric.decodeQuantity(this.stakingBalance); 55 | } 56 | 57 | public void setStakingBalance(String stakingBalance) { 58 | this.stakingBalance = stakingBalance; 59 | } 60 | 61 | public BigInteger getCollateralForStorage() { 62 | return Numeric.decodeQuantity(this.collateralForStorage); 63 | } 64 | 65 | public void setCollateralForStorage(String collateralForStorage) { 66 | this.collateralForStorage = collateralForStorage; 67 | } 68 | 69 | public BigInteger getAccumulatedInterestReturn() { 70 | return Numeric.decodeQuantity(this.accumulatedInterestReturn); 71 | } 72 | 73 | public void setAccumulatedInterestReturn(String accumulatedInterestReturn) { 74 | this.accumulatedInterestReturn = accumulatedInterestReturn; 75 | } 76 | 77 | public Address getAdmin() { 78 | return admin; 79 | } 80 | 81 | public void setAdmin(Address admin) { 82 | this.admin = admin; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/AccountPendingInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import conflux.web3j.utils.Utils; 5 | import org.web3j.utils.Numeric; 6 | 7 | import java.math.BigInteger; 8 | 9 | public class AccountPendingInfo { 10 | public static class Response extends CfxNullableResponse {} 11 | 12 | private String localNonce; 13 | private String pendingCount; 14 | private String pendingNonce; 15 | private String nextPendingTx; 16 | 17 | public BigInteger getPendingNonce() { 18 | return Numeric.decodeQuantity(this.pendingNonce); 19 | } 20 | 21 | public void setPendingNonce(String pendingNonce) { 22 | this.pendingNonce = pendingNonce; 23 | } 24 | 25 | public BigInteger getLocalNonce() { 26 | return Numeric.decodeQuantity(this.localNonce); 27 | } 28 | 29 | public void setLocalNonce(String localNonce) { 30 | this.localNonce = localNonce; 31 | } 32 | 33 | public BigInteger getPendingCount() { 34 | return Numeric.decodeQuantity(this.pendingCount); 35 | } 36 | 37 | public void setPendingCount(String pendingCount) { 38 | this.pendingCount = pendingCount; 39 | } 40 | 41 | public String getNextPendingTx() { 42 | return this.nextPendingTx; 43 | } 44 | 45 | public void setNextPendingTx(String nextPendingTx) { 46 | this.nextPendingTx = nextPendingTx; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return Utils.jsonStringify(this); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/AccountPendingTransactions.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import conflux.web3j.utils.Utils; 5 | import org.web3j.utils.Numeric; 6 | 7 | import java.math.BigInteger; 8 | import java.util.List; 9 | import java.util.Optional; 10 | 11 | public class AccountPendingTransactions { 12 | public static class Response extends CfxResponse {} 13 | 14 | private String pendingCount; 15 | private TxPendingStatus firstTxStatus; 16 | private List pendingTransactions; 17 | 18 | public Optional getFirstTxStatus() { 19 | if (this.firstTxStatus == null) { 20 | return Optional.empty(); 21 | } else { 22 | return Optional.of(this.firstTxStatus); 23 | } 24 | } 25 | 26 | public void setFirstTxStatus(TxPendingStatus firstTxStatus) { 27 | this.firstTxStatus = firstTxStatus; 28 | } 29 | 30 | public List getPendingTransactions() { 31 | return pendingTransactions; 32 | } 33 | 34 | public void setPendingTransactions(List pendingTransactions) { 35 | this.pendingTransactions = pendingTransactions; 36 | } 37 | 38 | public BigInteger getPendingCount() { 39 | return Numeric.decodeQuantity(this.pendingCount); 40 | } 41 | 42 | public void setPendingCount(String pendingCount) { 43 | this.pendingCount = pendingCount; 44 | } 45 | 46 | public class TxPendingStatus { 47 | private String pending; 48 | 49 | public String getPending() {return this.pending;} 50 | 51 | public void setPending(String pending) {this.pending = pending;} 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return Utils.jsonStringify(this); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Action.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import conflux.web3j.types.Address; 4 | import org.web3j.utils.Numeric; 5 | 6 | import java.math.BigInteger; 7 | 8 | public class Action { 9 | // call 10 | private String callType; 11 | private Address from; 12 | private String gas; 13 | private String input; 14 | private Address to; 15 | private String value; 16 | // create 17 | private String init; 18 | // call result 19 | private String outcome; 20 | private String gasLeft; 21 | private String returnData; 22 | // create result 23 | private String addr; 24 | 25 | public BigInteger getGas() { 26 | return Numeric.decodeQuantity(gas); 27 | } 28 | 29 | public String getInput() { 30 | return input; 31 | } 32 | 33 | public Address getTo() { 34 | return to; 35 | } 36 | 37 | public BigInteger getValue() { 38 | return Numeric.decodeQuantity(value); 39 | } 40 | 41 | public String getInit() { 42 | return init; 43 | } 44 | 45 | public String getOutcome() { 46 | return outcome; 47 | } 48 | 49 | public BigInteger getGasLeft() { 50 | return Numeric.decodeQuantity(gasLeft); 51 | } 52 | 53 | public String getReturnData() { 54 | return returnData; 55 | } 56 | 57 | public String getAddr() { 58 | return addr; 59 | } 60 | 61 | public void setGas(String gas) { 62 | this.gas = gas; 63 | } 64 | 65 | public void setInput(String input) { 66 | this.input = input; 67 | } 68 | 69 | public void setTo(Address to) { 70 | this.to = to; 71 | } 72 | 73 | public void setValue(String value) { 74 | this.value = value; 75 | } 76 | 77 | public void setInit(String init) { 78 | this.init = init; 79 | } 80 | 81 | public void setOutcome(String outcome) { 82 | this.outcome = outcome; 83 | } 84 | 85 | public void setGasLeft(String gasLeft) { 86 | this.gasLeft = gasLeft; 87 | } 88 | 89 | public void setReturnData(String returnData) { 90 | this.returnData = returnData; 91 | } 92 | 93 | public void setAddr(String addr) { 94 | this.addr = addr; 95 | } 96 | 97 | public void setCallType(String callType) { 98 | this.callType = callType; 99 | } 100 | 101 | public String getCallType() { 102 | return this.callType; 103 | } 104 | 105 | public void setFrom(Address from) { 106 | this.from = from; 107 | } 108 | 109 | public Address getFrom() { 110 | return this.from; 111 | } 112 | } 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BigIntNullableResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Optional; 5 | 6 | import org.web3j.protocol.core.Response; 7 | import org.web3j.utils.Numeric; 8 | 9 | import conflux.web3j.HasValue; 10 | 11 | public class BigIntNullableResponse extends Response implements HasValue> { 12 | 13 | @Override 14 | public Optional getValue() { 15 | String hexEncoded = this.getResult(); 16 | 17 | if (hexEncoded == null) { 18 | return Optional.empty(); 19 | } else { 20 | return Optional.of(Numeric.decodeQuantity(hexEncoded)); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BigIntResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.protocol.core.Response; 6 | import org.web3j.utils.Numeric; 7 | 8 | import conflux.web3j.HasValue; 9 | 10 | public class BigIntResponse extends Response implements HasValue { 11 | 12 | @Override 13 | public BigInteger getValue() { 14 | String hexEncoded = this.getResult(); 15 | return Numeric.decodeQuantity(hexEncoded); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Block.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.util.List; 4 | 5 | public class Block extends BlockHeader { 6 | 7 | public static class Response extends CfxNullableResponse {} 8 | 9 | public static class ListResponse extends CfxListResponse {} 10 | 11 | private List transactions; 12 | 13 | public List getTransactions() { 14 | return transactions; 15 | } 16 | 17 | public void setTransactions(List transactions) { 18 | this.transactions = transactions; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BlockHeader.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import conflux.web3j.types.Address; 8 | import org.web3j.utils.Numeric; 9 | 10 | public class BlockHeader { 11 | private String hash; 12 | private String parentHash; 13 | private String height; 14 | private Address miner; 15 | private String deferredStateRoot; 16 | private String deferredReceiptsRoot; 17 | private String deferredLogsBloomHash; 18 | private String blame; 19 | private String transactionsRoot; 20 | private String epochNumber; 21 | private String gasLimit; 22 | private String timestamp; 23 | private String difficulty; 24 | private List refereeHashes; 25 | private boolean adaptive; 26 | private String nonce; 27 | private String size; 28 | private String posReference; 29 | private List custom; 30 | private String baseFeePerGas; 31 | 32 | public BigInteger getBaseFeePerGas() { 33 | return Numeric.decodeQuantity(this.baseFeePerGas); 34 | } 35 | 36 | public void setBaseFeePerGas(String baseFeePerGas) { 37 | this.baseFeePerGas = baseFeePerGas; 38 | } 39 | 40 | public String getHash() { 41 | return hash; 42 | } 43 | 44 | public void setHash(String hash) { 45 | this.hash = hash; 46 | } 47 | 48 | public String getParentHash() { 49 | return parentHash; 50 | } 51 | 52 | public void setParentHash(String parentHash) { 53 | this.parentHash = parentHash; 54 | } 55 | 56 | public BigInteger getHeight() { 57 | return Numeric.decodeQuantity(this.height); 58 | } 59 | 60 | public void setHeight(String height) { 61 | this.height = height; 62 | } 63 | 64 | public Address getMiner() { 65 | return miner; 66 | } 67 | 68 | public void setMiner(Address miner) { 69 | this.miner = miner; 70 | } 71 | 72 | public String getDeferredStateRoot() { 73 | return deferredStateRoot; 74 | } 75 | 76 | public void setDeferredStateRoot(String deferredStateRoot) { 77 | this.deferredStateRoot = deferredStateRoot; 78 | } 79 | 80 | public String getDeferredReceiptsRoot() { 81 | return deferredReceiptsRoot; 82 | } 83 | 84 | public void setDeferredReceiptsRoot(String deferredReceiptsRoot) { 85 | this.deferredReceiptsRoot = deferredReceiptsRoot; 86 | } 87 | 88 | public String getDeferredLogsBloomHash() { 89 | return deferredLogsBloomHash; 90 | } 91 | 92 | public void setDeferredLogsBloomHash(String deferredLogsBloomHash) { 93 | this.deferredLogsBloomHash = deferredLogsBloomHash; 94 | } 95 | 96 | public BigInteger getBlame() { 97 | return Numeric.decodeQuantity(this.blame); 98 | } 99 | 100 | public void setBlame(String blame) { 101 | this.blame = blame; 102 | } 103 | 104 | public String getTransactionsRoot() { 105 | return transactionsRoot; 106 | } 107 | 108 | public void setTransactionsRoot(String transactionsRoot) { 109 | this.transactionsRoot = transactionsRoot; 110 | } 111 | 112 | public Optional getEpochNumber() { 113 | if (this.epochNumber == null || this.epochNumber.isEmpty()) { 114 | return Optional.empty(); 115 | } else { 116 | return Optional.of(Numeric.decodeQuantity(this.epochNumber)); 117 | } 118 | } 119 | 120 | public void setEpochNumber(String epochNumber) { 121 | this.epochNumber = epochNumber; 122 | } 123 | 124 | public BigInteger getGasLimit() { 125 | return Numeric.decodeQuantity(this.gasLimit); 126 | } 127 | 128 | public void setGasLimit(String gasLimit) { 129 | this.gasLimit = gasLimit; 130 | } 131 | 132 | public BigInteger getTimestamp() { 133 | return Numeric.decodeQuantity(this.timestamp); 134 | } 135 | 136 | public void setTimestamp(String timestamp) { 137 | this.timestamp = timestamp; 138 | } 139 | 140 | public BigInteger getDifficulty() { 141 | return Numeric.decodeQuantity(this.difficulty); 142 | } 143 | 144 | public void setDifficulty(String difficulty) { 145 | this.difficulty = difficulty; 146 | } 147 | 148 | public List getRefereeHashes() { 149 | return refereeHashes; 150 | } 151 | 152 | public void setRefereeHashes(List refereeHashes) { 153 | this.refereeHashes = refereeHashes; 154 | } 155 | 156 | public boolean isAdaptive() { 157 | return adaptive; 158 | } 159 | 160 | public void setAdaptive(boolean adaptive) { 161 | this.adaptive = adaptive; 162 | } 163 | 164 | public BigInteger getNonce() { 165 | return Numeric.decodeQuantity(this.nonce); 166 | } 167 | 168 | public void setNonce(String nonce) { 169 | this.nonce = nonce; 170 | } 171 | 172 | public Optional getSize() { 173 | if (this.size == null || this.size.isEmpty()) { 174 | return Optional.empty(); 175 | } else { 176 | return Optional.of(Numeric.decodeQuantity(this.size)); 177 | } 178 | } 179 | 180 | public void setSize(String size) { 181 | this.size = size; 182 | } 183 | 184 | public void setPosReference(String posReference) { 185 | this.posReference = posReference; 186 | } 187 | 188 | public String getPosReference() { 189 | return posReference; 190 | } 191 | 192 | public List getCustom() { 193 | return custom; 194 | } 195 | 196 | public void setCustom(List custom) { 197 | this.custom = custom; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BlockRevertRateResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.BigInteger; 5 | import java.math.RoundingMode; 6 | 7 | import org.web3j.protocol.core.Response; 8 | import org.web3j.utils.Numeric; 9 | 10 | import conflux.web3j.HasValue; 11 | 12 | public class BlockRevertRateResponse extends Response implements HasValue { 13 | 14 | private static final BigDecimal BASE = new BigDecimal(BigInteger.valueOf(2).pow(256)); 15 | 16 | public static int defaultScale = 7; 17 | 18 | @Override 19 | public BigDecimal getValue() { 20 | String hexValue = this.getResult(); 21 | if (hexValue == null) { 22 | return BigDecimal.ONE; 23 | } 24 | 25 | BigInteger risk = Numeric.decodeQuantity(hexValue); 26 | 27 | return new BigDecimal(risk).divide(BASE, defaultScale, RoundingMode.UP); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BlockSummary.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.util.List; 4 | 5 | public class BlockSummary extends BlockHeader { 6 | 7 | public static class Response extends CfxNullableResponse {} 8 | 9 | private List transactions; 10 | 11 | public List getTransactions() { 12 | return transactions; 13 | } 14 | 15 | public void setTransactions(List transactions) { 16 | this.transactions = transactions; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BlockTxInnerTrace.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class BlockTxInnerTrace { 4 | public Action getAction() { 5 | return action; 6 | } 7 | 8 | public void setAction(Action action) { 9 | this.action = action; 10 | } 11 | 12 | public String getType() { 13 | return type; 14 | } 15 | 16 | public void setType(String type) { 17 | this.type = type; 18 | } 19 | 20 | private Action action; 21 | private String type; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/BlockTxTrace.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | 8 | public class BlockTxTrace { 9 | public List getTraces() { 10 | return traces; 11 | } 12 | 13 | public void setTraces(List traces) { 14 | this.traces = traces; 15 | } 16 | 17 | public BigInteger getTransactionPosition() { 18 | return Numeric.decodeQuantity(transactionPosition); 19 | } 20 | 21 | public void setTransactionPosition(String transactionPosition) { 22 | this.transactionPosition = transactionPosition; 23 | } 24 | 25 | public String getTransactionHash() { 26 | return transactionHash; 27 | } 28 | 29 | public void setTransactionHash(String transactionHash) { 30 | this.transactionHash = transactionHash; 31 | } 32 | 33 | private List traces; 34 | private String transactionPosition; 35 | private String transactionHash; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/CfxResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import org.web3j.protocol.core.Response; 8 | 9 | import conflux.web3j.HasValue; 10 | 11 | class CfxResponse extends Response implements HasValue { 12 | 13 | @Override 14 | public T getValue() { 15 | return this.getResult(); 16 | } 17 | 18 | } 19 | 20 | class CfxNullableResponse extends Response implements HasValue> { 21 | 22 | @Override 23 | public Optional getValue() { 24 | return Optional.ofNullable(this.getResult()); 25 | } 26 | 27 | } 28 | 29 | class CfxListResponse extends Response> implements HasValue> { 30 | 31 | @Override 32 | public List getValue() { 33 | List value = this.getResult(); 34 | return value == null ? Collections.emptyList() : value; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/DepositInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | 7 | public class DepositInfo { 8 | public static class ListResponse extends CfxListResponse {} 9 | 10 | private String amount; 11 | private String depositTime; 12 | private String accumulatedInterestRate; 13 | 14 | public BigInteger getAmount() {return Numeric.decodeQuantity(amount);} 15 | 16 | public void setAmount(String amount) {this.amount = amount;} 17 | 18 | public long getDepositTime() {return Long.valueOf(depositTime);} 19 | 20 | public void setDepositTime(String time) {this.depositTime = time;} 21 | 22 | public BigInteger getAccumulatedInterestRate() {return Numeric.decodeQuantity(accumulatedInterestRate);} 23 | 24 | public void setAccumulatedInterestRate(String rate) {this.accumulatedInterestRate = rate;} 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/FeeHistory.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | import org.web3j.utils.Numeric; 3 | 4 | import java.math.BigInteger; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | public class FeeHistory { 9 | public static class Response extends CfxResponse {} 10 | 11 | private String oldestEpoch; 12 | private List baseFeePerGas; 13 | private List gasUsedRatio; 14 | private List reward; 15 | 16 | public BigInteger getOldestEpoch() { 17 | return Numeric.decodeQuantity(oldestEpoch); 18 | } 19 | 20 | public void setOldestEpoch(String oldestEpoch) { 21 | this.oldestEpoch = oldestEpoch; 22 | } 23 | 24 | public List getBaseFeePerGas() { 25 | return baseFeePerGas.stream().map(Numeric::decodeQuantity).collect(Collectors.toList()); 26 | } 27 | 28 | public void setBaseFeePerGas(List baseFeePerGas) { 29 | this.baseFeePerGas = baseFeePerGas; 30 | } 31 | 32 | public List getGasUsedRatio() { 33 | return gasUsedRatio; 34 | } 35 | 36 | public void setGasUsedRatio(List gasUsedRatio) { 37 | this.gasUsedRatio = gasUsedRatio; 38 | } 39 | 40 | public List getReward() { 41 | return reward.stream().map(Numeric::decodeQuantity).collect(Collectors.toList()); 42 | } 43 | 44 | public void setReward(List reward) { 45 | this.reward = reward; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/LocalizedBlockTrace.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | 8 | public class LocalizedBlockTrace { 9 | public static class Response extends CfxNullableResponse {} 10 | 11 | private List transactionTraces; 12 | private String epochHash; 13 | private String epochNumber; 14 | private String blockHash; 15 | 16 | public List getTransactionTraces() { 17 | return transactionTraces; 18 | } 19 | 20 | public void setTransactionTraces(List transactionTraces) { 21 | this.transactionTraces = transactionTraces; 22 | } 23 | 24 | public String getEpochHash() { 25 | return epochHash; 26 | } 27 | 28 | public void setEpochHash(String epochHash) { 29 | this.epochHash = epochHash; 30 | } 31 | 32 | public BigInteger getEpochNumber() { 33 | return Numeric.decodeQuantity(epochNumber); 34 | } 35 | 36 | public void setEpochNumber(String epochNumber) { 37 | this.epochNumber = epochNumber; 38 | } 39 | 40 | public String getBlockHash() { 41 | return blockHash; 42 | } 43 | 44 | public void setBlockHash(String blockHash) { 45 | this.blockHash = blockHash; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/LocalizedTrace.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | 8 | public class LocalizedTrace { 9 | public static class Response extends CfxNullableResponse> {} 10 | 11 | public Action getAction() { 12 | return action; 13 | } 14 | 15 | public String getEpochHash() { 16 | return epochHash; 17 | } 18 | 19 | public BigInteger getEpochNumber() { 20 | return Numeric.decodeQuantity(epochNumber); 21 | } 22 | 23 | public String getBlockHash() { 24 | return blockHash; 25 | } 26 | 27 | public BigInteger getTransactionPosition() { 28 | return Numeric.decodeQuantity(transactionPosition); 29 | } 30 | 31 | public String getTransactionHash() { 32 | return transactionHash; 33 | } 34 | 35 | public String getType() { 36 | return type; 37 | } 38 | 39 | public void setAction(Action action) { 40 | this.action = action; 41 | } 42 | 43 | public void setEpochHash(String epochHash) { 44 | this.epochHash = epochHash; 45 | } 46 | 47 | public void setEpochNumber(String epochNumber) { 48 | this.epochNumber = epochNumber; 49 | } 50 | 51 | public void setBlockHash(String blockHash) { 52 | this.blockHash = blockHash; 53 | } 54 | 55 | public void setTransactionPosition(String transactionPosition) { 56 | this.transactionPosition = transactionPosition; 57 | } 58 | 59 | public void setTransactionHash(String transactionHash) { 60 | this.transactionHash = transactionHash; 61 | } 62 | 63 | public void setType(String type) { 64 | this.type = type; 65 | } 66 | 67 | private Action action; 68 | private String type; 69 | private String epochHash; 70 | private String epochNumber; 71 | private String blockHash; 72 | private String transactionPosition; 73 | private String transactionHash; 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Log.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import conflux.web3j.types.Address; 8 | import org.web3j.utils.Numeric; 9 | 10 | public class Log { 11 | 12 | public static class Response extends CfxListResponse {} 13 | 14 | private Address address; 15 | private List topics; 16 | private String data; 17 | private String blockHash; 18 | private String epochNumber; 19 | private String transactionHash; 20 | private String transactionIndex; 21 | private String logIndex; 22 | private String transactionLogIndex; 23 | private String revertTo; 24 | 25 | public Address getAddress() { 26 | return address; 27 | } 28 | 29 | public void setAddress(Address address) { 30 | this.address = address; 31 | } 32 | 33 | public List getTopics() { 34 | return topics; 35 | } 36 | 37 | public void setTopics(List topics) { 38 | this.topics = topics; 39 | } 40 | 41 | public String getData() { 42 | return data; 43 | } 44 | 45 | public void setData(String data) { 46 | this.data = data; 47 | } 48 | 49 | public Optional getBlockHash() { 50 | if (this.blockHash == null || this.blockHash.isEmpty()) { 51 | return Optional.empty(); 52 | } else { 53 | return Optional.of(this.blockHash); 54 | } 55 | } 56 | 57 | public void setBlockHash(String blockHash) { 58 | this.blockHash = blockHash; 59 | } 60 | 61 | public Optional getEpochNumber() { 62 | if (this.epochNumber == null || this.epochNumber.isEmpty()) { 63 | return Optional.empty(); 64 | } else { 65 | return Optional.of(Numeric.decodeQuantity(this.epochNumber)); 66 | } 67 | } 68 | 69 | public void setEpochNumber(String epochNumber) { 70 | this.epochNumber = epochNumber; 71 | } 72 | 73 | public Optional getTransactionHash() { 74 | if (this.transactionHash == null || this.transactionHash.isEmpty()) { 75 | return Optional.empty(); 76 | } else { 77 | return Optional.of(this.transactionHash); 78 | } 79 | } 80 | 81 | public void setTransactionHash(String transactionHash) { 82 | this.transactionHash = transactionHash; 83 | } 84 | 85 | public Optional getTransactionIndex() { 86 | if (this.transactionIndex == null || this.transactionIndex.isEmpty()) { 87 | return Optional.empty(); 88 | } else { 89 | return Optional.of(Numeric.decodeQuantity(this.transactionIndex)); 90 | } 91 | } 92 | 93 | public void setTransactionIndex(String transactionIndex) { 94 | this.transactionIndex = transactionIndex; 95 | } 96 | 97 | public Optional getLogIndex() { 98 | if (this.logIndex == null || this.logIndex.isEmpty()) { 99 | return Optional.empty(); 100 | } else { 101 | return Optional.of(Numeric.decodeQuantity(this.logIndex)); 102 | } 103 | } 104 | 105 | public void setLogIndex(String logIndex) { 106 | this.logIndex = logIndex; 107 | } 108 | 109 | public Optional getTransactionLogIndex() { 110 | if (this.transactionLogIndex == null || this.transactionLogIndex.isEmpty()) { 111 | return Optional.empty(); 112 | } else { 113 | return Optional.of(Numeric.decodeQuantity(this.transactionLogIndex)); 114 | } 115 | } 116 | 117 | public void setTransactionLogIndex(String transactionLogIndex) { 118 | this.transactionLogIndex = transactionLogIndex; 119 | } 120 | 121 | public Optional getRevertTo() { 122 | if (this.revertTo == null || this.revertTo.isEmpty()) { 123 | return Optional.empty(); 124 | } else { 125 | return Optional.of(Numeric.decodeQuantity(this.revertTo)); 126 | } 127 | } 128 | 129 | public void setRevertTo(String revertTo) { 130 | this.revertTo = revertTo; 131 | } 132 | } 133 | 134 | 135 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/ParamsOfVote.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | 7 | public class ParamsOfVote { 8 | public static class Response extends CfxResponse {} 9 | 10 | private String baseFeeShareProp; 11 | private String interestRate; 12 | private String powBaseReward; 13 | private String storagePointProp; 14 | 15 | public BigInteger getBaseFeeShareProp() { 16 | return Numeric.decodeQuantity(baseFeeShareProp); 17 | } 18 | 19 | public void setBaseFeeShareProp(String baseFeeShareProp) { 20 | this.baseFeeShareProp = baseFeeShareProp; 21 | } 22 | 23 | public BigInteger getInterestRate() { 24 | return Numeric.decodeQuantity(interestRate); 25 | } 26 | 27 | public void setInterestRate(String interestRate) { 28 | this.interestRate = interestRate; 29 | } 30 | 31 | public BigInteger getPowBaseReward() { 32 | return Numeric.decodeQuantity(powBaseReward); 33 | } 34 | 35 | public void setPowBaseReward(String powBaseReward) { 36 | this.powBaseReward = powBaseReward; 37 | } 38 | 39 | public BigInteger getStoragePointProp() { 40 | return Numeric.decodeQuantity(storagePointProp); 41 | } 42 | 43 | public void setStoragePointProp(String storagePointProp) { 44 | this.storagePointProp = storagePointProp; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/PoSAccountReward.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | 7 | public class PoSAccountReward { 8 | public static class Response extends CfxResponse {} 9 | 10 | private String posAddress; 11 | private String powAddress; 12 | private String reward; 13 | 14 | public String getPosAddress() { 15 | return posAddress; 16 | } 17 | 18 | public void setPosAddress(String posAddress) { 19 | this.posAddress = posAddress; 20 | } 21 | 22 | public String getPowAddress() { 23 | return powAddress; 24 | } 25 | 26 | public void setPowAddress(String posAddress) { 27 | this.powAddress = powAddress; 28 | } 29 | 30 | public BigInteger getReward() { 31 | return Numeric.decodeQuantity(this.reward); 32 | } 33 | 34 | public void setReward(String reward) { 35 | this.reward = reward; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/PoSEconomics.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | 7 | public class PoSEconomics { 8 | public static class Response extends CfxResponse {} 9 | 10 | private String distributablePosInterest; 11 | private String lastDistributeBlock; 12 | private String totalPosStakingTokens; 13 | 14 | public BigInteger getDistributablePosInterest() { 15 | return Numeric.decodeQuantity(this.distributablePosInterest); 16 | } 17 | 18 | public void setDistributablePosInterest(String distributablePosInterest) { 19 | this.distributablePosInterest = distributablePosInterest; 20 | } 21 | 22 | public BigInteger getLastDistributeBlock() { 23 | return Numeric.decodeQuantity(this.lastDistributeBlock); 24 | } 25 | 26 | public void setLastDistributeBlock(String lastDistributeBlock) { 27 | this.distributablePosInterest = lastDistributeBlock; 28 | } 29 | 30 | public BigInteger getTotalPosStakingTokens() { 31 | return Numeric.decodeQuantity(this.totalPosStakingTokens); 32 | } 33 | 34 | public void setTotalPosStakingTokens(String totalPosStakingTokens) { 35 | this.distributablePosInterest = totalPosStakingTokens; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/PoSEpochRewards.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.util.List; 4 | 5 | public class PoSEpochRewards { 6 | public static class Response extends CfxResponse {} 7 | 8 | private String powEpochHash; 9 | private List accountRewards; 10 | 11 | public String getPowEpochHash() { 12 | return powEpochHash; 13 | } 14 | 15 | public void setPowEpochHash(String powEpochHash) { 16 | this.powEpochHash = powEpochHash; 17 | } 18 | 19 | public List getAccountRewards() { 20 | return accountRewards; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Receipt.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import conflux.web3j.types.Address; 8 | import org.web3j.utils.Numeric; 9 | 10 | public class Receipt { 11 | 12 | public static class Response extends CfxNullableResponse {} 13 | public static class ListResponse extends CfxNullableResponse>> {} 14 | 15 | private String transactionHash; 16 | private String index; 17 | private String blockHash; 18 | private String epochNumber; 19 | private Address from; 20 | private Address to; 21 | private String gasUsed; 22 | private Address contractCreated; 23 | private List logs; 24 | private String logsBloom; 25 | private String stateRoot; 26 | private String outcomeStatus; 27 | private String txExecErrorMsg; 28 | private boolean gasCoveredBySponsor; 29 | private boolean storageCoveredBySponsor; 30 | private String storageCollateralized; 31 | private List storageReleased; 32 | private String gasFee; 33 | private String type; 34 | private String burntGasFee; 35 | private String effectiveGasPrice; 36 | 37 | public BigInteger getBurntGasFee() { 38 | return Numeric.decodeQuantity(burntGasFee); 39 | } 40 | 41 | public void setBurntGasFee(String burntGasFee) { 42 | this.burntGasFee = burntGasFee; 43 | } 44 | 45 | public BigInteger getEffectiveGasPrice() { 46 | return Numeric.decodeQuantity(effectiveGasPrice); 47 | } 48 | 49 | public void setEffectiveGasPrice(String effectiveGasPrice) { 50 | this.effectiveGasPrice = effectiveGasPrice; 51 | } 52 | 53 | public int getType() { 54 | return Numeric.decodeQuantity(type).intValue(); 55 | } 56 | 57 | public void setType(String type) { 58 | this.type = type; 59 | } 60 | 61 | public String getTransactionHash() { 62 | return transactionHash; 63 | } 64 | 65 | public void setTransactionHash(String transactionHash) { 66 | this.transactionHash = transactionHash; 67 | } 68 | 69 | public BigInteger getIndex() { 70 | return Numeric.decodeQuantity(this.index); 71 | } 72 | 73 | public void setIndex(String index) { 74 | this.index = index; 75 | } 76 | 77 | public String getBlockHash() { 78 | return blockHash; 79 | } 80 | 81 | public void setBlockHash(String blockHash) { 82 | this.blockHash = blockHash; 83 | } 84 | 85 | public BigInteger getEpochNumber() { 86 | return Numeric.decodeQuantity(this.epochNumber); 87 | } 88 | 89 | public void setEpochNumber(String epochNumber) { 90 | this.epochNumber = epochNumber; 91 | } 92 | 93 | public Address getFrom() { 94 | return from; 95 | } 96 | 97 | public void setFrom(Address from) { 98 | this.from = from; 99 | } 100 | 101 | public Optional
getTo() { 102 | if (this.to == null) { 103 | return Optional.empty(); 104 | } else { 105 | return Optional.of(this.to); 106 | } 107 | } 108 | 109 | public void setTo(Address to) { 110 | this.to = to; 111 | } 112 | 113 | public BigInteger getGasUsed() { 114 | return Numeric.decodeQuantity(this.gasUsed); 115 | } 116 | 117 | public void setGasUsed(String gasUsed) { 118 | this.gasUsed = gasUsed; 119 | } 120 | 121 | public Optional
getContractCreated() { 122 | if (this.contractCreated == null) { 123 | return Optional.empty(); 124 | } else { 125 | return Optional.of(this.contractCreated); 126 | } 127 | } 128 | 129 | public void setContractCreated(Address contractCreated) { 130 | this.contractCreated = contractCreated; 131 | } 132 | 133 | public List getLogs() { 134 | return logs; 135 | } 136 | 137 | public void setLogs(List logs) { 138 | this.logs = logs; 139 | } 140 | 141 | public String getLogsBloom() { 142 | return logsBloom; 143 | } 144 | 145 | public void setLogsBloom(String logsBloom) { 146 | this.logsBloom = logsBloom; 147 | } 148 | 149 | public String getStateRoot() { 150 | return stateRoot; 151 | } 152 | 153 | public void setStateRoot(String stateRoot) { 154 | this.stateRoot = stateRoot; 155 | } 156 | 157 | public short getOutcomeStatus() { 158 | return Numeric.decodeQuantity(this.outcomeStatus).shortValueExact(); 159 | } 160 | 161 | public void setOutcomeStatus(String outcomeStatus) { 162 | this.outcomeStatus = outcomeStatus; 163 | } 164 | 165 | public String getTxExecErrorMsg() { 166 | return this.txExecErrorMsg; 167 | } 168 | 169 | public void setTxExecErrorMsg(String errorMsg) {this.txExecErrorMsg = errorMsg;} 170 | 171 | public boolean getGasCoveredBySponsor() { 172 | return gasCoveredBySponsor; 173 | } 174 | 175 | public void setGasCoveredBySponsor(boolean gasCovered) { 176 | this.gasCoveredBySponsor = gasCovered; 177 | } 178 | 179 | public boolean getStorageCoveredBySponsor() { 180 | return storageCoveredBySponsor; 181 | } 182 | 183 | public void setStorageCoveredBySponsor(boolean storageCovered) { 184 | this.storageCoveredBySponsor = storageCovered; 185 | } 186 | 187 | public BigInteger getStorageCollateralized() { 188 | return Numeric.decodeQuantity(storageCollateralized); 189 | } 190 | 191 | public void setStorageCollateralized(String collateralized) { 192 | this.storageCollateralized = collateralized; 193 | } 194 | 195 | public List getStorageReleased() { 196 | return this.storageReleased; 197 | } 198 | 199 | public void setStorageReleased(List change) { 200 | this.storageReleased = change; 201 | } 202 | 203 | public BigInteger getGasFee(){ 204 | return Numeric.decodeQuantity(gasFee); 205 | } 206 | 207 | public void setGasFee(String gasFee) { 208 | this.gasFee = gasFee; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/RevertLog.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class RevertLog { 4 | public static class Response extends CfxResponse {} 5 | 6 | private String revertTo; 7 | 8 | public String getRevertTo() { return revertTo; } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/RewardInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | 5 | import conflux.web3j.types.Address; 6 | import org.web3j.utils.Numeric; 7 | 8 | public class RewardInfo { 9 | 10 | public static class Response extends CfxListResponse {} 11 | 12 | private String blockHash; 13 | private Address author; 14 | private String totalReward; 15 | private String baseReward; 16 | private String txFee; 17 | 18 | public String getBlockHash() { 19 | return blockHash; 20 | } 21 | 22 | public void setBlockHash(String blockHash) { 23 | this.blockHash = blockHash; 24 | } 25 | 26 | public Address getAuthor() { 27 | return author; 28 | } 29 | 30 | public void setAuthor(Address author) { 31 | this.author = author; 32 | } 33 | 34 | public BigInteger getTotalReward() { 35 | return Numeric.decodeQuantity(this.totalReward); 36 | } 37 | 38 | public void setTotalReward(String totalReward) { 39 | this.totalReward = totalReward; 40 | } 41 | 42 | public BigInteger getBaseReward() { 43 | return Numeric.decodeQuantity(this.baseReward); 44 | } 45 | 46 | public void setBaseReward(String baseReward) { 47 | this.baseReward = baseReward; 48 | } 49 | 50 | public BigInteger getTxFee() { 51 | return Numeric.decodeQuantity(this.txFee); 52 | } 53 | 54 | public void setTxFee(String txFee) { 55 | this.txFee = txFee; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/SponsorInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | 5 | import conflux.web3j.types.Address; 6 | import org.web3j.utils.Numeric; 7 | 8 | public class SponsorInfo { 9 | 10 | public static class Response extends CfxResponse {} 11 | 12 | private Address sponsorForGas; 13 | private Address sponsorForCollateral; 14 | private String sponsorGasBound; 15 | private String sponsorBalanceForGas; 16 | private String sponsorBalanceForCollateral; 17 | 18 | public Address getSponsorForGas() { 19 | return sponsorForGas; 20 | } 21 | 22 | public void setSponsorForGas(Address sponsorForGas) { 23 | this.sponsorForGas = sponsorForGas; 24 | } 25 | 26 | public Address getSponsorForCollateral() { 27 | return sponsorForCollateral; 28 | } 29 | 30 | public void setSponsorForCollateral(Address sponsorForCollateral) { 31 | this.sponsorForCollateral = sponsorForCollateral; 32 | } 33 | 34 | public BigInteger getSponsorGasBound() { 35 | return Numeric.decodeQuantity(this.sponsorGasBound); 36 | } 37 | 38 | public void setSponsorGasBound(String sponsorGasBound) { 39 | this.sponsorGasBound = sponsorGasBound; 40 | } 41 | 42 | public BigInteger getSponsorBalanceForGas() { 43 | return Numeric.decodeQuantity(this.sponsorBalanceForGas); 44 | } 45 | 46 | public void setSponsorBalanceForGas(String sponsorBalanceForGas) { 47 | this.sponsorBalanceForGas = sponsorBalanceForGas; 48 | } 49 | 50 | public BigInteger getSponsorBalanceForCollateral() { 51 | return Numeric.decodeQuantity(this.sponsorBalanceForCollateral); 52 | } 53 | 54 | public void setSponsorBalanceForCollateral(String sponsorBalanceForCollateral) { 55 | this.sponsorBalanceForCollateral = sponsorBalanceForCollateral; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Status.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.utils.Numeric; 6 | 7 | public class Status { 8 | 9 | public static class Response extends CfxResponse {} 10 | 11 | private String bestHash; 12 | private String chainId; 13 | private String networkId; 14 | private String epochNumber; 15 | private String blockNumber; 16 | private String pendingTxNumber; 17 | private String latestCheckpoint; 18 | private String latestConfirmed; 19 | private String latestState; 20 | private String latestFinalized; 21 | private String ethereumSpaceChainId; 22 | 23 | public String getBestHash() { 24 | return bestHash; 25 | } 26 | 27 | public void setBestHash(String bestHash) { 28 | this.bestHash = bestHash; 29 | } 30 | 31 | public BigInteger getChainId() { 32 | return Numeric.decodeQuantity(this.chainId); 33 | } 34 | 35 | public void setChainId(String chainId) { 36 | this.chainId = chainId; 37 | } 38 | 39 | public BigInteger getEthereumSpaceChainId() { 40 | return Numeric.decodeQuantity(this.ethereumSpaceChainId); 41 | } 42 | 43 | public void setEthereumSpaceChainId(String chainId) { 44 | this.ethereumSpaceChainId = chainId; 45 | } 46 | 47 | public BigInteger getNetworkId() { 48 | return Numeric.decodeQuantity(this.networkId); 49 | } 50 | 51 | public void setNetworkId(String networkId) {this.networkId = networkId;} 52 | 53 | public BigInteger getEpochNumber() { 54 | return Numeric.decodeQuantity(this.epochNumber); 55 | } 56 | 57 | public void setEpochNumber(String epochNumber) { 58 | this.epochNumber = epochNumber; 59 | } 60 | 61 | public BigInteger getBlockNumber() { 62 | return Numeric.decodeQuantity(this.blockNumber); 63 | } 64 | 65 | public void setBlockNumber(String blockNumber) { 66 | this.blockNumber = blockNumber; 67 | } 68 | 69 | public BigInteger getPendingTxNumber() { 70 | return Numeric.decodeQuantity(this.pendingTxNumber); 71 | } 72 | 73 | public void setPendingTxNumber(String pendingTxNumber) { 74 | this.pendingTxNumber = pendingTxNumber; 75 | } 76 | 77 | public BigInteger getLatestCheckpoint() { 78 | return Numeric.decodeQuantity(this.latestCheckpoint); 79 | } 80 | 81 | public void setLatestCheckpoint(String latestCheckpoint) { 82 | this.latestCheckpoint = latestCheckpoint; 83 | } 84 | 85 | public BigInteger getLatestConfirmed() { 86 | return Numeric.decodeQuantity(this.latestConfirmed); 87 | } 88 | 89 | public void setLatestConfirmed(String latestConfirmed) { 90 | this.latestConfirmed = latestConfirmed; 91 | } 92 | 93 | public BigInteger getLatestState() { 94 | return Numeric.decodeQuantity(this.latestState); 95 | } 96 | 97 | public void setLatestState(String latestState) { 98 | this.latestState = latestState; 99 | } 100 | 101 | public BigInteger getLatestFinalized() { 102 | return Numeric.decodeQuantity(this.latestFinalized); 103 | } 104 | 105 | public void setLatestFinalized(String latestFinalized) { 106 | this.latestFinalized = latestFinalized; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/StorageChange.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import conflux.web3j.types.Address; 4 | import org.web3j.utils.Numeric; 5 | 6 | import java.math.BigInteger; 7 | 8 | public class StorageChange { 9 | // public static class Response extends CfxResponse {} 10 | 11 | private Address address; 12 | private String collaterals; 13 | 14 | public Address getAddress() { 15 | return address; 16 | } 17 | 18 | public void setAddress(Address address) { 19 | this.address = address; 20 | } 21 | 22 | public BigInteger getCollaterals () { 23 | return Numeric.decodeQuantity(collaterals); 24 | } 25 | 26 | public void setCollaterals(String collaterals) { 27 | this.collaterals = collaterals; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/StorageRoot.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class StorageRoot { 4 | 5 | public static class Response extends CfxNullableResponse {} 6 | 7 | private String delta; 8 | private String intermediate; 9 | private String snapshot; 10 | 11 | public String getDelta() { 12 | return delta; 13 | } 14 | 15 | public void setDelta(String delta) { 16 | this.delta = delta; 17 | } 18 | 19 | public String getIntermediate() { 20 | return intermediate; 21 | } 22 | 23 | public void setIntermediate(String intermediate) { 24 | this.intermediate = intermediate; 25 | } 26 | 27 | public String getSnapshot() { 28 | return snapshot; 29 | } 30 | 31 | public void setSnapshot(String snapshot) { 32 | this.snapshot = snapshot; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/StringListResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class StringListResponse { 4 | public static class Response extends CfxListResponse {} 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/StringNullableResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class StringNullableResponse extends CfxNullableResponse { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/StringResponse.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class StringResponse extends CfxResponse { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Subscribe.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class Subscribe extends CfxResponse { 4 | public String getSubscriptionId() { 5 | return getResult(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/SupplyInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | 7 | public class SupplyInfo { 8 | public static class Response extends CfxResponse {} 9 | 10 | private String totalIssued; 11 | private String totalStaking; 12 | private String totalCollateral; 13 | private String totalCirculating; 14 | 15 | public BigInteger getTotalIssued() { 16 | return Numeric.decodeQuantity(totalIssued); 17 | } 18 | 19 | public void setTotalIssued(String totalIssued) { 20 | this.totalIssued = totalIssued; 21 | } 22 | 23 | public BigInteger getTotalStaking() { 24 | return Numeric.decodeQuantity(totalStaking); 25 | } 26 | 27 | public void setTotalStaking(String totalStaking) { 28 | this.totalStaking = totalStaking; 29 | } 30 | 31 | public BigInteger getTotalCollateral () { 32 | return Numeric.decodeQuantity(totalCollateral); 33 | } 34 | 35 | public void setTotalCollateral(String totalCollateral) { 36 | this.totalCollateral = totalCollateral; 37 | } 38 | 39 | public BigInteger getTotalCirculating () { 40 | return Numeric.decodeQuantity(totalCirculating); 41 | } 42 | 43 | public void setTotalCirculating(String totalCirculating) { 44 | this.totalCirculating = totalCirculating; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | String formatStr = "{totalIssued = %s, totalStaking = %s, totalCollateral = %s, totalCirculating = %s}"; 50 | return String.format(formatStr, this.getTotalIssued(), this.getTotalStaking(), this.getTotalCollateral(), this.getTotalCirculating()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Transaction.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | import java.util.Optional; 5 | 6 | import conflux.web3j.types.AccessListEntry; 7 | import conflux.web3j.types.Address; 8 | import org.web3j.utils.Numeric; 9 | import java.util.List; 10 | 11 | public class Transaction { 12 | 13 | public static class Response extends CfxNullableResponse {} 14 | 15 | private String hash; 16 | private String nonce; 17 | private String blockHash; 18 | private String transactionIndex; 19 | private Address from; 20 | private Address to; 21 | private String value; 22 | private String gasPrice; 23 | private String gas; 24 | private String contractCreated; 25 | private String data; 26 | private String storageLimit; 27 | private String epochHeight; 28 | private String chainId; 29 | private String status; 30 | private String v; 31 | private String r; 32 | private String s; 33 | private String type; 34 | private String yParity; 35 | private String maxFeePerGas; 36 | private String maxPriorityFeePerGas; 37 | private List accessList; 38 | 39 | public BigInteger getMaxFeePerGas() { 40 | return Numeric.decodeQuantity(this.maxFeePerGas); 41 | } 42 | 43 | public void setMaxFeePerGas(String maxFeePerGas) { 44 | this.maxFeePerGas = maxFeePerGas; 45 | } 46 | 47 | public BigInteger getMaxPriorityFeePerGas() { 48 | return Numeric.decodeQuantity(this.maxPriorityFeePerGas); 49 | } 50 | 51 | public void setMaxPriorityFeePerGas(String maxPriorityFeePerGas) { 52 | this.maxPriorityFeePerGas = maxPriorityFeePerGas; 53 | } 54 | 55 | public BigInteger getYParity() { 56 | return Numeric.decodeQuantity(yParity); 57 | } 58 | 59 | public void setYParity(String yParity) { 60 | this.yParity = yParity; 61 | } 62 | 63 | public int getType() { 64 | return Numeric.decodeQuantity(type).intValue(); 65 | } 66 | 67 | public void setType(String type) { 68 | this.type = type; 69 | } 70 | 71 | public List getAccessList() { 72 | return accessList; 73 | } 74 | 75 | public void setAccessList(List accessList) { 76 | this.accessList = accessList; 77 | } 78 | 79 | public String getHash() { 80 | return hash; 81 | } 82 | 83 | public void setHash(String hash) { 84 | this.hash = hash; 85 | } 86 | 87 | public BigInteger getNonce() { 88 | return Numeric.decodeQuantity(this.nonce); 89 | } 90 | 91 | public void setNonce(String nonce) { 92 | this.nonce = nonce; 93 | } 94 | 95 | public Optional getBlockHash() { 96 | if (this.blockHash == null || this.blockHash.isEmpty()) { 97 | return Optional.empty(); 98 | } else { 99 | return Optional.of(this.blockHash); 100 | } 101 | } 102 | 103 | public void setBlockHash(String blockHash) { 104 | this.blockHash = blockHash; 105 | } 106 | 107 | public Optional getTransactionIndex() { 108 | if (this.transactionIndex == null || this.transactionIndex.isEmpty()) { 109 | return Optional.empty(); 110 | } else { 111 | return Optional.of(Numeric.decodeQuantity(this.transactionIndex)); 112 | } 113 | } 114 | 115 | public void setTransactionIndex(String transactionIndex) { 116 | this.transactionIndex = transactionIndex; 117 | } 118 | 119 | public Address getFrom() { 120 | return from; 121 | } 122 | 123 | public void setFrom(Address from) { 124 | this.from = from; 125 | } 126 | 127 | public Optional
getTo() { 128 | if (this.to == null) { 129 | return Optional.empty(); 130 | } else { 131 | return Optional.of(this.to); 132 | } 133 | } 134 | 135 | public void setTo(Address to) { 136 | this.to = to; 137 | } 138 | 139 | public BigInteger getValue() { 140 | return Numeric.decodeQuantity(this.value); 141 | } 142 | 143 | public void setValue(String value) { 144 | this.value = value; 145 | } 146 | 147 | public BigInteger getGasPrice() { 148 | return Numeric.decodeQuantity(this.gasPrice); 149 | } 150 | 151 | public void setGasPrice(String gasPrice) { 152 | this.gasPrice = gasPrice; 153 | } 154 | 155 | public BigInteger getGas() { 156 | return Numeric.decodeQuantity(this.gas); 157 | } 158 | 159 | public void setGas(String gas) { 160 | this.gas = gas; 161 | } 162 | 163 | public Optional getContractCreated() { 164 | if (this.contractCreated == null || this.contractCreated.isEmpty()) { 165 | return Optional.empty(); 166 | } else { 167 | return Optional.of(this.contractCreated); 168 | } 169 | } 170 | 171 | public void setContractCreated(String contractCreated) { 172 | this.contractCreated = contractCreated; 173 | } 174 | 175 | public String getData() { 176 | return data; 177 | } 178 | 179 | public void setData(String data) { 180 | this.data = data; 181 | } 182 | 183 | public BigInteger getStorageLimit() { 184 | return Numeric.decodeQuantity(this.storageLimit); 185 | } 186 | 187 | public void setStorageLimit(String storageLimit) { 188 | this.storageLimit = storageLimit; 189 | } 190 | 191 | public BigInteger getEpochHeight() { 192 | return Numeric.decodeQuantity(this.epochHeight); 193 | } 194 | 195 | public void setEpochHeight(String epochHeight) { 196 | this.epochHeight = epochHeight; 197 | } 198 | 199 | public BigInteger getChainId() { 200 | return Numeric.decodeQuantity(this.chainId); 201 | } 202 | 203 | public void setChainId(String chainId) { 204 | this.chainId = chainId; 205 | } 206 | 207 | public Optional getStatus() { 208 | if (this.status == null || this.status.isEmpty()) { 209 | return Optional.empty(); 210 | } else { 211 | return Optional.of(Numeric.decodeQuantity(this.status)); 212 | } 213 | } 214 | 215 | public void setStatus(String status) { 216 | this.status = status; 217 | } 218 | 219 | public BigInteger getV() { 220 | return Numeric.decodeQuantity(this.v); 221 | } 222 | 223 | public void setV(String v) { 224 | this.v = v; 225 | } 226 | 227 | public BigInteger getR() { 228 | return Numeric.decodeQuantity(this.r); 229 | } 230 | 231 | public void setR(String r) { 232 | this.r = r; 233 | } 234 | 235 | public BigInteger getS() { 236 | return Numeric.decodeQuantity(this.s); 237 | } 238 | 239 | public void setS(String s) { 240 | this.s = s; 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/Unsubscribe.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | public class Unsubscribe extends CfxResponse {} 4 | 5 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/UsedGasAndCollateral.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.utils.Numeric; 6 | 7 | public class UsedGasAndCollateral { 8 | 9 | public static class Response extends CfxResponse {} 10 | 11 | private String gasUsed; 12 | private String gasLimit; 13 | private String storageCollateralized; 14 | 15 | public BigInteger getGasUsed() { 16 | return Numeric.decodeQuantity(this.gasUsed); 17 | } 18 | 19 | public void setGasUsed(String gasUsed) { 20 | this.gasUsed = gasUsed; 21 | } 22 | 23 | public BigInteger getGasLimit() { 24 | return Numeric.decodeQuantity(this.gasLimit); 25 | } 26 | 27 | public void setGasLimit(String gasLimit) { 28 | this.gasLimit = gasLimit; 29 | } 30 | 31 | public BigInteger getStorageCollateralized() { 32 | return Numeric.decodeQuantity(this.storageCollateralized); 33 | } 34 | 35 | public void setStorageCollateralized(String storageCollateralized) { 36 | this.storageCollateralized = storageCollateralized; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return String.format("{gasUsed = %s, storageCollateralized = %s}", this.getGasUsed(), this.getStorageCollateralized()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/VoteStakeInfo.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response; 2 | 3 | import org.web3j.utils.Numeric; 4 | 5 | import java.math.BigInteger; 6 | 7 | public class VoteStakeInfo { 8 | public static class ListResponse extends CfxListResponse {} 9 | private String amount; 10 | private String unlockBlockNumber; 11 | 12 | public BigInteger getAmount() {return Numeric.decodeQuantity(amount);} 13 | 14 | public void setAmount(String amount) {this.amount = amount;} 15 | 16 | public BigInteger getUnlockBlockNumber() {return Numeric.decodeQuantity(unlockBlockNumber);} 17 | 18 | public void setUnlockBlockNumber(String blockNumber) {this.unlockBlockNumber = blockNumber;} 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/events/Epoch.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response.events; 2 | 3 | import java.util.List; 4 | import java.math.BigInteger; 5 | import org.web3j.utils.Numeric; 6 | 7 | public class Epoch { 8 | private String epochNumber; 9 | private List epochHashesOrdered; 10 | 11 | public BigInteger getEpochNumber() { return Numeric.decodeQuantity(epochNumber); } 12 | 13 | public List getEpochHashesOrdered() {return epochHashesOrdered;} 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/events/EpochNotification.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response.events; 2 | 3 | import org.web3j.protocol.websocket.events.Notification; 4 | 5 | public class EpochNotification extends Notification {} 6 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/events/LogNotification.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response.events; 2 | 3 | import conflux.web3j.response.Log; 4 | import org.web3j.protocol.websocket.events.Notification; 5 | 6 | public class LogNotification extends Notification { } 7 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/events/NewHead.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response.events; 2 | 3 | import java.util.List; 4 | import java.math.BigInteger; 5 | import java.util.Optional; 6 | 7 | import conflux.web3j.types.Address; 8 | import org.web3j.utils.Numeric; 9 | 10 | public class NewHead { 11 | private boolean adaptive; 12 | private String blame; 13 | private String deferredLogsBloomHash; 14 | private String deferredReceiptsRoot; 15 | private String deferredStateRoot; 16 | private String difficulty; 17 | private String epochNumber; 18 | private String gasLimit; 19 | private String hash; 20 | private String height; 21 | private Address miner; 22 | private String nonce; 23 | private String parentHash; 24 | private String powQuality; 25 | private List refereeHashes; 26 | private String timestamp; 27 | private String transactionsRoot; 28 | 29 | public boolean getAdaptive() { 30 | return adaptive; 31 | } 32 | 33 | public int getBlame() { 34 | return Numeric.decodeQuantity(blame).intValue(); 35 | } 36 | 37 | public String getDeferredLogsBloomHash() { 38 | return deferredLogsBloomHash; 39 | } 40 | 41 | public String getDeferredReceiptsRoot() { 42 | return deferredReceiptsRoot; 43 | } 44 | 45 | public String getDeferredStateRoot() { 46 | return deferredStateRoot; 47 | } 48 | 49 | public BigInteger getDifficulty() { return Numeric.decodeQuantity(difficulty); } 50 | 51 | public Optional getEpochNumber() { 52 | if (this.epochNumber == null || this.epochNumber.isEmpty()) { 53 | return Optional.empty(); 54 | } else { 55 | return Optional.of(Numeric.decodeQuantity(this.epochNumber)); 56 | } 57 | } 58 | 59 | public BigInteger getGasLimit() { 60 | return Numeric.decodeQuantity(gasLimit); 61 | } 62 | 63 | public BigInteger getHeight() { 64 | return Numeric.decodeQuantity(height); 65 | } 66 | 67 | public String getHash() { 68 | return hash; 69 | } 70 | 71 | public Address getMiner() { 72 | return miner; 73 | } 74 | 75 | public BigInteger getNonce() { 76 | return Numeric.decodeQuantity(nonce); 77 | } 78 | 79 | public String getParentHash() { 80 | return parentHash; 81 | } 82 | 83 | public BigInteger getPowQuality() { 84 | return Numeric.decodeQuantity(powQuality); 85 | } 86 | 87 | public List getRefereeHashes() { 88 | return refereeHashes; 89 | } 90 | 91 | public BigInteger getTimestamp() { return Numeric.decodeQuantity(timestamp); } 92 | 93 | public String getTransactionsRoot() { 94 | return transactionsRoot; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/response/events/NewHeadsNotification.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.response.events; 2 | 3 | import org.web3j.protocol.websocket.events.Notification; 4 | 5 | public class NewHeadsNotification extends Notification {} 6 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/AccessListEntry.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | import java.util.List; 3 | 4 | public class AccessListEntry { 5 | 6 | private Address address; 7 | private List storageKeys; 8 | 9 | public List getStorageKeys() { 10 | return storageKeys; 11 | } 12 | 13 | public void setStorageKeys(List storageKeys) { 14 | this.storageKeys = storageKeys; 15 | } 16 | 17 | public Address getAddress() { 18 | return address; 19 | } 20 | 21 | public void setAddress(CfxAddress address) { 22 | this.address = address; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/AddressException.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | public class AddressException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 2338294090416527939L; 6 | 7 | public static final String INVALID_PREFIX = "HEX prefix 0x missed"; 8 | public static final String INVALID_LENGTH = "wrong length"; 9 | public static final String INVALID_TYPE = "wrong type"; 10 | public static final String INVALID_HEX = "wrong HEX format"; 11 | 12 | private String reason; 13 | 14 | public AddressException() { 15 | } 16 | 17 | public AddressException(String reason) { 18 | super(String.format("invalid address (%s)", reason)); 19 | 20 | this.reason = reason; 21 | } 22 | 23 | public String getReason() { 24 | return reason; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/AddressType.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import java.util.HashMap; 4 | import java.util.Optional; 5 | 6 | import org.web3j.utils.Numeric; 7 | 8 | public enum AddressType { 9 | Null("null", "null address type required"), 10 | Builtin("builtin", "builtin address type required"), 11 | User("user", "user address type required"), 12 | Contract("contract", "contract address type required"), 13 | Unknown("unknown", "unknown address type required"); 14 | 15 | private static final HashMap TYPE_MAP = new HashMap<>(); 16 | static { 17 | TYPE_MAP.put("builtin", '0'); 18 | TYPE_MAP.put("user", '1'); 19 | TYPE_MAP.put("contract", '8'); 20 | } 21 | 22 | private String value; 23 | private String typeMismatchException; 24 | 25 | private AddressType(String value, String ae) { 26 | this.value = value; 27 | this.typeMismatchException = ae; 28 | } 29 | 30 | public String getValue() { 31 | return this.value; 32 | } 33 | 34 | public AddressException getTypeMismatchException() { 35 | return new AddressException(typeMismatchException); 36 | } 37 | 38 | public String normalize(String hexAddress) { 39 | return String.format("0x%s%s", TYPE_MAP.get(this.value), Numeric.cleanHexPrefix(hexAddress).substring(1)); 40 | } 41 | 42 | public static Optional parse(char ch) { 43 | switch (ch) { 44 | case '0': 45 | return Optional.of(Builtin); 46 | case '1': 47 | return Optional.of(User); 48 | case '8': 49 | return Optional.of(Contract); 50 | default: 51 | return Optional.of(Unknown); 52 | } 53 | // return Optional.empty(); 54 | } 55 | 56 | private static final int HEX_LENGTH_WITH_PREFIX = 42; 57 | 58 | public static void validateHexAddress(String hexValue) throws AddressException { 59 | validateHexAddress(hexValue, null); 60 | } 61 | 62 | public static void validateHexAddress(String hexValue, AddressType expectedType) throws AddressException { 63 | if (!Numeric.containsHexPrefix(hexValue)) { 64 | throw new AddressException(AddressException.INVALID_PREFIX); 65 | } 66 | 67 | if (hexValue.length() != HEX_LENGTH_WITH_PREFIX) { 68 | throw new AddressException(AddressException.INVALID_LENGTH); 69 | } 70 | 71 | Optional type = AddressType.parse(hexValue.charAt(2)); 72 | if (!type.isPresent()) { 73 | throw new AddressException(AddressException.INVALID_TYPE); 74 | } 75 | 76 | if (expectedType != null && !type.get().equals(expectedType)) { 77 | throw expectedType.getTypeMismatchException(); 78 | } 79 | 80 | for (int i = 2; i < HEX_LENGTH_WITH_PREFIX; i++) { 81 | char ch = hexValue.charAt(i); 82 | if (ch < '0' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a') || ch > 'z') { 83 | throw new AddressException(AddressException.INVALID_HEX); 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/CfxAddress.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | /* 4 | * CfxAddress is an alias to class Address 5 | * To easily distinguish from org.web3j.abi.datatypes.Address; 6 | * */ 7 | public class CfxAddress extends Address { 8 | public CfxAddress(String address) throws AddressException { 9 | super(address); 10 | } 11 | 12 | public CfxAddress(String hexAddress, int netId) throws AddressException { 13 | super(hexAddress, netId); 14 | } 15 | 16 | public CfxAddress(byte[] addressBuffer, int netId) throws AddressException { 17 | super(addressBuffer, netId); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/SendTransactionError.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import org.web3j.protocol.core.Response.Error; 4 | 5 | public enum SendTransactionError { 6 | 7 | Rlp(null, "rlp", "Rlp", "RLP"), 8 | TxAlreadyExists("tx already exist"), 9 | TxPoolFull(null, "txpool is full", "Transaction Pool is full"), 10 | 11 | InvalidEpochHeight("transaction epoch height"), 12 | InvalidChainId("transaction chain_id"), 13 | InvalidGasLimitExceedsMax("transaction gas", "exceeds the maximum value"), 14 | InvalidGasLimitLessThanIntrinsic("transaction gas", "less than intrinsic gas"), 15 | InvalidGasPriceTooSmall("transaction gas price", "less than the minimum value"), 16 | InvalidSignature(null, "invalid signature", "Invalid EC signature", "Cannot recover public key"), 17 | InvalidNonceTooStale("Transaction", "is discarded due to a too stale nonce"), 18 | InvalidNonceTooFuture("Transaction", "is discarded due to in too distant future"), 19 | InvalidNonceAlreadyUsed(null, "Tx with same nonce already inserted"), 20 | 21 | Internal(null, "Failed to read account_cache from storage"), 22 | 23 | Unknown(null, "unknown"); 24 | 25 | private String prefix; 26 | private String[] texts; 27 | 28 | private SendTransactionError(String prefix, String... texts) { 29 | this.prefix = prefix; 30 | this.texts = texts; 31 | } 32 | 33 | private boolean matches(String message) { 34 | if (message == null) { 35 | return false; 36 | } 37 | if (this.prefix != null && !message.startsWith(this.prefix)) { 38 | return false; 39 | } 40 | 41 | if (this.texts == null || this.texts.length == 0) { 42 | return true; 43 | } 44 | 45 | for (String text : this.texts) { 46 | if (message.contains(text)) { 47 | return true; 48 | } 49 | } 50 | 51 | return false; 52 | } 53 | 54 | public static SendTransactionError parse(Error rpcError) { 55 | if (rpcError == null) { 56 | return null; 57 | } 58 | 59 | String message = rpcError.getMessage(); 60 | if (message == null || message.isEmpty()) { 61 | return null; 62 | } 63 | 64 | String data = rpcError.getData(); 65 | if (data != null) { 66 | data = data.replace("\"", "").replace("\\", ""); 67 | 68 | for (SendTransactionError error : SendTransactionError.values()) { 69 | if (error.matches(data)) { 70 | return error; 71 | } 72 | } 73 | } 74 | 75 | return Unknown; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/SendTransactionResult.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import org.web3j.protocol.core.Response.Error; 4 | 5 | public class SendTransactionResult { 6 | 7 | private String txHash; 8 | private SendTransactionError errorType; 9 | private Error rawError; 10 | 11 | public SendTransactionResult(String txHash) { 12 | this.txHash = txHash; 13 | } 14 | 15 | public SendTransactionResult(Error error) { 16 | this.errorType = SendTransactionError.parse(error); 17 | this.rawError = error; 18 | } 19 | 20 | public String getTxHash() { 21 | return txHash; 22 | } 23 | 24 | public SendTransactionError getErrorType() { 25 | return errorType; 26 | } 27 | 28 | public Error getRawError() { 29 | return rawError; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | if (this.txHash != null) { 35 | return this.txHash; 36 | } 37 | 38 | return String.format("RPC error: type = %s, code = %s, message = %s, data = %s", 39 | this.errorType, 40 | this.rawError.getCode(), 41 | this.rawError.getMessage(), 42 | this.rawError.getData()); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/types/TransactionBuilder.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.BigInteger; 5 | import java.util.List; 6 | import java.util.Objects; 7 | 8 | import conflux.web3j.request.Epoch; 9 | import conflux.web3j.response.Block; 10 | import org.web3j.utils.Strings; 11 | 12 | import conflux.web3j.Cfx; 13 | import conflux.web3j.request.Call; 14 | import conflux.web3j.response.UsedGasAndCollateral; 15 | 16 | public class TransactionBuilder { 17 | 18 | public static final BigDecimal DEFAULT_GAS_OVERFLOW_RATIO = BigDecimal.valueOf(1.3); 19 | public static final BigDecimal DEFAULT_COLLATERAL_OVERFLOW_RATIO = BigDecimal.valueOf(1.3); 20 | 21 | private Address from; 22 | private BigDecimal gasOverflowRatio; 23 | private BigDecimal collateralOverflowRatio; 24 | private RawTransaction tx = new RawTransaction(); 25 | 26 | public TransactionBuilder(Address from) { 27 | this(from, DEFAULT_GAS_OVERFLOW_RATIO, DEFAULT_COLLATERAL_OVERFLOW_RATIO); 28 | } 29 | 30 | public TransactionBuilder(Address from, BigDecimal gasOverflowRatio, BigDecimal collateralOverflowRatio) { 31 | this.from = from; 32 | this.gasOverflowRatio = gasOverflowRatio; 33 | this.collateralOverflowRatio = collateralOverflowRatio; 34 | } 35 | 36 | public TransactionBuilder withFrom(Address from) { 37 | this.from = from; 38 | return this; 39 | } 40 | 41 | public TransactionBuilder withNonce(BigInteger nonce) { 42 | this.tx.setNonce(nonce); 43 | return this; 44 | } 45 | 46 | public TransactionBuilder withType(BigInteger val) { 47 | this.tx.setType(val); 48 | return this; 49 | } 50 | 51 | public TransactionBuilder withAccessList(List val) { 52 | this.tx.setAccessList(val); 53 | return this; 54 | } 55 | 56 | public TransactionBuilder withMaxPriorityFeePerGas(BigInteger val) { 57 | this.tx.setType(RawTransaction.TYPE_1559); 58 | this.tx.setMaxPriorityFeePerGas(val); 59 | return this; 60 | } 61 | 62 | public TransactionBuilder withMaxFeePerGas(BigInteger val) { 63 | this.tx.setType(RawTransaction.TYPE_1559); 64 | this.tx.setMaxFeePerGas(val); 65 | return this; 66 | } 67 | 68 | public TransactionBuilder withGasPrice(BigInteger price) { 69 | this.tx.setGasPrice(price); 70 | return this; 71 | } 72 | 73 | public TransactionBuilder withGasLimit(BigInteger gasLimit) { 74 | this.tx.setGas(gasLimit); 75 | return this; 76 | } 77 | 78 | public TransactionBuilder withGasLimit(long gasLimit) { 79 | this.tx.setGas(BigInteger.valueOf(gasLimit)); 80 | return this; 81 | } 82 | 83 | public TransactionBuilder withTo(Address to) { 84 | this.tx.setTo(to); 85 | return this; 86 | } 87 | 88 | public TransactionBuilder withValue(BigInteger value) { 89 | this.tx.setValue(value); 90 | return this; 91 | } 92 | 93 | public TransactionBuilder withStorageLimit(BigInteger storageLimit) { 94 | this.tx.setStorageLimit(storageLimit); 95 | return this; 96 | } 97 | 98 | public TransactionBuilder withStorageLimit(long storageLimit) { 99 | this.tx.setStorageLimit(BigInteger.valueOf(storageLimit)); 100 | return this; 101 | } 102 | 103 | public TransactionBuilder withEpochHeight(BigInteger epoch) { 104 | this.tx.setEpochHeight(epoch); 105 | return this; 106 | } 107 | 108 | public TransactionBuilder withEpochHeight(long epoch) { 109 | this.tx.setEpochHeight(BigInteger.valueOf(epoch)); 110 | return this; 111 | } 112 | 113 | public TransactionBuilder withChainId(BigInteger chainId) { 114 | this.tx.setChainId(chainId); 115 | return this; 116 | } 117 | 118 | public TransactionBuilder withChainId(long chainId) { 119 | this.tx.setChainId(BigInteger.valueOf(chainId)); 120 | return this; 121 | } 122 | 123 | public TransactionBuilder withData(String data) { 124 | this.tx.setData(data); 125 | return this; 126 | } 127 | 128 | public RawTransaction build(Cfx cfx) { 129 | this.estimateLimit(cfx); 130 | 131 | if (this.tx.getNonce() == null) { 132 | this.tx.setNonce(cfx.getNonce(this.from).sendAndGet()); 133 | } 134 | 135 | if (Objects.equals(this.tx.getType(), RawTransaction.TYPE_1559)) { 136 | if (this.tx.getMaxPriorityFeePerGas() == null) { 137 | BigInteger maxPriorityFeePerGas = cfx.getMaxPriorityFeePerGas().sendAndGet(); 138 | this.tx.setMaxPriorityFeePerGas(maxPriorityFeePerGas); 139 | } 140 | if (this.tx.getMaxFeePerGas() == null) { 141 | Block b = cfx.getBlockByEpoch(Epoch.latestState()).sendAndGet().get(); 142 | 143 | BigInteger maxFeePerGas = b.getBaseFeePerGas().multiply(new BigInteger("2")).add(this.tx.getMaxPriorityFeePerGas()); 144 | this.tx.setMaxFeePerGas(maxFeePerGas); 145 | } 146 | } else { 147 | if (this.tx.getGasPrice() == null) { 148 | BigInteger gasPrice = cfx.getGasPrice().sendAndGet(); 149 | this.tx.setGasPrice(gasPrice); 150 | } 151 | } 152 | 153 | // if (this.tx.getTo() == null) { 154 | // this.tx.setTo(null); 155 | // } 156 | 157 | if (this.tx.getValue() == null) { 158 | this.tx.setValue(BigInteger.ZERO); 159 | } 160 | 161 | if (this.tx.getEpochHeight() == null) { 162 | this.tx.setEpochHeight(cfx.getEpochNumber().sendAndGet()); 163 | } 164 | 165 | if (this.tx.getChainId() == null) { 166 | this.tx.setChainId(cfx.getChainId()); 167 | } 168 | 169 | return this.tx; 170 | } 171 | 172 | private void estimateLimit(Cfx cfx) { 173 | if (this.tx.getGas() != null && this.tx.getStorageLimit() != null) { 174 | return; 175 | } 176 | 177 | Call call = new Call(); 178 | call.setFrom(this.from); 179 | 180 | Address to = this.tx.getTo(); 181 | if (to != null) { 182 | call.setTo(to); 183 | } 184 | 185 | BigInteger value = this.tx.getValue(); 186 | if (value != null) { 187 | call.setValue(value); 188 | } 189 | 190 | String data = this.tx.getData(); 191 | if (!Strings.isEmpty(data)) { 192 | call.setData(data); 193 | } 194 | 195 | UsedGasAndCollateral estimation = cfx.estimateGasAndCollateral(call).sendAndGet(); 196 | 197 | if (this.tx.getGas() == null) { 198 | // BigDecimal gasLimit = new BigDecimal(estimation.getGasUsed()).multiply(this.gasOverflowRatio); 199 | this.tx.setGas(estimation.getGasUsed()); 200 | } 201 | 202 | if (this.tx.getStorageLimit() == null) { 203 | BigDecimal storageLimit = new BigDecimal(estimation.getStorageCollateralized()).multiply(this.collateralOverflowRatio); 204 | this.tx.setStorageLimit(storageLimit.toBigInteger()); 205 | } 206 | } 207 | 208 | } 209 | -------------------------------------------------------------------------------- /src/main/java/conflux/web3j/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.utils; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | 6 | public class Utils { 7 | private static final ObjectMapper objectMapper = new ObjectMapper(); 8 | 9 | public static ObjectMapper getObjectMapper() { 10 | return objectMapper; 11 | } 12 | 13 | public static String jsonStringify(Object data) { 14 | try { 15 | return objectMapper.writeValueAsString(data); 16 | } catch (JsonProcessingException e) { 17 | e.printStackTrace(); 18 | return "{\"className\":" + data.toString() + "}"; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/crypto/ECRecoverTest.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.web3j.crypto.*; 5 | import org.web3j.crypto.Sign; 6 | import org.web3j.utils.Numeric; 7 | 8 | import java.io.IOException; 9 | import java.util.Arrays; 10 | 11 | import static org.junit.jupiter.api.Assertions.assertEquals; 12 | 13 | public class ECRecoverTest { 14 | private String getAddress() { 15 | return Numeric.prependHexPrefix(Keys.getAddress(getPubKey())); 16 | } 17 | 18 | private String getPubKey() { 19 | return SampleKeys.KEY_PAIR.getPublicKey().toString(); 20 | } 21 | 22 | 23 | @Test 24 | public void testSignAndRecoverMessage() { 25 | String message = "v0G9u7huK4mJb2K1"; 26 | 27 | byte[] msgHash = conflux.web3j.crypto.Sign.getConfluxMessageHash(message.getBytes()); 28 | 29 | Sign.SignatureData sign = conflux.web3j.crypto.Sign.signPrefixedMessage(message.getBytes(), SampleKeys.KEY_PAIR); 30 | 31 | String recoverAddress = conflux.web3j.crypto.Sign.recoverSignature(sign, msgHash, getAddress()); 32 | assertEquals(recoverAddress, getAddress()); 33 | } 34 | 35 | @Test 36 | public void testRecoverTyped() throws IOException { 37 | StructuredDataTests t = new StructuredDataTests(); 38 | String msg = t.getResource( 39 | "build/resources/test/" 40 | + "structured_data_json_files/ValidStructuredData.json"); 41 | StructuredDataEncoder dataEncoder = new StructuredDataEncoder(msg); 42 | 43 | //signature comes from `fluent` 44 | String signature = 45 | "0x371ef48d63082d3875fee13b392c5b6a7449aa638921cb9f3d419f5b6a817ba754d085965fb3a041c3b178d3ae3798ea322ae74cb687dd699b5f6045c7fe47a91c"; 46 | 47 | byte[] signatureBytes = Numeric.hexStringToByteArray(signature); 48 | byte v = signatureBytes[64]; 49 | if (v < 27) { 50 | v += 27; 51 | } 52 | 53 | Sign.SignatureData sd = 54 | new Sign.SignatureData( 55 | v, 56 | (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32), 57 | (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64)); 58 | 59 | String recoverAddress = conflux.web3j.crypto.Sign.recoverSignature(sd, dataEncoder.hashStructuredData(), getAddress()); 60 | assertEquals(recoverAddress, getAddress()); 61 | } 62 | 63 | @Test 64 | public void testSignAndRecoverTyped() throws IOException { 65 | StructuredDataTests t = new StructuredDataTests(); 66 | String msg = t.getResource( 67 | "build/resources/test/" 68 | + "structured_data_json_files/ValidStructuredData.json"); 69 | StructuredDataEncoder dataEncoder = new StructuredDataEncoder(msg); 70 | Sign.SignatureData sign = Sign.signMessage(dataEncoder.hashStructuredData(), SampleKeys.KEY_PAIR, false); 71 | 72 | String recoverAddress = conflux.web3j.crypto.Sign.recoverSignature(sign, dataEncoder.hashStructuredData(), getAddress()); 73 | assertEquals(recoverAddress, getAddress()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/crypto/SampleKeys.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | 3 | import java.math.BigInteger; 4 | 5 | import org.web3j.crypto.Credentials; 6 | import org.web3j.crypto.ECKeyPair; 7 | import org.web3j.utils.Numeric; 8 | 9 | /** Keys generated for unit testing purposes. */ 10 | public class SampleKeys { 11 | 12 | public static final String PRIVATE_KEY_STRING = 13 | "a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6"; 14 | static final String PUBLIC_KEY_STRING = 15 | "0x506bc1dc099358e5137292f4efdd57e400f29ba5132aa5d12b18dac1c1f6aab" 16 | + "a645c0b7b58158babbfa6c6cd5a48aa7340a8749176b120e8516216787a13dc76"; 17 | public static final String ADDRESS = "0xef678007d18427e6022059dbc264f27507cd1ffc"; 18 | public static final String ADDRESS_NO_PREFIX = Numeric.cleanHexPrefix(ADDRESS); 19 | 20 | public static final String PASSWORD = "Insecure Pa55w0rd"; 21 | public static final String MNEMONIC = 22 | "scatter major grant return flee easy female jungle" 23 | + " vivid movie bicycle absent weather inspire carry"; 24 | 25 | static final BigInteger PRIVATE_KEY = Numeric.toBigInt(PRIVATE_KEY_STRING); 26 | static final BigInteger PUBLIC_KEY = Numeric.toBigInt(PUBLIC_KEY_STRING); 27 | 28 | static final ECKeyPair KEY_PAIR = new ECKeyPair(PRIVATE_KEY, PUBLIC_KEY); 29 | 30 | public static final Credentials CREDENTIALS = Credentials.create(KEY_PAIR); 31 | 32 | // https://github.com/ethereum/EIPs/issues/155 33 | public static final Credentials CREDENTIALS_ETH_EXAMPLE = 34 | Credentials.create( 35 | "0x4646464646464646464646464646464646464646464646464646464646464646"); 36 | 37 | private SampleKeys() {} 38 | } -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/crypto/SignDataTests.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.crypto; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.web3j.utils.Numeric; 5 | 6 | import java.io.IOException; 7 | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; 9 | 10 | public class SignDataTests { 11 | 12 | //cfx_signTypedData_v4 13 | @Test 14 | public void testSignValidStructure() throws IOException { 15 | StructuredDataTests t = new StructuredDataTests(); 16 | 17 | String msg = t.getResource( 18 | "build/resources/test/" 19 | + "structured_data_json_files/ValidStructuredData.json"); 20 | StructuredDataEncoder dataEncoder = new StructuredDataEncoder(msg); 21 | org.web3j.crypto.Sign.SignatureData sign = org.web3j.crypto.Sign.signMessage(dataEncoder.hashStructuredData(), SampleKeys.KEY_PAIR, false); 22 | assertEquals( 23 | "0x371ef48d63082d3875fee13b392c5b6a7449aa638921cb9f3d419f5b6a817ba754d085965fb3a041c3b178d3ae3798ea322ae74cb687dd699b5f6045c7fe47a91c", 24 | Numeric.toHexString(sign.getR()) + Numeric.toHexStringNoPrefix(sign.getS()) + Numeric.toHexStringNoPrefix(sign.getV())); 25 | } 26 | 27 | //personal_sign 28 | @Test 29 | public void testSignAnyMessage() throws IOException { 30 | String message = "v0G9u7huK4mJb2K1"; 31 | org.web3j.crypto.Sign.SignatureData sign = Sign.signPrefixedMessage(message.getBytes(), SampleKeys.KEY_PAIR); 32 | assertEquals( 33 | "0xbb0ee8492623f2ef6ed461ea638f8b5060b191a1c8830c93d84245f3fb27e20a755e24ff60fe76482dd4377a0aef036937ef88537b2d0fdd834a54e76ecafadc1c", 34 | Numeric.toHexString(sign.getR()) + Numeric.toHexStringNoPrefix(sign.getS()) + Numeric.toHexStringNoPrefix(sign.getV())); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/types/AddressTests.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.DisplayName; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class AddressTests { 10 | @Test 11 | @DisplayName("Conflux Address Encode") 12 | void cfxAddressEncoderTest() throws Exception { 13 | assertEquals("cfx:aajg4wt2mbmbb44sp6szd783ry0jtad5bea80xdy7p", Address.encode("106d49f8505410eb4e671d51f7d96d2c87807b09", 1029), ""); 14 | assertEquals("CFX:TYPE.USER:AAJG4WT2MBMBB44SP6SZD783RY0JTAD5BEA80XDY7P", Address.encode("106d49f8505410eb4e671d51f7d96d2c87807b09", 1029, true), ""); 15 | assertEquals("cfx:acag4wt2mbmbb44sp6szd783ry0jtad5bex25t8vc9", Address.encode("806d49f8505410eb4e671d51f7d96d2c87807b09", 1029), ""); 16 | assertEquals("CFX:TYPE.CONTRACT:ACAG4WT2MBMBB44SP6SZD783RY0JTAD5BEX25T8VC9", Address.encode("806d49f8505410eb4e671d51f7d96d2c87807b09", 1029, true), ""); 17 | assertEquals("cfx:aaag4wt2mbmbb44sp6szd783ry0jtad5beaar3k429", Address.encode("006d49f8505410eb4e671d51f7d96d2c87807b09", 1029), ""); 18 | assertEquals("CFX:TYPE.BUILTIN:AAAG4WT2MBMBB44SP6SZD783RY0JTAD5BEAAR3K429", Address.encode("006d49f8505410eb4e671d51f7d96d2c87807b09", 1029, true), ""); 19 | 20 | assertEquals("cfx:aajg4wt2mbmbb44sp6szd783ry0jtad5bea80xdy7p", Address.encode("106d49f8505410eb4e671d51f7d96d2c87807b09", 1029, false), ""); 21 | assertEquals("cfxtest:acag4wt2mbmbb44sp6szd783ry0jtad5be3xj925gz", Address.encode("806d49f8505410eb4e671d51f7d96d2c87807b09", 1, false), ""); 22 | assertEquals("net10086:aaag4wt2mbmbb44sp6szd783ry0jtad5benr1ap5gp", Address.encode("006d49f8505410eb4e671d51f7d96d2c87807b09", 10086, false), ""); 23 | 24 | assertEquals("cfx:acc7uawf5ubtnmezvhu9dhc6sghea0403y2dgpyfjp", Address.encode("0x85d80245dc02f5a89589e1f19c5c718e405b56cd", 1029, false), ""); 25 | assertEquals("cfxtest:acc7uawf5ubtnmezvhu9dhc6sghea0403ywjz6wtpg", Address.encode("0x85d80245dc02f5a89589e1f19c5c718e405b56cd", 1, false), ""); 26 | assertEquals("CFXTEST:TYPE.CONTRACT:ACC7UAWF5UBTNMEZVHU9DHC6SGHEA0403YWJZ6WTPG", Address.encode("0x85d80245dc02f5a89589e1f19c5c718e405b56cd", 1, true), ""); 27 | 28 | assertEquals("cfx:aarc9abycue0hhzgyrr53m6cxedgccrmmyybjgh4xg", Address.encode("0x1a2f80341409639ea6a35bbcab8299066109aa55", 1029, false), ""); 29 | assertEquals("cfxtest:aarc9abycue0hhzgyrr53m6cxedgccrmmy8m50bu1p", Address.encode("0x1a2f80341409639ea6a35bbcab8299066109aa55", 1, false), ""); 30 | assertEquals("CFXTEST:TYPE.USER:AARC9ABYCUE0HHZGYRR53M6CXEDGCCRMMY8M50BU1P", Address.encode("0x1a2f80341409639ea6a35bbcab8299066109aa55", 1, true), ""); 31 | 32 | assertEquals("cfx:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaajrwuc9jnb", Address.encode("0x0888000000000000000000000000000000000002", 1029, false), ""); 33 | assertEquals("cfxtest:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaajh3dw3ctn", Address.encode("0x0888000000000000000000000000000000000002", 1, false), ""); 34 | assertEquals("CFXTEST:TYPE.BUILTIN:AAEJUAAAAAAAAAAAAAAAAAAAAAAAAAAAAJH3DW3CTN", Address.encode("0x0888000000000000000000000000000000000002", 1, true), ""); 35 | assertEquals("0x0888000000000000000000000000000000000002", Address.decode("CFXTEST:TYPE.BUILTIN:AAEJUAAAAAAAAAAAAAAAAAAAAAAAAAAAAJH3DW3CTN"), ""); 36 | assertEquals("0x0888000000000000000000000000000000000002", Address.decode("cfxtest:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaajh3dw3ctn"), ""); 37 | assertEquals("0x0888000000000000000000000000000000000002", Address.decode("cfxtest:aaejuaaaaaaaaaaaaaaaaaaaaaaaaaaaajh3dw3ctn"), ""); 38 | 39 | assertEquals("0x1a2f80341409639ea6a35bbcab8299066109aa55", Address.decode("cfx:aarc9abycue0hhzgyrr53m6cxedgccrmmyybjgh4xg"), ""); 40 | assertEquals("0x85d80245dc02f5a89589e1f19c5c718e405b56cd", Address.decode("cfxtest:acc7uawf5ubtnmezvhu9dhc6sghea0403ywjz6wtpg"), ""); 41 | // 42 | // assertEquals("", CfxAddress.encode("", 10086, false), ""); 43 | // assertEquals("", CfxAddress.encode("", 10086, false), ""); 44 | // assertEquals("", CfxAddress.encode("", 10086, false), ""); 45 | } 46 | 47 | @Test 48 | @DisplayName("Address Corner Case") 49 | void cfxAddressEncoderFailTest() throws Exception { 50 | // encode: null, invalid hex char, invalid hex length, invalid chainId 51 | Assertions.assertThrows(Exception.class, () -> { 52 | Address.encode("zzzz", 1); 53 | }); 54 | Assertions.assertThrows(AddressException.class, () -> { 55 | Address.encode((byte[]) null, 1); 56 | }); 57 | Assertions.assertThrows(AddressException.class, () -> { 58 | Address.encode((String) null, 1); 59 | }); 60 | Assertions.assertThrows(AddressException.class, () -> { 61 | Address.encode("invalid len".getBytes(), 1); 62 | }); 63 | // 64 | // // decode: null, without :, invalid base32, invalid length, invalid checksum 65 | Assertions.assertThrows(AddressException.class, () -> { 66 | Address.decode(null); 67 | }); 68 | Assertions.assertThrows(AddressException.class, () -> { 69 | Address.decode("012345"); 70 | }); 71 | Assertions.assertThrows(AddressException.class, () -> { 72 | Address.decode("cfx:0206ujfsa1a11uuecwen3xytdmp8f03v14ksvfy"); 73 | }); 74 | Assertions.assertThrows(AddressException.class, () -> { 75 | Address.decode("cfx:0206ujfsa1a11uuecwen3xytdmp8f03v14ksvfyl"); 76 | }); 77 | Assertions.assertThrows(AddressException.class, () -> { 78 | Address.decode("cfx:0206ujfsa1a"); 79 | }); 80 | Assertions.assertThrows(AddressException.class, () -> { 81 | Address.decode("cfx:0048g000000000000000000000000000087t3jt2fd"); 82 | }); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/types/CfxBase32Tests.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import com.google.common.io.BaseEncoding; 4 | import conflux.web3j.crypto.ConfluxBase32; 5 | import org.junit.jupiter.api.DisplayName; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.util.Arrays; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | public class CfxBase32Tests { 13 | @Test 14 | @DisplayName("CfxBase32Encode") 15 | void cfxBase32() throws Exception { 16 | byte[] testBytes = "123456".getBytes(); 17 | assertEquals("ge3dgrbzg2", ConfluxBase32.encode(testBytes), ""); 18 | assertEquals(true, Arrays.equals(ConfluxBase32.decode("ge3dgrbzg2"), testBytes), ""); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/types/RPCTests.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | import conflux.web3j.Web3; 4 | import conflux.web3j.request.Epoch; 5 | import conflux.web3j.request.LogFilter; 6 | import conflux.web3j.response.*; 7 | import org.junit.jupiter.api.DisplayName; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import java.math.BigInteger; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.Optional; 14 | 15 | import static org.junit.jupiter.api.Assertions.assertEquals; 16 | import static org.junit.jupiter.api.Assertions.assertTrue; 17 | 18 | public class RPCTests { 19 | String MAIN_NET = "https://main.confluxrpc.com"; 20 | String TEST_NET = "https://test.confluxrpc.com"; 21 | String INSIDE_URL = "http://54.250.48.155:12537"; // trace methods opened 22 | String LOCAL_URL = "http://127.0.0.1:12537"; 23 | Web3 cfx = Web3.create(this.LOCAL_URL); // a local node that connected with testnet 24 | Web3 cfx_testnet = Web3.create(this.TEST_NET); 25 | Web3 cfx_inside_testnet = Web3.create(this.INSIDE_URL); 26 | Address EMPTY_ADDRESS = new Address("cfxtest:aame568esrpusxku1c449939ntrx2j0rxpmm5ge874"); 27 | Address TEST_ADDRESS = new Address("CFXTEST:TYPE.USER:AAK2RRA2NJVD77EZWJVX04KKDS9FZAGFE6D5R8E957"); 28 | /* 29 | @Test 30 | @DisplayName("getLog") 31 | void getLog() { 32 | Web3 cfx = Web3.create(this.MAIN_NET); 33 | LogFilter filter = new LogFilter(); 34 | filter.setFromEpoch(Epoch.numberOf(6818006)); 35 | filter.setToEpoch(Epoch.numberOf(6818007)); 36 | filter.setLimit(100L); 37 | filter.setOffset(0L); 38 | List
addresses = new ArrayList<>(); 39 | addresses.add(new Address("cfx:achc8nxj7r451c223m18w2dwjnmhkd6rxawrvkvsy2")); 40 | filter.setAddress(addresses); 41 | List logs = cfx.getLogs(filter).sendAndGet(); 42 | assertTrue(logs.size() > 0); 43 | assertEquals("cfx:achc8nxj7r451c223m18w2dwjnmhkd6rxawrvkvsy2", logs.get(0).getAddress().getAddress()); 44 | } 45 | 46 | @Test 47 | @DisplayName("getStatus") 48 | void getStatus() { 49 | Status status = cfx.getStatus().sendAndGet(); 50 | assertEquals(BigInteger.ONE, status.getChainId()); 51 | assertEquals(BigInteger.ONE, status.getNetworkId()); 52 | assertTrue(status.getLatestCheckpoint().intValue() > 0); 53 | assertTrue(status.getLatestConfirmed().intValue() > 0); 54 | assertTrue(status.getLatestState().intValue() > 0); 55 | } 56 | 57 | // Only can be tested with RPC has opened this RPC method 58 | @Test 59 | @DisplayName("cfx_getEpochReceipts") 60 | void getEpochReceipts() { 61 | // Web3 web3 = Web3.create(this.TEST_NET); 62 | // int empty_epoch = 100; 63 | // List> receipts = web3.getEpochReceipt(Epoch.numberOf(empty_epoch)).sendAndGet(); 64 | // assertTrue(receipts.size() > 0); 65 | // assertEquals(0, receipts.get(0).size()); 66 | // TODO test one epoch that have receipts 67 | } 68 | 69 | @Test 70 | @DisplayName("cfx_getAccountPendingInfo") 71 | void getAccountPendingInfo() { 72 | Web3 web3 = Web3.create(this.TEST_NET); 73 | Optional pendingInfo = web3.getAccountPendingInfo(EMPTY_ADDRESS).sendAndGet(); 74 | assertTrue(pendingInfo.isPresent()); 75 | assertEquals(0, pendingInfo.get().getLocalNonce().intValue()); 76 | assertEquals(BigInteger.valueOf(0), pendingInfo.get().getPendingNonce()); 77 | assertEquals("0x0000000000000000000000000000000000000000000000000000000000000000", pendingInfo.get().getNextPendingTx()); 78 | 79 | Optional testPendingInfo = web3.getAccountPendingInfo(TEST_ADDRESS).sendAndGet(); 80 | assertTrue(testPendingInfo.isPresent()); 81 | // assertTrue(testPendingInfo.get().getPendingCount().intValue() > 0); 82 | // assertTrue(testPendingInfo.get().getNextPendingTx().length() > 0); 83 | } 84 | 85 | @Test 86 | @DisplayName("cfx_getAccountPendingTransactions") 87 | void getAccountPendingTransactions() { 88 | Web3 web3 = Web3.create(this.TEST_NET); 89 | AccountPendingTransactions pendingTx = web3.getAccountPendingTransactions(EMPTY_ADDRESS).sendAndGet(); 90 | assertEquals(0, pendingTx.getPendingTransactions().size()); 91 | 92 | AccountPendingTransactions testPendingTx = web3.getAccountPendingTransactions(TEST_ADDRESS).sendAndGet(); 93 | assertEquals(testPendingTx.getPendingTransactions().size(), testPendingTx.getPendingCount().intValue()); 94 | } 95 | 96 | 97 | @Test 98 | @DisplayName("trace_block") 99 | void traceBlock() { 100 | Web3 web3 = Web3.create(this.INSIDE_URL); 101 | String blockHash = "0xf07e42b132bf91d2b5682e65964194bc3087713b956f508b034fe10bb22dd252"; 102 | Optional blockTraces = web3.traceBlock(blockHash).sendAndGet(); 103 | assertTrue(blockTraces.isPresent()); 104 | assertTrue(blockTraces.get().getTransactionTraces().size() > 0); 105 | } 106 | 107 | @Test 108 | @DisplayName("trace_transaction") 109 | void traceTransaction() { 110 | Web3 web3 = Web3.create(this.INSIDE_URL); 111 | String txHash = "0xd52149d9000c57cf5b831dc5dbd1f68a95e9a1945154ab1a3743c8c645f57603"; 112 | Optional> traces = web3.traceTransaction(txHash).sendAndGet(); 113 | assertTrue(traces.isPresent()); 114 | assertTrue(traces.get().size() > 0); 115 | System.out.println(traces.get().get(0)); 116 | } 117 | */ 118 | } 119 | -------------------------------------------------------------------------------- /src/test/java/conflux/web3j/types/RawTransactionTests.java: -------------------------------------------------------------------------------- 1 | package conflux.web3j.types; 2 | 3 | //import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.DisplayName; 5 | import org.junit.jupiter.api.Test; 6 | import org.web3j.rlp.RlpEncoder; 7 | import org.web3j.utils.Numeric; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | import java.math.BigInteger; 11 | import java.util.Arrays; 12 | 13 | public class RawTransactionTests { 14 | @Test 15 | @DisplayName("Raw2930TransactionRlp encode") 16 | void raw2930TransactionRlpEncodeTest() { 17 | RawTransaction tx = new RawTransaction(); 18 | tx.setType(RawTransaction.TYPE_2930); 19 | tx.setNonce(new BigInteger("100")); 20 | tx.setGas(new BigInteger("100")); 21 | tx.setGasPrice(new BigInteger("100")); 22 | tx.setChainId(new BigInteger("100")); 23 | tx.setEpochHeight(new BigInteger("100")); 24 | tx.setStorageLimit(new BigInteger("100")); 25 | tx.setValue(new BigInteger("100")); 26 | tx.setTo(new Address("0x19578cf3c71eab48cf810c78b5175d5c9e6ef441", 1)); 27 | tx.setData(Numeric.toHexString("Hello, World".getBytes())); 28 | 29 | AccessListEntry entry = new AccessListEntry(); 30 | entry.setAddress(new CfxAddress("0x19578cf3c71eab48cf810c78b5175d5c9e6ef441", 1)); 31 | entry.setStorageKeys(Arrays.asList(new String[]{"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"})); 32 | 33 | tx.setAccessList(Arrays.asList(new AccessListEntry[]{entry})); 34 | 35 | byte[] encoded = RlpEncoder.encode(tx.toRlp()); 36 | 37 | assertEquals(Numeric.toHexString(encoded), "0xf8636464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", ""); 38 | } 39 | 40 | @Test 41 | @DisplayName("Raw1559TransactionRlp encode") 42 | void raw1559TransactionRlpEncodeTest() { 43 | RawTransaction tx = new RawTransaction(); 44 | tx.setType(RawTransaction.TYPE_1559); 45 | tx.setNonce(new BigInteger("100")); 46 | tx.setGas(new BigInteger("100")); 47 | tx.setMaxPriorityFeePerGas(new BigInteger("100")); 48 | tx.setMaxFeePerGas(new BigInteger("100")); 49 | tx.setChainId(new BigInteger("100")); 50 | tx.setEpochHeight(new BigInteger("100")); 51 | tx.setStorageLimit(new BigInteger("100")); 52 | tx.setValue(new BigInteger("100")); 53 | tx.setTo(new Address("0x19578cf3c71eab48cf810c78b5175d5c9e6ef441", 1)); 54 | tx.setData(Numeric.toHexString("Hello, World".getBytes())); 55 | 56 | AccessListEntry entry = new AccessListEntry(); 57 | entry.setAddress(new CfxAddress("0x19578cf3c71eab48cf810c78b5175d5c9e6ef441", 1)); 58 | entry.setStorageKeys(Arrays.asList(new String[]{"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"})); 59 | 60 | tx.setAccessList(Arrays.asList(new AccessListEntry[]{entry})); 61 | 62 | byte[] encoded = RlpEncoder.encode(tx.toRlp()); 63 | 64 | assertEquals(Numeric.toHexString(encoded), "0xf864646464649419578cf3c71eab48cf810c78b5175d5c9e6ef441646464648c48656c6c6f2c20576f726c64f838f79419578cf3c71eab48cf810c78b5175d5c9e6ef441e1a01234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", ""); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/resources/structured_data_json_files/ValidStructuredData.json: -------------------------------------------------------------------------------- 1 | { 2 | "types": { 3 | "CIP23Domain": [ 4 | { 5 | "name": "name", 6 | "type": "string" 7 | }, 8 | { 9 | "name": "version", 10 | "type": "string" 11 | }, 12 | { 13 | "name": "chainId", 14 | "type": "uint256" 15 | }, 16 | { 17 | "name": "verifyingContract", 18 | "type": "address" 19 | } 20 | ], 21 | "Person": [ 22 | { 23 | "name": "name", 24 | "type": "string" 25 | }, 26 | { 27 | "name": "wallet", 28 | "type": "address" 29 | } 30 | ], 31 | "Mail": [ 32 | { 33 | "name": "from", 34 | "type": "Person" 35 | }, 36 | { 37 | "name": "to", 38 | "type": "Person" 39 | }, 40 | { 41 | "name": "contents", 42 | "type": "string" 43 | } 44 | ] 45 | }, 46 | "primaryType": "Mail", 47 | "domain": { 48 | "name": "Ether Mail", 49 | "version": "1", 50 | "chainId": 1, 51 | "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" 52 | }, 53 | "message": { 54 | "from": { 55 | "name": "Cow", 56 | "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" 57 | }, 58 | "to": { 59 | "name": "Bob", 60 | "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" 61 | }, 62 | "contents": "Hello, Bob!" 63 | } 64 | } --------------------------------------------------------------------------------