├── .github
└── FUNDING.yml
├── .gitignore
├── README.md
├── abi
├── basicInfoGetter.abi
├── basicInfoGetter.bin
└── problem.txt
├── abiWrapper
└── com
│ └── micronautics
│ └── solidity
│ └── BasicInfoGetter.java
├── assembly.sbt
├── bin
├── attachHttp
├── attachIpc
├── demo
├── gethApis
├── isGethListening
├── isWeb3jReady
├── runGeth
├── tweetNewVersion
└── web3j
├── build.sbt
├── core-4.5.16.pom
├── demo
├── Demo.scala
├── DemoObservables.scala
├── DemoSmartContracts.scala
├── DemoTransaction.scala
└── Main.scala
├── geth.md
├── logos
├── repository-open-graph-template.png
├── repository-open-graph.ai
├── repository-open-graph.png
└── web3j-orange.png
├── project
├── build.properties
├── build.sbt
├── ghpages.sbt
└── plugins.sbt
├── publish.sbt
└── src
├── main
├── resources
│ └── logback.xml
└── scala
│ └── com
│ └── micronautics
│ └── web3j
│ ├── Cmd.scala
│ ├── Ether.scala
│ ├── EthereumASynchronous.scala
│ ├── EthereumSynchronous.scala
│ ├── InfuraNetwork.java
│ ├── ValueClasses.scala
│ ├── Web3JScala.scala
│ └── package.scala
└── test
├── resources
└── basic_info_getter.sol
└── scala
└── EtherTest.scala
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | [mslinn]
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .classpath
2 | *.sublime-*
3 | *~
4 | .cache
5 | .ethereum/
6 | .github/
7 | .idea/
8 | .idea_modules/
9 | .project
10 | .history
11 | .settings/
12 | *.iml
13 | *.stackdump
14 | *.zip
15 | #abi/
16 | #abiWrapper/
17 | logs/
18 | project/target/
19 | target/
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DEATH NOTICE
2 | May 8, 2020: I have abandoned this project and will not update it. If someone else wants to take it over please contact me.
3 |
4 | -- Mike
5 |
6 | # Web3J-Scala Library
7 |
8 |
9 |
10 | [](https://badge.fury.io/gh/mslinn%2Fweb3j-scala)
11 |
12 | `web3j-scala` is an idiomatic Scala wrapper around [Web3J](https://www.web3j.io) for Ethereum.
13 | Web3J is a lightweight, reactive, somewhat type safe Java and Android library for integrating with nodes on Ethereum blockchains.
14 |
15 | Web3J features RxJava extensions, and `web3j-scala` wraps that syntax in Scala goodness.
16 | For example, the `web3j-scala` [observable methods](http://mslinn.github.io/web3j-scala/latest/api/com/micronautics/web3j/Web3JScala$.html)
17 | provide [simple and efficient application code](https://github.com/mslinn/web3j-scala/blob/master/demo/DemoObservables.scala#L14-L22).
18 | Scala's [value classes are used](https://github.com/mslinn/web3j-scala/blob/master/src/main/scala/com/micronautics/web3j/ValueClasses.scala)
19 | to provide much stronger type safety than Web3J, without incurring a runtime penalty.
20 |
21 | ## Use As a Library
22 | Add this to your SBT project's `build.sbt`:
23 |
24 | resolvers ++= Seq(
25 | "micronautics/scala on bintray" at "https://dl.bintray.com/micronautics/scala",
26 | "ethereum" at "https://dl.bintray.com/ethereum/maven/"
27 | )
28 |
29 | libraryDependencies += "com.micronautics" %% "web3j-scala" % "4.5.17" withSources()
30 |
31 | This library is cross-built for Scala 2.12 and 2.13. Tested with Oracle JDK 8 and OpenJDK 8 & 11.
32 |
33 | ## Questions and Problems
34 | This library merely wraps [Web3J](https://www.web3j.io), so if you have questions about how to use this library,
35 | please [read their docs](https://web3j.readthedocs.io/en/stable/quickstart.html), and participate in [their Gitter channel](https://gitter.im/web3j/web3j).
36 |
37 | If you find a bug in this library you can [post an issue here](https://github.com/mslinn/web3j-scala/issues).
38 |
39 | ## Run the Demo Program
40 | The demo program performs the following:
41 | - Follows the outline of the [Web3J Getting Started](https://docs.web3j.io/getting_started.html#start-sending-requests) documentation,
42 | adapted for Web3J-Scala, including synchronous and asynchronous versions of the available methods.
43 | - Compiles an example Solidity program that defines a smart contract.
44 | - Creates a JVM wrapper from an example smart contract.
45 |
46 | To run the demo:
47 | 1. Start up an Ethereum client if you don’t already have one running, such as `geth`.
48 | The `bin/runGeth` script invokes `geth` with the following options, which are convenient for development but not secure enough for production:
49 | - The Ethereum data directory is set to `~/.ethereum`, or a subdirectory that depends on the network chosen;
50 | the directory will be created if required.
51 | - HTTP-RPC server at `localhost:8545` is enabled, and all APIs are allowed.
52 | - Ethereum's experimental Whisper message facility is enabled.
53 | - Inter-process communication will be via a virtual file called `geth.ipc`,
54 | located at `~/.ethereum` or a subdirectory.
55 | - WS-RPC server at `localhost:8546` is enabled, and all APIs are allowed.
56 | - Info verbosity is specified.
57 | - A log file for the `geth` output will be written, or overwritten, in `logs/geth.log`;
58 | the `log/` directory will be created if it does not already exist.
59 | ```
60 | $ mkdir logs/
61 | $ geth \
62 | #--datadir .ethereum/devnet --dev \ # boots quickly but has no deployed contracts from others
63 | --datadir .ethereum/rinkeby --rinkeby \ # takes about 15 minutes to boot, but has contracts
64 | --ipcpath geth.ipc \
65 | --metrics \
66 | --rpc \
67 | --rpcapi eth,net,web3,clique,debug,eth,miner,personal,rpc,ssh,txpool \
68 | --shh \
69 | --ws \
70 | --wsapi eth,net,web3,clique,debug,eth,miner,personal,rpc,ssh,txpool \
71 | --verbosity 2
72 | ```
73 | You will see the message `No etherbase set and no accounts found as default`.
74 | Etherbase is the index into `personal.listAccounts` which determines the account to send Ether too.
75 | You can specify this value with the option `--etherbase 0`.
76 | 2. The shell that you just used will continuously scroll output so long as `geth` continues to run,
77 | so type the following into another shell:
78 | ```
79 | $ bin/demo
80 | ```
81 | The demo has two major components:
82 | 1. [Creates a JVM wrapper](https://github.com/mslinn/web3j-scala/blob/master/demo/DemoSmartContracts.scala)
83 | for the [sample smart contract](https://github.com/mslinn/web3j-scala/blob/master/src/test/resources/basic_info_getter.sol).
84 | 2. The second portion of the demo consists of the following:
85 | - Examples of using `web3j-scala`'s [synchrounous and asynchronous APIs](https://github.com/mslinn/web3j-scala/blob/master/demo/Demo.scala)
86 | - Examples of working with [RxJava's Observables from Scala](https://github.com/mslinn/web3j-scala/blob/master/demo/DemoObservables.scala)
87 | - Examples of working with [JVM wrappers around Ethereum smart contracts](https://github.com/mslinn/web3j-scala/blob/master/demo/DemoSmartContracts.scala).
88 | - Examples of using [transactions](https://github.com/mslinn/web3j-scala/blob/master/demo/DemoTransaction.scala)
89 | with Ethereum wallet files and the Ethereum client.
90 | 3. The `bin/web3j` script runs the [Web3J command-line console](https://docs.web3j.io/command_line.html).
91 | The script builds a fat jar the first time it is run, so the command runs quickly on subsequent invocations.
92 | 4. More scripts are provided in the `bin/` directory, including:
93 | - [bin/attachHttp](https://github.com/mslinn/web3j-scala/blob/master/bin/attachHttp) -
94 | Attach to a running geth instance via HTTP and open a
95 | [JavaScript console](https://godoc.org/github.com/robertkrimen/otto)
96 | - [bin/attachIpc](https://github.com/mslinn/web3j-scala/blob/master/bin/attachIpc) -
97 | Attach to a running geth instance via IPC and open a JavaScript console.
98 | This script might need to be edited if a network other than `devnet` is used.
99 | - [bin/getApis](https://github.com/mslinn/web3j-scala/blob/master/bin/gethApis) -
100 | Reports the available APIs exposed by this `geth` instance.
101 | - [bin/isGethListening](https://github.com/mslinn/web3j-scala/blob/master/bin/isGethListening) -
102 | Verifies that `geth` is listening on HTTP port 8545
103 |
104 | ## Developers
105 | ### API Documentation
106 | * [This library's Scaladoc is here](http://mslinn.github.io/web3j-scala/latest/api/com/micronautics/web3j/index.html)
107 | and the [gitter channel is here](https://gitter.im/web3j-scala/Lobby).
108 |
109 | * [The Web3J JavaDoc is here](https://jar-download.com/java-documentation-javadoc.php?a=core&g=org.web3j&v=3.0.2),
110 | and here is the [Web3J gitter channel](https://gitter.im/web3j/web3j).
111 |
112 | ### Publishing
113 | 1. Update the version string in `build.sbt` and in this `README.md` before attempting to publish to Bintray.
114 | 2. Commit changes with a descriptive comment:
115 | ```
116 | $ git add -a && git commit -m "Comment here"
117 | ```
118 | 3. Publish a new version of this library, including committing changes and updating the Scaladoc with this command:
119 | ```
120 | $ sbt publishAndTag
121 | ```
122 |
123 | ### Updating Scaladoc
124 | 1. Use the Scaladoc project; first do a [preflight check of the Scaladoc output](https://github.com/mslinn/multi-scaladoc#preflight-check-optimize-your-scaladoc-source):
125 | ```
126 | sbt "; project web3j-scala; doc; project demo; doc"
127 | ```
128 |
129 | 2. Now [Update the Git Version String and Make a New Tag](https://github.com/mslinn/multi-scaladoc#update-the-git-version-string-and-make-a-new-tag).
130 |
131 | 3. Now [edit the multi-scaladoc settings](https://github.com/mslinn/multi-scaladoc#running-this-program)
132 | ```
133 | export SCALADOC_SUB_PROJECT_NAMES="web3j-scala,demo"
134 | ```
135 |
136 | 4. Run multi-scaladoc:
137 | ```
138 | ../scaladoc/bin/run
139 | ```
140 |
141 | ### Updating Scaladoc and Committing Changes Without Publishing a New Version
142 | This task rebuilds the docs, commits the git repository, and publishes the updated Scaladoc without publishing a new version:
143 |
144 | $ sbt commitAndDoc
145 |
146 | ## Sponsor
147 |
148 |
149 | This project is sponsored by [Micronautics Research Corporation](http://www.micronauticsresearch.com/),
150 | the company that delivers online Scala training via [ScalaCourses.com](http://www.ScalaCourses.com).
151 | You can learn Scala by taking the [Introduction to Scala](http://www.ScalaCourses.com/showCourse/40),
152 | and [Intermediate Scala](http://www.ScalaCourses.com/showCourse/45) courses.
153 |
154 | Please [contact us](mailto:sales@micronauticsresearch.com) to discuss your organization’s training needs.
155 |
156 | ## License
157 | This software is published under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0.html).
158 |
--------------------------------------------------------------------------------
/abi/basicInfoGetter.abi:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[],"name":"getContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getContractBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTxGasprice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBlockTimestamp","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMsgSender","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentGaslimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMsgGas","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentDifficulty","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"getMsgValue","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getTxOrigin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMsgData","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentMinerAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
--------------------------------------------------------------------------------
/abi/basicInfoGetter.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000f57600080fd5b60008054600160a060020a033316600160a060020a031990911617905561038f8061003b6000396000f3006060604052600436106100cf5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166332a2c5d081146100d457806341c0e1b5146101105780636f9fb98a146101255780636fd902e11461014a57806377e5bf841461015d578063796b89b9146101705780637a6ce2e11461018357806392b7d5b9146101965780639d5c6061146101a9578063a1188e56146101bc578063a17042cc146101cf578063b8077e28146101d7578063c8e7ca2e146101ea578063f8f46b5f14610274575b600080fd5b34156100df57600080fd5b6100e7610287565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b341561011b57600080fd5b61012361028b565b005b341561013057600080fd5b6101386102cc565b60405190815260200160405180910390f35b341561015557600080fd5b6101386102e7565b341561016857600080fd5b6101386102eb565b341561017b57600080fd5b6101386102ef565b341561018e57600080fd5b6100e76102f3565b34156101a157600080fd5b6101386102f7565b34156101b457600080fd5b6101386102fb565b34156101c757600080fd5b610138610303565b610138610307565b34156101e257600080fd5b6100e761030b565b34156101f557600080fd5b6101fd61030f565b60405160208082528190810183818151815260200191508051906020019080838360005b83811015610239578082015183820152602001610221565b50505050905090810190601f1680156102665780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561027f57600080fd5b6100e761034d565b3090565b6000543373ffffffffffffffffffffffffffffffffffffffff908116911614156102ca5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b73ffffffffffffffffffffffffffffffffffffffff30163190565b4390565b3a90565b4290565b3390565b4590565b60005a905090565b4490565b3490565b3290565b610317610351565b6000368080601f016020809104026020016040519081016040528181529291906020840183838082843750949550505050505090565b4190565b602060405190810160405260008152905600a165627a7a7230582013a79aa2701d45e426efdad37282ae3be07edda51eed0dbac13611b8053a3fc80029
--------------------------------------------------------------------------------
/abi/problem.txt:
--------------------------------------------------------------------------------
1 | I am having a problem generating a wrapper from a Solidity 0.4.18 program.
2 | ```
3 | $ solc --bin --abi --optimize --overwrite -o abi/ src/test/resources/basic_info_getter.sol
4 |
5 | $ l abi
6 | total 16
7 | drwxrwxr-x 2 mslinn mslinn 4096 Nov 10 12:33 ./
8 | drwxrwxr-x 12 mslinn mslinn 4096 Nov 10 12:33 ../
9 | -rw-rw-r-- 1 mslinn mslinn 2227 Nov 10 12:33 basicInfoGetter.abi
10 | -rw-rw-r-- 1 mslinn mslinn 1940 Nov 10 12:33 basicInfoGetter.bin
11 |
12 | $ bin/web3j solidity generate abi/basicInfoGetter.bin abi/basicInfoGetter.abi -o abiWrapper/ -p com.micronautics.solidity
13 |
14 | _ _____ _ _
15 | | | |____ (_) (_)
16 | __ _____| |__ / /_ _ ___
17 | \ \ /\ / / _ \ '_ \ \ \ | | | / _ \
18 | \ V V / __/ |_) |.___/ / | _ | || (_) |
19 | \_/\_/ \___|_.__/ \____/| |(_)|_| \___/
20 | _/ |
21 | |__/
22 |
23 | Invalid input binary file specified: abi/basic_info_getter.bin
24 | ```
25 |
26 | I have copied the .sol, .abi and .bin files to https://www.micronauticsresearch.com/abi.zip
27 | Suggestions?
28 |
--------------------------------------------------------------------------------
/abiWrapper/com/micronautics/solidity/BasicInfoGetter.java:
--------------------------------------------------------------------------------
1 | package com.micronautics.solidity;
2 |
3 | import java.math.BigInteger;
4 | import java.util.Collections;
5 | import org.web3j.abi.TypeReference;
6 | import org.web3j.abi.datatypes.Address;
7 | import org.web3j.abi.datatypes.DynamicBytes;
8 | import org.web3j.abi.datatypes.Function;
9 | import org.web3j.abi.datatypes.generated.Uint256;
10 | import org.web3j.crypto.Credentials;
11 | import org.web3j.protocol.Web3j;
12 | import org.web3j.protocol.core.RemoteCall;
13 | import org.web3j.protocol.core.methods.response.TransactionReceipt;
14 | import org.web3j.tx.Contract;
15 | import org.web3j.tx.TransactionManager;
16 | import org.web3j.tx.gas.StaticGasProvider;
17 |
18 | /**
19 | *
Auto generated code.
20 | *
Do not modify!
21 | *
Please use the web3j command line tools,
22 | * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the
23 | * codegen module to update.
24 | *
25 | *
Generated with web3j version 3.0.2.
26 | */
27 | public final class BasicInfoGetter extends Contract {
28 | private static final String BINARY = "6060604052341561000f57600080fd5b60008054600160a060020a033316600160a060020a031990911617905561038f8061003b6000396000f3006060604052600436106100cf5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166332a2c5d081146100d457806341c0e1b5146101105780636f9fb98a146101255780636fd902e11461014a57806377e5bf841461015d578063796b89b9146101705780637a6ce2e11461018357806392b7d5b9146101965780639d5c6061146101a9578063a1188e56146101bc578063a17042cc146101cf578063b8077e28146101d7578063c8e7ca2e146101ea578063f8f46b5f14610274575b600080fd5b34156100df57600080fd5b6100e7610287565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b341561011b57600080fd5b61012361028b565b005b341561013057600080fd5b6101386102cc565b60405190815260200160405180910390f35b341561015557600080fd5b6101386102e7565b341561016857600080fd5b6101386102eb565b341561017b57600080fd5b6101386102ef565b341561018e57600080fd5b6100e76102f3565b34156101a157600080fd5b6101386102f7565b34156101b457600080fd5b6101386102fb565b34156101c757600080fd5b610138610303565b610138610307565b34156101e257600080fd5b6100e761030b565b34156101f557600080fd5b6101fd61030f565b60405160208082528190810183818151815260200191508051906020019080838360005b83811015610239578082015183820152602001610221565b50505050905090810190601f1680156102665780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561027f57600080fd5b6100e761034d565b3090565b6000543373ffffffffffffffffffffffffffffffffffffffff908116911614156102ca5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b73ffffffffffffffffffffffffffffffffffffffff30163190565b4390565b3a90565b4290565b3390565b4590565b60005a905090565b4490565b3490565b3290565b610317610351565b6000368080601f016020809104026020016040519081016040528181529291906020840183838082843750949550505050505090565b4190565b602060405190810160405260008152905600a165627a7a7230582013a79aa2701d45e426efdad37282ae3be07edda51eed0dbac13611b8053a3fc80029";
29 |
30 | private BasicInfoGetter(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
31 | super(BINARY, contractAddress, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
32 | }
33 |
34 | private BasicInfoGetter(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
35 | super(BINARY, contractAddress, web3j, transactionManager, new StaticGasProvider(gasPrice, gasLimit));
36 | }
37 |
38 | /*public RemoteCall getContractAddress() {
39 | Function function = new Function("getContractAddress",
40 | Arrays.asList(),
41 | Arrays.>asList(new TypeReference() {}));
42 | return executeRemoteCallSingleValueReturn(function, String.class);
43 | }*/
44 |
45 | public RemoteCall kill() {
46 | Function function = new Function(
47 | "kill",
48 | Collections.emptyList(),
49 | Collections.emptyList());
50 | return executeRemoteCallTransaction(function);
51 | }
52 |
53 | public RemoteCall getContractBalance() {
54 | Function function = new Function("getContractBalance",
55 | Collections.emptyList(),
56 | Collections.singletonList(new TypeReference() {
57 | }));
58 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
59 | }
60 |
61 | public RemoteCall getCurrentBlockNumber() {
62 | Function function = new Function("getCurrentBlockNumber",
63 | Collections.emptyList(),
64 | Collections.singletonList(new TypeReference() {}));
65 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
66 | }
67 |
68 | public RemoteCall getTxGasprice() {
69 | Function function = new Function("getTxGasprice",
70 | Collections.emptyList(),
71 | Collections.singletonList(new TypeReference() {
72 | }));
73 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
74 | }
75 |
76 | public RemoteCall getBlockTimestamp() {
77 | Function function = new Function("getBlockTimestamp",
78 | Collections.emptyList(),
79 | Collections.singletonList(new TypeReference() {
80 | }));
81 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
82 | }
83 |
84 | public RemoteCall getMsgSender() {
85 | Function function = new Function("getMsgSender",
86 | Collections.emptyList(),
87 | Collections.singletonList(new TypeReference() {}));
88 | return executeRemoteCallSingleValueReturn(function, String.class);
89 | }
90 |
91 | public RemoteCall getCurrentGaslimit() {
92 | Function function = new Function("getCurrentGaslimit",
93 | Collections.emptyList(),
94 | Collections.singletonList(new TypeReference() {}));
95 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
96 | }
97 |
98 | public RemoteCall getMsgGas() {
99 | Function function = new Function("getMsgGas",
100 | Collections.emptyList(),
101 | Collections.singletonList(new TypeReference() {}));
102 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
103 | }
104 |
105 | public RemoteCall getCurrentDifficulty() {
106 | Function function = new Function("getCurrentDifficulty",
107 | Collections.emptyList(),
108 | Collections.singletonList(new TypeReference() {}));
109 | return executeRemoteCallSingleValueReturn(function, BigInteger.class);
110 | }
111 |
112 | public RemoteCall getMsgValue(BigInteger weiValue) {
113 | Function function = new Function(
114 | "getMsgValue",
115 | Collections.emptyList(),
116 | Collections.emptyList());
117 | return executeRemoteCallTransaction(function, weiValue);
118 | }
119 |
120 | public RemoteCall getTxOrigin() {
121 | Function function = new Function("getTxOrigin",
122 | Collections.emptyList(),
123 | Collections.singletonList(new TypeReference() {}));
124 | return executeRemoteCallSingleValueReturn(function, String.class);
125 | }
126 |
127 | public RemoteCall getMsgData() {
128 | Function function = new Function("getMsgData",
129 | Collections.emptyList(),
130 | Collections.singletonList(new TypeReference() {}));
131 | return executeRemoteCallSingleValueReturn(function, byte[].class);
132 | }
133 |
134 | public RemoteCall getCurrentMinerAddress() {
135 | Function function = new Function("getCurrentMinerAddress",
136 | Collections.emptyList(),
137 | Collections.singletonList(new TypeReference() {}));
138 | return executeRemoteCallSingleValueReturn(function, String.class);
139 | }
140 |
141 | public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
142 | return deployRemoteCall(BasicInfoGetter.class, web3j, credentials, gasPrice, gasLimit, BINARY, "");
143 | }
144 |
145 | public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
146 | return deployRemoteCall(BasicInfoGetter.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "");
147 | }
148 |
149 | public static BasicInfoGetter load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
150 | return new BasicInfoGetter(contractAddress, web3j, credentials, gasPrice, gasLimit);
151 | }
152 |
153 | public static BasicInfoGetter load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
154 | return new BasicInfoGetter(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/assembly.sbt:
--------------------------------------------------------------------------------
1 | // Settings for sbt assembly
2 |
3 | test in assembly := {}
4 |
5 | mainClass in assembly := Some("org.web3j.console.Runner")
6 |
7 | assemblyMergeStrategy in assembly := {
8 | case PathList("META-INF", xs @ _*) => MergeStrategy.discard
9 | case x => MergeStrategy.first
10 | }
11 |
12 | //fullClasspath in assembly := (fullClasspath in Compile).value
13 |
14 | //exportJars := true
15 |
--------------------------------------------------------------------------------
/bin/attachHttp:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Attach to a running geth instance and open a JavaScript console
4 |
5 | geth attach http://localhost:8545
6 |
7 | # Welcome to the Geth JavaScript console!
8 | #
9 | # instance: Geth/v1.7.3-unstable-3ee86a57/linux-amd64/go1.9.1
10 | # coinbase: 0x549d692ea074df8a9585b16775117e732a17f444
11 | # at block: 0 (Wed, 31 Dec 1969 16:00:00 PST)
12 | # modules: clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
13 |
--------------------------------------------------------------------------------
/bin/attachIpc:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Attach to a running geth (dev) instance via IPC:
4 |
5 | geth attach ipc:"${HOME}/.ethereum/devnet/geth.ipc"
6 |
7 | # Welcome to the Geth JavaScript console!
8 | #
9 | # instance: Geth/v1.7.3-unstable-3ee86a57/linux-amd64/go1.9.1
10 | # coinbase: 0x549d692ea074df8a9585b16775117e732a17f444
11 | # at block: 0 (Wed, 31 Dec 1969 16:00:00 PST)
12 | # datadir: /home/mslinn/.ethereum/devnet
13 | # modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0
14 |
--------------------------------------------------------------------------------
/bin/demo:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sbt "test:runMain demo.CreateSmartContracts" \
4 | "test:runMain demo.Main"
5 |
--------------------------------------------------------------------------------
/bin/gethApis:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Discover the geth APIs provided by invoking the modules JSON-RPC method
4 | # See https://github.com/ethereum/go-ethereum/wiki/Management-APIs
5 |
6 | network="${1:-devnet}"
7 |
8 | echo '{"jsonrpc":"2.0","method":"rpc_modules","params":[],"id":1}' | \
9 | nc -NU ${HOME}/.ethereum/${network}/geth.ipc | \
10 | python -m json.tool
11 |
12 | # Typical response:
13 | # {
14 | # "jsonrpc":"2.0",
15 | # "id":1,
16 | # "result":{
17 | # "admin":"1.0",
18 | # "clique":"1.0",
19 | # "debug":"1.0",
20 | # "eth":"1.0",
21 | # "miner":"1.0",
22 | # "net":"1.0",
23 | # "personal":"1.0",
24 | # "rpc":"1.0",
25 | # "shh":"1.0",
26 | # "txpool":"1.0",
27 | # "web3":"1.0"
28 | # }
29 | # }
30 |
--------------------------------------------------------------------------------
/bin/isGethListening:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Verify that geth is listening on port 8545
4 |
5 | sudo netstat -pan | grep 8545
6 |
7 | # tcp 0 0 127.0.0.1:8545 0.0.0.0:* LISTEN 22296/geth
8 |
--------------------------------------------------------------------------------
/bin/isWeb3jReady:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | VERSION="$( cat build.sbt | grep 'val web3jVersion =' | cut -d' ' -f 4 | tr -d '"' | tr -d "\r" )"
4 | wget --no-hsts https://repo1.maven.org/maven2/org/web3j/core/$VERSION/core-$VERSION.pom > /dev/null 2>&1
5 | if [ $? -eq 0 ]; then
6 | echo "Web3j v$VERSION is ready!!!"
7 | else
8 | echo "Web3j v$VERSION is NOT ready. Try again later."
9 | fi
10 |
11 |
--------------------------------------------------------------------------------
/bin/runGeth:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ETHEREUM_HOME="${HOME}/.ethereum"
4 |
5 | function help {
6 | echo "
7 | Usage: $0 [Network [Options]]
8 | Network defaults to dev. Other supported values are: main, rinkeby and ropsten.
9 | Options can be any geth command-line options that do not conflict or duplicate existing options used.
10 |
11 | This script invokes geth with the following options:
12 | - The Ethereum data directory is set to $ETHEREUM_HOME, or a subdirectory that depends on the network chosen; the directory will be created if required.
13 | - HTTP-RPC server at localhost:8545 is enabled, and all APIs are allowed.
14 | - Ethereum's experimental Whisper message facility is enabled.
15 | - Inter-process communication will be via a virtual file located at $ETHEREUM_HOME/geth.ipc.
16 | - WS-RPC server at localhost:8546 is enabled, and all APIs are allowed.
17 | - Info verbosity is specified.
18 | - A log file for the geth output will be written, or overwritten, in logs/geth.log;
19 | the log/ directory will be created if it does not already exist.
20 |
21 | You will see the message 'No etherbase set and no accounts found as default'.
22 | Etherbase is the index into personal.listAccounts which determines the account to send Ether too.
23 | You can specify this value with this option: --etherbase 0
24 |
25 | geth -h # displays the geth help message; the help message for geth v1.7.3 is available in geth.md.
26 | "
27 | exit 1
28 | }
29 |
30 | if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then help; fi
31 |
32 | case "$1" in
33 | kovan)
34 | echo "Error: The Kovan test network is only supported by Parity"
35 | exit 1
36 | ;;
37 |
38 | main) # Live network, takes hours to boot, real money is at risk with this choice
39 | ETHEREUM_NETWORK=mainnet
40 | ETHEREUM_HOME="$ETHEREUM_HOME"
41 | DATADIR="--datadir $ETHEREUM_HOME"
42 | shift
43 | ;;
44 |
45 | rinkeby) # This test network takes about 15 minutes to boot, and has contracts. Only supported by geth
46 | ETHEREUM_NETWORK=$1
47 | ETHEREUM_HOME="$ETHEREUM_HOME/$ETHEREUM_NETWORK"
48 | DATADIR="--datadir $ETHEREUM_HOME --$ETHEREUM_NETWORK"
49 | shift
50 | ;;
51 |
52 | ropsten) # This test network takes about 15 minutes to boot, and has contracts. Supported by geth and Parity.
53 | ETHEREUM_NETWORK=$1
54 | ETHEREUM_HOME="$ETHEREUM_HOME/$ETHEREUM_NETWORK"
55 | DATADIR="--datadir $ETHEREUM_HOME --testnet"
56 | shift
57 | ;;
58 |
59 | dev) # Generic development network; boots very quickly but has no deployed contracts from others
60 | shift
61 | ETHEREUM_NETWORK=devnet
62 | ETHEREUM_HOME="$ETHEREUM_HOME/$ETHEREUM_NETWORK"
63 | DATADIR="--datadir $ETHEREUM_HOME --dev"
64 | ;;
65 |
66 | "") # Generic development network; boots very quickly but has no deployed contracts from others
67 | ETHEREUM_NETWORK=devnet
68 | ETHEREUM_HOME="$ETHEREUM_HOME/$ETHEREUM_NETWORK"
69 | DATADIR="--datadir $ETHEREUM_HOME --dev"
70 | ;;
71 | esac
72 |
73 | echo "Using $ETHEREUM_NETWORK Ethereum network with home $ETHEREUM_HOME at timestamp $(date)"
74 |
75 | mkdir -p "$ETHEREUM_HOME"
76 | mkdir -p logs/
77 |
78 | # All geth options are defined here: https://github.com/ethereum/go-ethereum/blob/master/cmd/utils/flags.go#L105
79 | # Seems --ipcapi is no longer supported. Wonder what that means?
80 | #
81 | # Beside the officially exposed DApp API namespaces (eth, shh, web3), Geth provides the following extra API namespaces:
82 | # admin: Geth node management
83 | # debug: Geth node debugging
84 | # miner: Miner and DAG management
85 | # personal: Account management
86 | # txpool: Transaction pool inspection
87 |
88 | APIS_MIN=eth,net,web3
89 | export APIS="$APIS_MIN,clique,debug,eth,miner,personal,rpc,ssh,txpool" # Edit this if desired
90 |
91 | set -xv
92 | geth \
93 | ${DATADIR} \
94 | --ipcpath geth.ipc \
95 | --metrics \
96 | --rpc \
97 | --rpcapi $APIS \
98 | --shh \
99 | --ws \
100 | --wsapi $APIS \
101 | --verbosity 3 \
102 | "$*" 2> logs/geth.log
103 | set +xv
104 |
--------------------------------------------------------------------------------
/bin/tweetNewVersion:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | function findSettingValue {
4 | echo "$( grep "$1 :=" build.sbt | cut -d' ' -f 3 | tr -d \" | tr -d '\n' | tr -d '\r' )"
5 | }
6 |
7 | function findVarValue {
8 | echo "$( grep "$1 =" build.sbt | cut -d' ' -f 4 | tr -d \" | tr -d '\n' | tr -d '\r' )"
9 | }
10 |
11 | VER="$( findVarValue web3jVersion )"
12 |
13 | read -r -d '' TWEET << EndOfMessage
14 | I updated web3j-scala to match upstream (web3j v$VER).
15 | web3j-scala supports Scala 2.12 and 2.13.
16 |
17 | https://github.com/mslinn/web3j-scala
18 |
19 | #web3j #ethereum #Scala
20 | EndOfMessage
21 |
22 | echo "$TWEET"
23 |
--------------------------------------------------------------------------------
/bin/web3j:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Sample usage:
4 | # bin/web3j -j
5 | #
6 | # -j option forces rebuild of jar
7 |
8 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/.."
9 | cd "$DIR" || exit 1
10 |
11 | # Scan build.sbt for program name, Scala version and program version
12 | function findValue {
13 | grep "$1 :=" build.sbt | cut -d' ' -f 3 | tr -d \"
14 | }
15 |
16 | SCALA_VERSION() {
17 | V=$( findValue scalaVersion )
18 | case $V in
19 | 2.10.*) echo 2.10 ;;
20 | 2.11.*) echo 2.11 ;;
21 | 2.12.*) echo 2.12 ;;
22 | 2.13.*) echo 2.13 ;;
23 | 3.0.*) echo 3.0 ;;
24 | 3.1.*) echo 3.1 ;;
25 | *) echo UNKNOWN ;;
26 | esac
27 | }
28 |
29 | NAME="$( findValue name )"
30 | VERSION="$( findValue version )"
31 | JAR=target/scala-$(SCALA_VERSION)/$NAME-assembly-$VERSION.jar
32 |
33 | if [ "$1" == -j ] || [ ! -f "${JAR}" ]; then
34 | echo "Building $JAR"
35 | sbt assembly
36 |
37 | if [ "$1" == -j ]; then shift; fi
38 | fi
39 |
40 | java -cp "$JAR" org.web3j.console.Runner "$@"
41 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | val web3jVersion = "4.5.17"
2 |
3 | cancelable := true
4 |
5 | // Travis can be a PITA
6 | crossScalaVersions := { if (new java.io.File("/home/travis").exists) Seq("2.13.1") else Seq("2.12.10", "2.13.1") }
7 |
8 | fork in Test := true
9 |
10 | // define the statements initially evaluated when entering 'console', 'console-quick', but not 'console-project'
11 | initialCommands in console := """import scala.sys.process._
12 | |import java.math.BigInteger
13 | |import java.util.concurrent.Future
14 | |import org.web3j.protocol._
15 | |import org.web3j.protocol.infura._
16 | |""".stripMargin
17 |
18 | javacOptions ++= Seq(
19 | "-Xlint:deprecation",
20 | "-Xlint:unchecked",
21 | "-source", "1.8",
22 | "-target", "1.8",
23 | "-g:vars"
24 | )
25 |
26 | libraryDependencies ++= Seq(
27 | "org.scala-lang.modules" %% "scala-collection-compat" % "2.1.3" withSources(),
28 | // See https://docs.web3j.io/modules.html
29 | "org.web3j" % "abi" % web3jVersion withSources(), // Application Binary Interface encoders
30 | "org.web3j" % "codegen" % web3jVersion withSources(), // Code generators
31 | //"org.web3j" % "console" % web3jVersion withSources(), // Command-line tools
32 | "org.web3j" % "core" % web3jVersion withSources(),
33 | // "org.web3j" % "crypto" % web3jVersion withSources(), // For transaction signing and key/wallet management
34 | "org.web3j" % "geth" % web3jVersion withSources(), // Geth-specific JSON-RPC module
35 | "org.web3j" % "infura" % "4.2.0" withSources(), // Infura-specific HTTP header support
36 | "org.web3j" % "parity" % web3jVersion withSources(), // Parity-specific JSON-RPC module
37 | // "org.web3j" % "quorum" % "0.7.0" withSources(), // integration with JP Morgan's Quorum
38 | "org.web3j" % "rlp" % web3jVersion withSources(), // Recursive Length Prefix (RLP) encoders
39 | "org.web3j" % "utils" % web3jVersion withSources(), // Minimal set of utility classes
40 | "org.web3j" % "web3j-maven-plugin" % "0.3.5" withSources(), // Create Java classes from solidity contract files
41 | //
42 | "org.scala-lang.modules" %% "scala-java8-compat" % "0.9.0",
43 | "ch.qos.logback" % "logback-classic" % "1.2.3",
44 | //
45 | "org.scalatest" %% "scalatest" % "3.0.8" % Test withSources(),
46 | "junit" % "junit" % "4.12" % Test
47 | )
48 |
49 | libraryDependencies ++= { // Newer versions of Java have had the runtime library reduced, so include missing Java dependencies
50 | sys.props("java.version") match {
51 | case jv if jv.startsWith("11") =>
52 | javacOptions += "-J--add-modules=java.xml.bind"
53 | Seq(
54 | "javax.xml.bind" % "jaxb-api" % "2.3.1"
55 | )
56 |
57 | case _ => Nil
58 | }}
59 |
60 | licenses += ("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0.html"))
61 |
62 | logLevel := Level.Warn
63 |
64 | // Only show warnings and errors on the screen for compilations.
65 | // This applies to both test:compile and compile and is Info by default
66 | logLevel in compile := Level.Warn
67 |
68 | // Level.INFO is needed to see detailed output when running tests
69 | logLevel in test := Level.Info
70 |
71 | name := "web3j-scala"
72 |
73 | organization := "com.micronautics"
74 |
75 | resolvers ++= Seq(
76 | "Ethereum Maven" at "https://dl.bintray.com/ethereum/maven/",
77 | "bintray" at "https://bintray.com/web3j/maven/org.web3j",
78 | //"Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
79 | )
80 |
81 | scalacOptions ++= Seq( // From https://tpolecat.github.io/2017/04/25/scalac-flags.html
82 | "-deprecation", // Emit warning and location for usages of deprecated APIs.
83 | "-encoding", "utf-8", // Specify character encoding used by source files.
84 | "-explaintypes", // Explain type errors in more detail.
85 | "-feature", // Emit warning and location for usages of features that should be imported explicitly.
86 | "-language:existentials", // Existential types (besides wildcard types) can be written and inferred
87 | "-language:experimental.macros", // Allow macro definition (besides implementation and application)
88 | "-language:higherKinds", // Allow higher-kinded types
89 | "-language:implicitConversions", // Allow definition of implicit functions called views
90 | "-unchecked", // Enable additional warnings where generated code depends on assumptions.
91 | "-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
92 | "-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
93 | "-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
94 | "-Xlint:delayedinit-select", // Selecting member of DelayedInit.
95 | "-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element.
96 | "-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`.
97 | "-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id.
98 | "-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
99 | "-Xlint:nullary-unit", // Warn when nullary methods return Unit.
100 | "-Xlint:option-implicit", // Option.apply used implicit view.
101 | "-Xlint:package-object-classes", // Class or object defined in package object.
102 | "-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds.
103 | "-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field.
104 | "-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component.
105 | "-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope.
106 | )
107 |
108 | // The REPL can’t cope with -Ywarn-unused:imports or -Xfatal-warnings so turn them off for the console
109 | scalacOptions in (Compile, console) --= Seq("-Ywarn-unused:imports", "-Xfatal-warnings")
110 |
111 | scalacOptions in (Compile, doc) ++= baseDirectory.map { bd: File =>
112 | Seq[String](
113 | "-sourcepath", bd.getAbsolutePath,
114 | "-doc-source-url", "https://github.com/mslinn/web3j-scala/tree/master€{FILE_PATH}.scala"
115 | )
116 | }.value
117 |
118 | scalaVersion := "2.13.1"
119 |
120 | unmanagedSourceDirectories in Test ++= Seq(
121 | baseDirectory.value / "abiWrapper",
122 | baseDirectory.value / "demo"
123 | )
124 |
125 | version := web3jVersion
126 |
--------------------------------------------------------------------------------
/core-4.5.16.pom:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 | org.web3j
6 | core
7 | 4.5.16
8 | web3j
9 | web3j is a lightweight Java library for integration with Ethereum clients
10 | https://web3j.io
11 |
12 |
13 | The Apache License, Version 2.0
14 | http://www.apache.org/licenses/LICENSE-2.0.txt
15 |
16 |
17 |
18 |
19 | conor10
20 | Conor Svensson
21 | conor10@gmail.com
22 |
23 |
24 | antonydenyer
25 | Antony Denyer
26 | antony@web3labs.com
27 |
28 |
29 |
30 | scm:https://github.com/web3j/web3j.git
31 | scm:git://github.com/web3j/web3j.git
32 | https://github.com/web3j/web3j
33 |
34 |
35 |
36 | org.web3j
37 | abi
38 | 4.5.16
39 | compile
40 |
41 |
42 | org.web3j
43 | crypto
44 | 4.5.16
45 | compile
46 |
47 |
48 | org.web3j
49 | tuples
50 | 4.5.16
51 | compile
52 |
53 |
54 | com.github.jnr
55 | jnr-unixsocket
56 | 0.21
57 | compile
58 |
59 |
60 | com.squareup.okhttp3
61 | okhttp
62 | 4.3.1
63 | compile
64 |
65 |
66 | com.squareup.okhttp3
67 | logging-interceptor
68 | 4.3.1
69 | compile
70 |
71 |
72 | io.reactivex.rxjava2
73 | rxjava
74 | 2.2.2
75 | compile
76 |
77 |
78 | org.java-websocket
79 | Java-WebSocket
80 | 1.3.8
81 | compile
82 |
83 |
84 | com.fasterxml.jackson.core
85 | jackson-databind
86 | 2.8.5
87 | compile
88 |
89 |
90 | org.slf4j
91 | slf4j-api
92 | 1.7.25
93 | compile
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/demo/Demo.scala:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | import java.math.BigInteger
4 | import com.micronautics.web3j.{Cmd, Ether, EthereumSynchronous, Web3JScala}
5 | import Cmd.{isMac, isWindows}
6 | import org.web3j.protocol.Web3j
7 | import org.web3j.protocol.ipc.{UnixIpcService, WindowsIpcService}
8 | import scala.concurrent.duration.Duration
9 | import scala.concurrent.{Await, ExecutionContext, Promise}
10 | import org.web3j.protocol.core.DefaultBlockParameterName._
11 |
12 | object Demo {
13 | val gasPrice: Ether = Ether(1)
14 | val gasLimit: BigInteger = BigInt(2).bigInteger
15 |
16 | val walletDir: String = Cmd.home(
17 | if (isWindows) s"${ sys.props("user.home") }\\AppData\\Roaming\\Ethereum\\"
18 | else if (isMac) "~/Library/Ethereum/"
19 | else "~/.ethereum/"
20 | )
21 | }
22 |
23 | class Demo(implicit ec: ExecutionContext) {
24 | // Setup for running command lines from Scala
25 | val cmd = new Cmd()
26 |
27 | // Instantiate an instance of the underlying Web3J library:
28 | val web3j: Web3j = Web3JScala.fromHttp() // defaults to http://localhost:8545/
29 | val web3jScala: Web3JScala = new Web3JScala(web3j)
30 |
31 | // Example of a synchronous request:
32 | val web3ClientVersion1: String = web3jScala.sync.versionWeb3J
33 | println(s"Web3J version = $web3ClientVersion1")
34 |
35 | // Contrived example of an asynchronous request, which provides no benefit over using a synchronous request:
36 | val web3ClientVersion2: String = Await.result(web3jScala.async.versionWeb3J, Duration.Inf)
37 | println(s"Web3J version = $web3ClientVersion2")
38 |
39 | // Better example of an asynchronous request:
40 | private val promise: Promise[String] = Promise[String]
41 | web3jScala.async.versionWeb3J.foreach { web3ClientVersion =>
42 | println(s"Web3J version = $web3ClientVersion")
43 | promise.complete(scala.util.Success("Done"))
44 | }
45 | Await.ready(promise.future, Duration.Inf) // pause while the async request completes
46 |
47 | val eSync: EthereumSynchronous = web3jScala.sync
48 | eSync.accounts match {
49 | case Nil => println("No accounts found.")
50 | case accounts =>
51 | accounts.foreach {
52 | account => println(s"The balance of $account is ${ eSync.balance(account, LATEST) } Wei")
53 | }
54 | }
55 |
56 | val ethereumDir: String = Cmd.home(
57 | if (isWindows) "~/AppData/Roaming/Ethereum"
58 | else if (isMac) "~/Library/Ethereum/"
59 | else "~/.ethereum/"
60 | ) + "devnet/" // todo discover the ethereum name at runtime
61 |
62 | // Web3J supports fast inter-process communication (IPC) via file sockets to clients running on the same host as Web3J.
63 | // To connect simply use the relevant IpcService implementation instead of HttpService when you create your service:
64 | val web3J3: Web3j = try {
65 | if (isWindows)
66 | Web3j.build(new WindowsIpcService(ethereumDir))
67 | else
68 | Web3j.build(new UnixIpcService(ethereumDir + "geth.ipc"))
69 | } catch {
70 | case e: Throwable =>
71 | System.err.println(e.getMessage)
72 | web3j
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/demo/DemoObservables.scala:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | import com.micronautics.web3j._
4 | import com.micronautics.web3j.Web3JScala._
5 | import org.web3j.protocol.core.DefaultBlockParameterName._
6 | import org.web3j.protocol.core.methods.{request, response}
7 |
8 | /** Web3J's functional-reactive nature makes it easy to set up observers that notify subscribers of events taking place on the blockchain.
9 | * The functional-reactive programming style works really well with Scala.
10 | *
11 | * Other transaction and block replay [[org.web3j.utils.Flowables]] are described in [[https://docs.web3j.io/filters.html Filters and Events]]. */
12 | class DemoObservables(demo: Demo) {
13 | import demo._
14 |
15 | // Display the first 2 new blocks as they are added to the blockchain:
16 | observe(2)(web3j.blockFlowable(false)) { ethBlock =>
17 | println(format(ethBlock))
18 | }
19 |
20 | // Display only the first 2 new transactions as they are added to the blockchain:
21 | observe(2)(web3j.transactionFlowable) { tx =>
22 | println(format(tx))
23 | }
24 |
25 | // Display the first 2 pending transactions as they are submitted to the network, before they have been grouped into a block:
26 | observe(2)(web3j.pendingTransactionFlowable) { tx =>
27 | println(format(tx))
28 | }
29 |
30 | // Replay all blocks to the most current, and be notified of new subsequent blocks being created
31 | // Display minimal information about old blocks, show detailed information for new blocks
32 | val now: Long = System.currentTimeMillis
33 | var count = 0
34 | web3j.replayPastAndFutureBlocksFlowable(EARLIEST, false).subscribe { ethBlock =>
35 | val block = ethBlock.getBlock
36 | if (block.getTimestamp.longValue
58 | println(format(log))
59 | }
60 |
61 |
62 | protected def format(ethBlock: response.EthBlock): String = {
63 | val block = ethBlock.getBlock
64 | s"""ETH block:
65 | | Author = ${ block.getAuthor }
66 | | Bloom logs = ${ block.getLogsBloom }
67 | | Difficulty = ${ block.getDifficulty }
68 | | Extra data = ${ block.getExtraData }
69 | | Gas limit = ${ block.getGasLimit }
70 | | Gas used = ${ block.getGasUsed }
71 | | Hash = ${ block.getHash }
72 | | Java time = ${ block.javaTime }
73 | | Miner = ${ block.getMiner }
74 | | Mix hash = ${ block.getMixHash }
75 | | Nonce = ${ block.getNonce }
76 | | Number = ${ block.getNumber }
77 | | Parent hash = ${ block.getParentHash }
78 | | Receipts root = ${ block.getReceiptsRoot }
79 | | Seal fields = ${ block.getSealFields }
80 | | SHA3 uncles = ${ block.getSha3Uncles }
81 | | Size = ${ block.getSize }
82 | | State root = ${ block.getStateRoot }
83 | | Timestamp = ${ block.getTimestamp }
84 | | Transactions.size = ${ block.getTransactions.size }
85 | | Transactions root = ${ block.getTransactionsRoot }
86 | | Uncles = ${ block.getUncles }
87 | | Raw difficulty = ${ block.getDifficultyRaw }
88 | | Raw gas limit = ${ block.getGasLimitRaw }
89 | | Raw gas used = ${ block.getGasUsedRaw }
90 | | Raw nonce = ${ block.getNonceRaw }
91 | | Raw number = ${ block.getNumberRaw }
92 | | Raw size = ${ block.getSizeRaw }
93 | | Raw timestamp = ${ block.getTimestampRaw}
94 | | Total difficulty = ${ block.getTotalDifficulty }
95 | | Raw total difficulty = ${ block.getTotalDifficultyRaw }
96 | |""".stripMargin
97 | }
98 |
99 | protected def format(log: response.Log): String =
100 | s"""Response Log:
101 | | Address = ${ log.getAddress }
102 | | Block hash = ${ log.getBlockHash }
103 | | Block number = ${ log.getBlockNumber }
104 | | Data = ${ log.getData }
105 | | Log index = ${ log.getLogIndex }
106 | | Topics = ${ log.getTopics }
107 | | Transaction hash = ${ log.getTransactionHash }
108 | | Transaction index = ${ log.getTransactionIndex }
109 | | Type = ${ log.getType }
110 | | Removed = ${ log.isRemoved }
111 | | Raw block number = ${ log.getBlockNumberRaw }
112 | | Raw log index = ${ log.getLogIndexRaw }
113 | | Raw transaction index = ${ log.getTransactionIndexRaw }
114 | |""".stripMargin
115 |
116 | protected def format(tx: response.Transaction): String =
117 | s"""Transaction:
118 | | Block hash = ${ tx.getBlockHash }
119 | | Block number = ${ tx.getBlockNumber }
120 | | Block number raw = ${ tx.getBlockNumberRaw }
121 | | Creates = ${ tx.getCreates }
122 | | From = ${ tx.getFrom }
123 | | Gas = ${ tx.getGas }
124 | | Gas price = ${ tx.getGasPrice }
125 | | Hash = ${ tx.getHash }
126 | | Input = ${ tx.getInput }
127 | | Nonce = ${ tx.getNonce }
128 | | Public key = ${ tx.getPublicKey }
129 | | R = ${ tx.getR }
130 | | To = ${ tx.getTo }
131 | | Transaction index = ${ tx.getTransactionIndex }
132 | | V = ${ tx.getV }
133 | | Value = ${ tx.getValue }
134 | | Raw = ${ tx.getRaw }
135 | | Raw gas = ${ tx.getGasRaw }
136 | | Raw gas price = ${ tx.getGasPriceRaw }
137 | | Raw nonce = ${ tx.getNonceRaw }
138 | | Raw transaction index = ${ tx.getTransactionIndexRaw }
139 | | Raw value = ${ tx.getValueRaw }
140 | |""".stripMargin
141 | }
142 |
--------------------------------------------------------------------------------
/demo/DemoSmartContracts.scala:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | import org.web3j.crypto.{Credentials, WalletUtils}
4 | import org.web3j.protocol.core.RemoteCall
5 |
6 | object CreateSmartContracts extends App {
7 | import scala.concurrent.ExecutionContext.Implicits.global
8 |
9 | new DemoSmartContracts(new Demo)
10 | }
11 |
12 | /** Web3J can auto-generate smart contract wrapper code to deploy and interact with smart contracts without leaving the JVM.
13 | * This program creates a smart contract wrapper around a [[../src/test/resources/basic_info_getter.sol sample smart contract]]
14 | * and demonstrates how to work with smart contracts using JVM wrappers.
15 | *
16 | * Run this program before [[Main running the demo]].
17 | *
18 | * @see See [[https://web3j.readthedocs.io/en/latest/smart_contracts.html Web3J Smart Contracts]] */
19 | class DemoSmartContracts(demo: Demo) {
20 | import com.micronautics.web3j.Web3JScala.{solc,wrapAbi}
21 | import com.micronautics.solidity._
22 | import Demo._
23 |
24 | // Compile the smart contract before generating the wrapper code
25 | println(solc("src/test/resources/basic_info_getter.sol"))
26 | println(wrapAbi("basic_info_getter"))
27 |
28 | try {
29 | val credentials: Credentials = WalletUtils.loadCredentials("password", walletDir)
30 |
31 | val basicInfoGetter: RemoteCall[BasicInfoGetter] = BasicInfoGetter.deploy(demo.web3j, credentials, gasPrice.bigInteger, gasLimit)
32 | val x: BasicInfoGetter = basicInfoGetter.send
33 | println(x)
34 |
35 | // Or use an existing contract:
36 | // val contract2 = YourSmartContract.load( "0x", web3j, credentials, gasPrice, gasLimit)
37 |
38 | // Transact with a smart contract
39 | // val result = basicInfoGetter.send().getContractAddress.send()
40 | // println(s"basicInfoGetter.getContractAddress = $result")
41 | } catch {
42 | case e: Throwable =>
43 | System.err.println(e.getMessage)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/demo/DemoTransaction.scala:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | import java.math.BigInteger
4 | import com.micronautics.web3j.{Address, Nonce}
5 | import org.web3j.crypto.{Credentials, RawTransaction, TransactionEncoder, WalletUtils}
6 | import org.web3j.protocol.admin.Admin
7 | import org.web3j.protocol.admin.methods.response.PersonalUnlockAccount
8 | import org.web3j.protocol.core.DefaultBlockParameterName._
9 | import org.web3j.protocol.core.methods.response.TransactionReceipt
10 | import org.web3j.protocol.http.HttpService
11 | import org.web3j.tx.Transfer
12 | import org.web3j.utils.Convert.Unit.{ETHER, WEI}
13 |
14 | /** Web3J provides support for both working with Ethereum wallet files (recommended) and Ethereum client admin commands
15 | * for sending transactions. */
16 | class DemoTransaction(demo: Demo) {
17 | import Demo._, demo._
18 |
19 | // Send Ether to another party using your Ethereum wallet file
20 | val credentials: Credentials = WalletUtils.loadCredentials("password", walletDir)
21 | val transactionReceipt: TransactionReceipt =
22 | Transfer.sendFunds(web3j, credentials, "0x...", BigDecimal.valueOf(0.01).bigDecimal, ETHER).send
23 | println(format(transactionReceipt))
24 |
25 | // Before creating a custom transaction, first get the next available nonce
26 | val nonce: Nonce = demo.web3jScala.sync.nextNonce(Address("address"))
27 |
28 | // Create a custom transaction
29 | val rawTransaction: RawTransaction =
30 | RawTransaction.createEtherTransaction(nonce.bigInteger, gasPrice.bigInteger, gasLimit, "toAddress", BigInt(1).bigInteger)
31 | println(format(rawTransaction))
32 |
33 | // Sign & send the transaction
34 | val signedMessage: Array[Byte] = TransactionEncoder.signMessage(rawTransaction, credentials)
35 | val hexValue: String = javax.xml.bind.DatatypeConverter.printHexBinary(signedMessage)
36 | val transactionHash: String = web3j.ethSendRawTransaction(hexValue).send.getTransactionHash
37 |
38 | // Now let's transfer some funds. Be sure a wallet is available in the client’s keystore. TODO how?
39 | // One option is to use web3j’s `Transfer` class for transacting with Ether.
40 | Transfer.sendFunds(web3j, credentials, "toAddress", BigDecimal(1).bigDecimal, WEI)
41 |
42 | // Here is how to use the Ethereum client’s admin commands:
43 | val web3jAdmin: Admin = Admin.build(new HttpService)
44 | val personalUnlockAccount: PersonalUnlockAccount = web3jAdmin.personalUnlockAccount("0x000...", "a password").sendAsync.get
45 | if (personalUnlockAccount.accountUnlocked) {
46 | // todo send a transaction
47 | }
48 |
49 | // Todo demonstrate the use of Parity’s Personal, Trace, or geth’s personal client APIs, by using the org.web3j:parity and org.web3j:geth modules respectively.
50 |
51 | protected def format(tx: RawTransaction): String =
52 | s"""Raw transaction:
53 | | Data = ${ tx.getData }
54 | | Gas limit = ${ tx.getGasLimit }
55 | | Gas price = ${ tx.getGasPrice }
56 | | Gas limit = ${ tx.getGasLimit }
57 | | Nonce = ${ tx.getNonce }
58 | | To = ${ tx.getTo }
59 | | Value = ${ tx.getValue }
60 | |""".stripMargin
61 |
62 | protected def format(tx: TransactionReceipt): String =
63 | s"""Transaction receipt:
64 | | Block hash = ${ tx.getBlockHash }
65 | | Block number = ${ tx.getBlockNumber }
66 | | Raw block number = ${ tx.getBlockNumberRaw }
67 | | Contract address = ${ tx.getContractAddress }
68 | | Cumulative gas used = ${ tx.getCumulativeGasUsed }
69 | | Raw cumulative gas used = ${ tx.getCumulativeGasUsedRaw }
70 | | From = ${ tx.getFrom }
71 | | Gas used = ${ tx.getGasUsed }
72 | | Raw gas used = ${ tx.getGasUsedRaw }
73 | | Logs = ${ tx.getLogs }
74 | | Log bloom = ${ tx.getLogsBloom }
75 | | Root = ${ tx.getRoot }
76 | | To = ${ tx.getTo }
77 | | Transaction hash = ${ tx.getTransactionHash }
78 | | Transaction index = ${ tx.getTransactionIndex }
79 | | Raw transaction index = ${ tx.getTransactionIndexRaw }
80 | |""".stripMargin
81 | }
82 |
--------------------------------------------------------------------------------
/demo/Main.scala:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | /** Adapted from [[https://docs.web3j.io/getting_started.html#start-a-client Web3J Getting Started]].
4 | *
5 | * 1. Before running this program, start up an Ethereum client if you don’t already have one running, such as `geth`:
6 | * {{{$ geth --rpcapi personal,db,eth,net,web3 --rpc --rinkeby --ipcpath "geth.ipc"}}}
7 | *
8 | * 2. Create the smart contract JVM wrapper by running `CreateSmartContracts` defined in `demo/DemoSmartContracts.scala`:
9 | * {{{$ sbt "test:runMain demo.CreateSmartContracts"}}}
10 | *
11 | * 3. Run this program by typing the following at a shell prompt:
12 | * {{{$ sbt "test:runMain demo.Main"}}} */
13 | object Main extends App {
14 | import scala.concurrent.ExecutionContext.Implicits.global
15 |
16 | val demo = new Demo
17 | new DemoObservables(demo)
18 | new DemoSmartContracts(demo)
19 | new DemoTransaction(demo)
20 | }
21 |
--------------------------------------------------------------------------------
/geth.md:
--------------------------------------------------------------------------------
1 | ```
2 | $ geth -h
3 | NAME:
4 | geth - the go-ethereum command line interface
5 |
6 | Copyright 2013-2017 The go-ethereum Authors
7 |
8 | USAGE:
9 | geth [options] command [command options] [arguments...]
10 |
11 | VERSION:
12 | 1.7.3-unstable-9619a610
13 |
14 | COMMANDS:
15 | account Manage accounts
16 | attach Start an interactive JavaScript environment (connect to node)
17 | bug opens a window to report a bug on the geth repo
18 | console Start an interactive JavaScript environment
19 | copydb Create a local chain from a target chaindata folder
20 | dump Dump a specific block from storage
21 | dumpconfig Show configuration values
22 | export Export blockchain into file
23 | import Import a blockchain file
24 | init Bootstrap and initialize a new genesis block
25 | js Execute the specified JavaScript files
26 | license Display license information
27 | makecache Generate ethash verification cache (for testing)
28 | makedag Generate ethash mining DAG (for testing)
29 | monitor Monitor and visualize node metrics
30 | removedb Remove blockchain and state databases
31 | version Print version numbers
32 | wallet Manage Ethereum presale wallets
33 | help, h Shows a list of commands or help for one command
34 |
35 | ETHEREUM OPTIONS:
36 | --config value TOML configuration file
37 | --datadir "/home/mslinn/.ethereum" Data directory for the databases and keystore
38 | --keystore Directory for the keystore (default = inside the datadir)
39 | --nousb Disables monitoring for and managing USB hardware wallets
40 | --networkid value Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby) (default: 1)
41 | --testnet Ropsten network: pre-configured proof-of-work test network
42 | --rinkeby Rinkeby network: pre-configured proof-of-authority test network
43 | --syncmode "fast" Blockchain sync mode ("fast", "full", or "light")
44 | --ethstats value Reporting URL of a ethstats service (nodename:secret@host:port)
45 | --identity value Custom node name
46 | --lightserv value Maximum percentage of time allowed for serving LES requests (0-90) (default: 0)
47 | --lightpeers value Maximum number of LES client peers (default: 20)
48 | --lightkdf Reduce key-derivation RAM & CPU usage at some expense of KDF strength
49 |
50 | DEVELOPER CHAIN OPTIONS:
51 | --dev Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled
52 | --dev.period value Block period to use in developer mode (0 = mine only if transaction pending) (default: 0)
53 |
54 | ETHASH OPTIONS:
55 | --ethash.cachedir Directory to store the ethash verification caches (default = inside the datadir)
56 | --ethash.cachesinmem value Number of recent ethash caches to keep in memory (16MB each) (default: 2)
57 | --ethash.cachesondisk value Number of recent ethash caches to keep on disk (16MB each) (default: 3)
58 | --ethash.dagdir "/home/mslinn/.ethash" Directory to store the ethash mining DAGs (default = inside home folder)
59 | --ethash.dagsinmem value Number of recent ethash mining DAGs to keep in memory (1+GB each) (default: 1)
60 | --ethash.dagsondisk value Number of recent ethash mining DAGs to keep on disk (1+GB each) (default: 2)
61 |
62 | TRANSACTION POOL OPTIONS:
63 | --txpool.nolocals Disables price exemptions for locally submitted transactions
64 | --txpool.journal value Disk journal for local transaction to survive node restarts (default: "transactions.rlp")
65 | --txpool.rejournal value Time interval to regenerate the local transaction journal (default: 1h0m0s)
66 | --txpool.pricelimit value Minimum gas price limit to enforce for acceptance into the pool (default: 1)
67 | --txpool.pricebump value Price bump percentage to replace an already existing transaction (default: 10)
68 | --txpool.accountslots value Minimum number of executable transaction slots guaranteed per account (default: 16)
69 | --txpool.globalslots value Maximum number of executable transaction slots for all accounts (default: 4096)
70 | --txpool.accountqueue value Maximum number of non-executable transaction slots permitted per account (default: 64)
71 | --txpool.globalqueue value Maximum number of non-executable transaction slots for all accounts (default: 1024)
72 | --txpool.lifetime value Maximum amount of time non-executable transaction are queued (default: 3h0m0s)
73 |
74 | PERFORMANCE TUNING OPTIONS:
75 | --cache value Megabytes of memory allocated to internal caching (min 16MB / database forced) (default: 128)
76 | --trie-cache-gens value Number of trie node generations to keep in memory (default: 120)
77 |
78 | ACCOUNT OPTIONS:
79 | --unlock value Comma separated list of accounts to unlock
80 | --password value Password file to use for non-interactive password input
81 |
82 | API AND CONSOLE OPTIONS:
83 | --rpc Enable the HTTP-RPC server
84 | --rpcaddr value HTTP-RPC server listening interface (default: "localhost")
85 | --rpcport value HTTP-RPC server listening port (default: 8545)
86 | --rpcapi value API's offered over the HTTP-RPC interface
87 | --ws Enable the WS-RPC server
88 | --wsaddr value WS-RPC server listening interface (default: "localhost")
89 | --wsport value WS-RPC server listening port (default: 8546)
90 | --wsapi value API's offered over the WS-RPC interface
91 | --wsorigins value Origins from which to accept websockets requests
92 | --ipcdisable Disable the IPC-RPC server
93 | --ipcpath Filename for IPC socket/pipe within the datadir (explicit paths escape it)
94 | --rpccorsdomain value Comma separated list of domains from which to accept cross origin requests (browser enforced)
95 | --jspath loadScript JavaScript root path for loadScript (default: ".")
96 | --exec value Execute JavaScript statement
97 | --preload value Comma separated list of JavaScript files to preload into the console
98 |
99 | NETWORKING OPTIONS:
100 | --bootnodes value Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)
101 | --bootnodesv4 value Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)
102 | --bootnodesv5 value Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)
103 | --port value Network listening port (default: 30303)
104 | --maxpeers value Maximum number of network peers (network disabled if set to 0) (default: 25)
105 | --maxpendpeers value Maximum number of pending connection attempts (defaults used if set to 0) (default: 0)
106 | --nat value NAT port mapping mechanism (any|none|upnp|pmp|extip:) (default: "any")
107 | --nodiscover Disables the peer discovery mechanism (manual peer addition)
108 | --v5disc Enables the experimental RLPx V5 (Topic Discovery) mechanism
109 | --netrestrict value Restricts network communication to the given IP networks (CIDR masks)
110 | --nodekey value P2P node key file
111 | --nodekeyhex value P2P node key as hex (for testing)
112 |
113 | MINER OPTIONS:
114 | --mine Enable mining
115 | --minerthreads value Number of CPU threads to use for mining (default: 8)
116 | --etherbase value Public address for block mining rewards (default = first account created) (default: "0")
117 | --targetgaslimit value Target gas limit sets the artificial target gas floor for the blocks to mine (default: 4712388)
118 | --gasprice "18000000000" Minimal gas price to accept for mining a transactions
119 | --extradata value Block extra data set by the miner (default = client version)
120 |
121 | GAS PRICE ORACLE OPTIONS:
122 | --gpoblocks value Number of recent blocks to check for gas prices (default: 10)
123 | --gpopercentile value Suggested gas price is the given percentile of a set of recent transaction gas prices (default: 50)
124 |
125 | VIRTUAL MACHINE OPTIONS:
126 | --vmdebug Record information useful for VM and contract debugging
127 |
128 | LOGGING AND DEBUGGING OPTIONS:
129 | --metrics Enable metrics collection and reporting
130 | --fakepow Disables proof-of-work verification
131 | --nocompaction Disables db compaction after import
132 | --verbosity value Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail (default: 3)
133 | --vmodule value Per-module verbosity: comma-separated list of = (e.g. eth/*=5,p2p=4)
134 | --backtrace value Request a stack trace at a specific logging statement (e.g. "block.go:271")
135 | --debug Prepends log messages with call-site location (file and line number)
136 | --pprof Enable the pprof HTTP server
137 | --pprofaddr value pprof HTTP server listening interface (default: "127.0.0.1")
138 | --pprofport value pprof HTTP server listening port (default: 6060)
139 | --memprofilerate value Turn on memory profiling with the given rate (default: 524288)
140 | --blockprofilerate value Turn on block profiling with the given rate (default: 0)
141 | --cpuprofile value Write CPU profile to the given file
142 | --trace value Write execution trace to the given file
143 |
144 | WHISPER (EXPERIMENTAL) OPTIONS:
145 | --shh Enable Whisper
146 | --shh.maxmessagesize value Max message size accepted (default: 1048576)
147 | --shh.pow value Minimum POW accepted (default: 0.2)
148 |
149 | DEPRECATED OPTIONS:
150 | --fast Enable fast syncing through state downloads
151 | --light Enable light client mode
152 |
153 | MISC OPTIONS:
154 | --help, -h show help
155 |
156 |
157 | COPYRIGHT:
158 | Copyright 2013-2017 The go-ethereum Authors
159 | ```
160 |
--------------------------------------------------------------------------------
/logos/repository-open-graph-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mslinn/web3j-scala/d93644861655c27446858d638d53c63007699211/logos/repository-open-graph-template.png
--------------------------------------------------------------------------------
/logos/repository-open-graph.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mslinn/web3j-scala/d93644861655c27446858d638d53c63007699211/logos/repository-open-graph.ai
--------------------------------------------------------------------------------
/logos/repository-open-graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mslinn/web3j-scala/d93644861655c27446858d638d53c63007699211/logos/repository-open-graph.png
--------------------------------------------------------------------------------
/logos/web3j-orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mslinn/web3j-scala/d93644861655c27446858d638d53c63007699211/logos/web3j-orange.png
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.3.9
2 |
--------------------------------------------------------------------------------
/project/build.sbt:
--------------------------------------------------------------------------------
1 | libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
2 |
--------------------------------------------------------------------------------
/project/ghpages.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.4.0")
2 | addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.6.3")
3 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | // See https://github.com/rtimush/sbt-updates
2 | addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.5.0")
3 |
4 | // See https://github.com/sbt/sbt-assembly
5 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")
6 |
7 | // See https://github.com/sbt/sbt-bintray
8 | resolvers += Resolver.jcenterRepo
9 | addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.6")
10 |
11 | // See https://github.com/ThoughtWorksInc/sbt-api-mappings
12 | addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "3.0.0")
13 |
--------------------------------------------------------------------------------
/publish.sbt:
--------------------------------------------------------------------------------
1 | import scala.sys.process._
2 |
3 | lazy val scaladoc =
4 | taskKey[Unit]("Rebuilds the Scaladoc and pushes the updated Scaladoc to GitHub pages without committing to the git repository")
5 |
6 | scaladoc := {
7 | println("Creating Scaladoc")
8 | doc.in(Test).value
9 |
10 | println("Uploading Scaladoc to GitHub Pages")
11 | ghpagesPushSite.value
12 | }
13 |
14 | /** Best practice is to comment your commits before invoking this task: `git commit -am "Your comment here"`.
15 | * This task does the following:
16 | * 1. `git pull` when it starts.
17 | * 2. Attempts to build Scaladoc, which fails if there is a compile error
18 | * 3. Ensures any uncommitted changes are committed before publishing, including new files; it provides the comment as "-".
19 | * 4. Git pushes all files
20 | * 5. Uploads new Scaladoc
21 | * 6. Publishes new version to Bintray */
22 | lazy val commitAndDoc =
23 | taskKey[Unit]("Rebuilds the docs, commits the git repository, and publishes the updated Scaladoc without publishing a new version")
24 |
25 | commitAndDoc := {
26 | try {
27 | println("Fetching latest updates for this git repo")
28 | "git pull".!!
29 |
30 | println("Creating Scaladoc")
31 | doc.in(Test).value
32 |
33 | val changedFileNames: String = "git diff --name-only".!!.trim.replace("\n", ", ")
34 | if (changedFileNames.nonEmpty) {
35 | println(s"About to commit these changed files: $changedFileNames")
36 | "git add -A".!!
37 | "git commit -m -".!!
38 | }
39 |
40 | /*val stagedFileNames = "git diff --cached --name-only".!!.trim.replace("\n", ", ")
41 | if (stagedFileNames.nonEmpty) {
42 | println(s"About to push these staged files: $stagedFileNames")
43 | }*/
44 |
45 | println("About to git push to origin")
46 | "git push origin HEAD".!! // See https://stackoverflow.com/a/20922141/553865
47 |
48 | println("Uploading Scaladoc to GitHub Pages")
49 | ghpagesPushSite.value
50 | } catch {
51 | case e: Exception => println(e.getMessage)
52 | }
53 | ()
54 | }
55 |
56 | /** Publish a new version of this library to BinTray.
57 | * Be sure to update the version string in build.sbt before running this task. */
58 | lazy val publishAndTag =
59 | taskKey[Unit]("Invokes commitAndPublish, then creates a git tag for the version string defined in build.sbt")
60 |
61 | publishAndTag := {
62 | commitAndDoc.in(Compile).value
63 | publish.value
64 | println(s"Creating git tag for v${ version.value }")
65 | s"""git tag -a ${ version.value } -m ${ version.value }""".!!
66 | s"""git push origin --tags""".!!
67 | ()
68 | }
69 |
70 | // See http://www.scala-sbt.org/1.0/docs/Howto-Scaladoc.html
71 | autoAPIMappings := true
72 | apiURL := Some(url("https://mslinn.github.io/web3j-scala/latest/api"))
73 |
74 | bintrayOrganization := Some("micronautics")
75 | bintrayRepository := "scala"
76 | bintrayPackage := "web3j-scala"
77 |
78 | // sbt-site settings
79 | enablePlugins(SiteScaladocPlugin)
80 | siteSourceDirectory := target.value / "api"
81 | publishSite
82 |
83 | // sbt-ghpages settings
84 | enablePlugins(GhpagesPlugin)
85 | git.remoteRepo := s"git@github.com:mslinn/${ name.value }.git"
86 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/Cmd.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j
2 |
3 | import java.io.File
4 | import java.nio.file.{Files, Path, Paths}
5 | import java.util.regex.Pattern
6 | import org.slf4j.Logger
7 | import scala.sys.process._
8 |
9 | /** Command-line invocation / process control */
10 | object Cmd {
11 | val logger: Logger = org.slf4j.LoggerFactory.getLogger("gitStats")
12 |
13 | protected lazy val os: String = sys.props("os.name").toLowerCase
14 |
15 | lazy val isWindows: Boolean = os.indexOf("win") >= 0
16 | lazy val isMac: Boolean = os.toLowerCase.startsWith("mac os x")
17 | lazy val isLinux: Boolean = os.toLowerCase.startsWith("linux")
18 |
19 | protected def which(program: String): Option[Path] = {
20 | val path = if (isWindows) sys.env("Path") else sys.env("PATH")
21 | path
22 | .split(Pattern.quote(File.pathSeparator))
23 | .map(Paths.get(_))
24 | .find(path => Files.exists(path.resolve(program)))
25 | .map(_.resolve(program)).orElse(
26 | Paths.get("").resolve(program) match {
27 | case path if Files.exists(path) => Some(path)
28 | case _ => None
29 | }
30 | )
31 | }
32 |
33 | @inline protected def whichOrThrow(program: String): Path =
34 | which(program) match {
35 | case None => sys.error(program + " not found on PATH")
36 | case Some(programPath) => programPath
37 | }
38 |
39 | @inline def home(path: String): String = path.replace("~", sys.props("user.home"))
40 | }
41 |
42 | class Cmd(cwd: File = new File("."), showOutput: Boolean=true, verbose: Boolean=false) {
43 | import Cmd._
44 |
45 | @inline def apply(cmd: String*): ProcessBuilder = {
46 | val command: List[String] = whichOrThrow(cmd(0)).toString :: cmd.tail.toList.map(home)
47 | if (verbose) println(s"[${ cwd.getAbsolutePath }] " + command.mkString(" "))
48 | Process(command=command, cwd=cwd)
49 | }
50 |
51 | @inline def getOutputFrom(cmd: String*): String =
52 | try {
53 | val result = apply(cmd:_*).!!.trim
54 | if (showOutput) println(result)
55 | result
56 | } catch {
57 | case e: Exception =>
58 | Console.err.println(e.getMessage)
59 | if (null!=e.getCause && e.getCause.toString.nonEmpty) Console.err.println(e.getCause)
60 | Console.err.println(e.getStackTrace.mkString("\n"))
61 | sys.exit(-1)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/Ether.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j
2 |
3 | object Ether {
4 | lazy val zero: Ether = Ether(0)
5 |
6 | /** @return a BigInt containing 1 with the given number of zeros after it, e.g. {{{e(3) == BigInt(1000)}}} */
7 | @inline def e(howManyZeros: Int): BigInt = BigInt(s"1${ zeros(howManyZeros) }")
8 |
9 | /** @return a String containing the specified number of zeros, e.g. {{{zeros(3) == "000"}}} */
10 | @inline def zeros(howMany: Int): String = "0" * howMany
11 |
12 | /** @param value unit is wei */
13 | @inline def apply(value: String): Ether = new Ether(BigInt(value))
14 | @inline def apply(value: BigInt): Ether = new Ether(value)
15 | @inline def apply(value: Int): Ether = new Ether(BigInt(value))
16 | @inline def apply(value: Double): Ether = new Ether(BigDecimal(value).bigDecimal.toBigInteger)
17 | @inline def apply(value: BigDecimal): Ether = new Ether(value.bigDecimal.toBigInteger)
18 |
19 | @inline def fromWei(value: String): Ether = Ether(value)
20 | @inline def fromWei(value: Double): Ether = Ether(value)
21 | @inline def fromWei(value: BigDecimal): Ether = Ether(value)
22 | @inline def fromWei(value: Int): Ether = Ether(value)
23 | @inline def fromWei(value: BigInt): Ether = Ether(value)
24 |
25 | @inline def fromKWei(value: String): Ether = Ether(value + zeros(3))
26 | @inline def fromKWei(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(3)))
27 | @inline def fromKWei(value: BigDecimal): Ether = Ether(value * BigDecimal(e(3)))
28 | @inline def fromKWei(value: Int): Ether = Ether(value * e(3))
29 | @inline def fromKWei(value: BigInt): Ether = Ether(value * e(3))
30 |
31 | @inline def fromMWei(value: String): Ether = Ether(value + zeros(6))
32 | @inline def fromMWei(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(6)))
33 | @inline def fromMWei(value: BigDecimal): Ether = Ether(value * BigDecimal(e(6)))
34 | @inline def fromMWei(value: Int): Ether = Ether(value * e(6))
35 | @inline def fromMWei(value: BigInt): Ether = Ether(value * e(6))
36 |
37 | @inline def fromGWei(value: String): Ether = Ether(value + zeros(9))
38 | @inline def fromGWei(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(9)))
39 | @inline def fromGWei(value: BigDecimal): Ether = Ether(value * BigDecimal(e(9)))
40 | @inline def fromGWei(value: Int): Ether = Ether(value * e(9))
41 | @inline def fromGWei(value: BigInt): Ether = Ether(value * e(9))
42 |
43 | @inline def fromSzabo(value: String): Ether = Ether(value + zeros(12))
44 | @inline def fromSzabo(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(12)))
45 | @inline def fromSzabo(value: BigDecimal): Ether = Ether(value * BigDecimal(e(12)))
46 | @inline def fromSzabo(value: Int): Ether = Ether(value * e(12))
47 | @inline def fromSzabo(value: BigInt): Ether = Ether(value * e(12))
48 |
49 | @inline def fromFinney(value: String): Ether = Ether(value + zeros(15))
50 | @inline def fromFinney(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(15)))
51 | @inline def fromFinney(value: BigDecimal): Ether = Ether(value * BigDecimal(e(15)))
52 | @inline def fromFinney(value: Int): Ether = Ether(value * e(15))
53 | @inline def fromFinney(value: BigInt): Ether = Ether(value * e(15))
54 |
55 | @inline def fromEther(value: String): Ether = Ether(value + zeros(18))
56 | @inline def fromEther(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(18)))
57 | @inline def fromEther(value: BigDecimal): Ether = Ether(value * BigDecimal(e(18)))
58 | @inline def fromEther(value: Int): Ether = Ether(value * e(18))
59 | @inline def fromEther(value: BigInt): Ether = Ether(value * e(18))
60 |
61 | @inline def fromKEther(value: String): Ether = Ether(value + zeros(21))
62 | @inline def fromKEther(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(21)))
63 | @inline def fromKEther(value: BigDecimal): Ether = Ether(value * BigDecimal(e(21)))
64 | @inline def fromKEther(value: Int): Ether = Ether(value * e(21))
65 | @inline def fromKEther(value: BigInt): Ether = Ether(value * e(21))
66 |
67 | @inline def fromMEther(value: String): Ether = Ether(value + zeros(24))
68 | @inline def fromMEther(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(24)))
69 | @inline def fromMEther(value: BigDecimal): Ether = Ether(value * BigDecimal(e(24)))
70 | @inline def fromMEther(value: Int): Ether = Ether(value * e(24))
71 | @inline def fromMEther(value: BigInt): Ether = Ether(value * e(24))
72 |
73 | @inline def fromGEther(value: String): Ether = Ether(value + zeros(27))
74 | @inline def fromGEther(value: Double): Ether = Ether(BigDecimal(value) * BigDecimal(e(27)))
75 | @inline def fromGEther(value: BigDecimal): Ether = Ether(value * BigDecimal(e(27)))
76 | @inline def fromGEther(value: Int): Ether = Ether(value * e(27))
77 | @inline def fromGEther(value: BigInt): Ether = Ether(value * e(27))
78 | }
79 |
80 | /** Wei are the smallest unit of currency and are always integers, never fractional quantities */
81 | class Ether(val wei: BigInt) extends Ordered[Ether] {
82 | import Ether._
83 |
84 | @inline def *(value: Ether): Ether = Ether(wei * value.wei)
85 | @inline def *(value: Int): Ether = Ether(wei * value)
86 | @inline def *(value: Double): Ether = Ether(BigDecimal(wei) * value)
87 | @inline def *(value: BigInt): Ether = Ether(value) * wei
88 | @inline def *(value: BigDecimal): Ether = Ether(value) * wei
89 |
90 | @inline def /(value: Ether): Ether = Ether(wei / value.wei)
91 | @inline def /(value: Int): Ether = Ether(wei / value)
92 | @inline def /(value: Double): Ether = Ether(BigDecimal(wei) / value)
93 | @inline def /(value: BigInt): Ether = Ether(value) / wei
94 | @inline def /(value: BigDecimal): Ether = Ether(value) / wei
95 |
96 | @inline def +(value: Ether): Ether = Ether(wei + value.wei)
97 | @inline def +(value: Int): Ether = Ether(wei + value)
98 | @inline def +(value: Double): Ether = Ether(BigDecimal(wei) + value)
99 | @inline def +(value: BigInt): Ether = Ether(value) + wei
100 | @inline def +(value: BigDecimal): Ether = Ether(value) + wei
101 |
102 | @inline def -(value: Ether): Ether = Ether(wei - value.wei)
103 | @inline def -(value: Int): Ether = Ether(wei - value)
104 | @inline def -(value: Double): Ether = Ether(BigDecimal(wei) - value)
105 | @inline def -(value: BigInt): Ether = Ether(value) - wei
106 | @inline def -(value: BigDecimal): Ether = Ether(value) - wei
107 |
108 | @inline def bigInteger: java.math.BigInteger = wei.bigInteger
109 | @inline def asWei: BigInt = wei
110 | @inline def asKWei: BigDecimal = bigDecimal(wei / e(3))
111 | @inline def asMWei: BigDecimal = bigDecimal(wei / e(6))
112 | @inline def asGWei: BigDecimal = bigDecimal(wei / e(9))
113 | @inline def asSzabo: BigDecimal = bigDecimal(wei / e(12))
114 | @inline def asFinney: BigDecimal = bigDecimal(wei / e(15))
115 | @inline def asEther: BigDecimal = bigDecimal(wei / e(18))
116 | @inline def asKEther: BigDecimal = bigDecimal(wei / e(21))
117 | @inline def asMEther: BigDecimal = bigDecimal(wei / e(24))
118 | @inline def asGEther: BigDecimal = bigDecimal(wei / e(27))
119 |
120 | /** @return Amount of Ether corresponding to the given wei value */
121 | @inline def bigDecimal(wei: BigInt): java.math.BigDecimal =
122 | new java.math.BigDecimal(wei.bigInteger)
123 | .setScale(16, java.math.RoundingMode.DOWN)
124 |
125 | @inline def compare(that: Ether): Int = this.wei compare that.wei
126 |
127 | @inline override def equals(that: Any): Boolean =
128 | that match {
129 | case that: Ether =>
130 | this.hashCode == that.hashCode
131 |
132 | case _ => false
133 | }
134 |
135 | @inline override def hashCode: Int = wei.hashCode
136 |
137 | @inline def isNegative: Boolean = wei < zero.wei
138 |
139 | /** Zero is not considered to be a positive value */
140 | @inline def isPositive: Boolean = wei > zero.wei
141 |
142 | @inline def isZero: Boolean = wei == zero.wei
143 |
144 | @inline def toHex: String = s"0x${ wei.toString(16) }"
145 |
146 | override def toString: String = wei.bitLength match {
147 | case length if length <=3 => s"$wei Wei"
148 | case length if length <=6 => s"$asKWei KWei"
149 | case length if length <=9 => s"$asMWei MWei"
150 | case length if length <=12 => s"$asGWei GWei"
151 | case length if length <=15 => s"$asSzabo Szabo"
152 | case length if length <=18 => s"$asFinney Finney"
153 | case length if length <=21 => s"$asEther Ether"
154 | case length if length <=24 => s"$asKEther KEther"
155 | case length if length <=27 => s"$asMEther MEther"
156 | case _ => s"$asGEther GEther"
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/EthereumASynchronous.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j
2 |
3 | import java.math.BigInteger
4 | import org.web3j.protocol.Web3j
5 | import org.web3j.protocol.core.DefaultBlockParameter
6 | import org.web3j.protocol.core.DefaultBlockParameterName.LATEST
7 | import org.web3j.protocol.core.methods.request
8 | import org.web3j.protocol.core.methods.response.{EthBlock, EthCompileSolidity, EthGetWork, EthLog, ShhMessages, Transaction, TransactionReceipt}
9 | import scala.collection.compat._
10 | import scala.jdk.CollectionConverters._
11 | import scala.compat.java8.OptionConverters._
12 | import scala.collection.immutable.List
13 | import scala.compat.java8.FutureConverters._
14 | import scala.concurrent.ExecutionContext.{global => defaultExecutionContext}
15 | import scala.concurrent.{ExecutionContext, Future}
16 |
17 | /** All of the methods in this class return a [[scala.concurrent.Future]] and do not block.
18 | * @param web3j can be shared with [[EthereumSynchronous]]
19 | * @param ec if no [[scala.concurrent.ExecutionContext]] is implicitly available, the default Scala
20 | * [[scala.concurrent.ExecutionContext]] is used. */
21 | class EthereumASynchronous(val web3j: Web3j)
22 | (implicit val ec: ExecutionContext = defaultExecutionContext) {
23 |
24 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts eth_accounts]] JSON-RPC endpoint.
25 | * @return the list of addresses owned by the client */
26 | def accounts: Future[List[Address]] =
27 | web3j.ethAccounts.sendAsync.toScala.map(_.getAccounts.asScala.toList.map(Address))
28 |
29 | /** Add the given identity address to the Whisper group.
30 | *
31 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup shh_addtogroup]] JSON-RPC endpoint.
32 | * @return true if the identity was successfully added to the group */
33 | def addToGroup(identityAddress: Address): Future[Boolean] =
34 | web3j.shhAddToGroup(identityAddress.value).sendAsync.toScala.map(_.addedToGroup)
35 |
36 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance eth_getbalance]] JSON-RPC endpoint.
37 | * @param defaultBlockParameter either an integer block number, or the string "latest", "earliest" or "pending".
38 | * See the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter specification]].
39 | * @return the balance of the account of given address */
40 | def balance(address: Address, defaultBlockParameter: DefaultBlockParameter): Future[Ether] =
41 | web3j.ethGetBalance(address.value, defaultBlockParameter).sendAsync.toScala.map(x => Ether(x.getBalance))
42 |
43 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash eth_getblockbyhash]] JSON-RPC endpoint.
44 | * @return Option[EthBlock.Block] */
45 | def blockByHash(blockHash: BlockHash, returnFullTransactionObjects: Boolean): Future[Option[EthBlock.Block]] =
46 | web3j.ethGetBlockByHash(blockHash.value, returnFullTransactionObjects).sendAsync.toScala.map(x => Option(x.getBlock))
47 |
48 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash eth_getblockbyhash]] JSON-RPC endpoint.
49 | * @return Some(block object), or None if no block was found */
50 | def blockByNumber(
51 | defaultBlockParameter: DefaultBlockParameter,
52 | returnFullTransactionObjects: Boolean = false
53 | ): Future[Option[EthBlock.Block]] =
54 | web3j
55 | .ethGetBlockByNumber(defaultBlockParameter, returnFullTransactionObjects)
56 | .sendAsync
57 | .toScala
58 | .map(x => Option(x.getBlock))
59 |
60 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber eth_blocknumber]] JSON-RPC endpoint.
61 | * @return the number of the most recent block */
62 | def blockNumber: Future[BigInteger] = web3j.ethBlockNumber.sendAsync.toScala.map(_.getBlockNumber)
63 |
64 | def blockTransactionCountByHash(blockHash: String): Future[BigInteger] =
65 | web3j.ethGetBlockTransactionCountByHash(blockHash).sendAsync.toScala.map(_.getTransactionCount)
66 |
67 | def blockTransactionCountByNumber(defaultBlockParameter: DefaultBlockParameter): Future[BigInteger] =
68 | web3j.ethGetBlockTransactionCountByNumber(defaultBlockParameter).sendAsync.toScala.map(_.getTransactionCount)
69 |
70 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call eth_call]] JSON-RPC endpoint.
71 | * @return value of executed contract, without creating a transaction on the block chain */
72 | def call(transaction: request.Transaction, defaultBlockParameter: DefaultBlockParameter): Future[String] =
73 | web3j.ethCall(transaction, defaultBlockParameter).sendAsync.toScala.map(_.getValue)
74 |
75 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode eth_getcode]] JSON-RPC endpoint.
76 | * @return code at a given address */
77 | def code(address: Address, defaultBlockParameter: DefaultBlockParameter): Future[String] =
78 | web3j.ethGetCode(address.value, defaultBlockParameter).sendAsync.toScala.map(_.getCode)
79 |
80 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase eth_coinbase]] JSON-RPC endpoint.
81 | * @return the client coinbase address */
82 | def coinbaseAddress: Future[Address] = web3j.ethCoinbase.sendAsync.toScala.map(x => Address(x.getAddress))
83 |
84 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll eth_compilelll]] JSON-RPC endpoint.
85 | * @return compiled LLL code */
86 | def compileLLL(sourceCode: LLLSource): Future[LLLCompiled] =
87 | web3j.ethCompileLLL(sourceCode.value).sendAsync.toScala.map(x => LLLCompiled(x.getCompiledSourceCode))
88 |
89 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compileserpent eth_compileserpent]] JSON-RPC endpoint.
90 | * @return compiled Serpent code */
91 | def compileSerpent(sourceCode: SerpentSource): Future[SerpentCompiled] =
92 | web3j.ethCompileSerpent(sourceCode.value).sendAsync.toScala.map(x => SerpentCompiled(x.getCompiledSourceCode))
93 |
94 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity eth_compilesolidity]] JSON-RPC endpoint.
95 | * @return compiled Solidity code */
96 | def compileSolidity(sourceCode: SoliditySource): Future[Map[String, EthCompileSolidity.Code]] =
97 | web3j.ethCompileSolidity(sourceCode.value).sendAsync.toScala.map(_.getCompiledSolidity.asScala.toMap)
98 |
99 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers eth_getcompilers]] JSON-RPC endpoint.
100 | * @return a list of available compilers found by the underlying Web3J library */
101 | def compilers: Future[List[Compiler]] =
102 | web3j.ethGetCompilers.sendAsync.toScala.map(_.getCompilers.asScala.toList.map(Compiler))
103 |
104 | /** Makes a call or transaction, which won't be added to the blockchain and returns the used gas, which can be used
105 | * for estimating the used gas.
106 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas eth_estimategas]] JSON-RPC endpoint.
107 | * @return amount of gas estimated */
108 | def estimateGas(transaction: request.Transaction): Future[Ether] =
109 | web3j.ethEstimateGas(transaction).sendAsync.toScala.map(x => Ether(x.getAmountUsed))
110 |
111 | /** Polling method for an eth filter.
112 | *
113 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges eth_getfilterchanges]] JSON-RPC endpoint.
114 | * @return List of log items since last poll, could be Nil if nothing changed since the last poll */
115 | def filterChangesEth(filterId: FilterId): Future[List[EthLog.LogResult[_]]] =
116 | web3j.ethGetFilterChanges(filterId.value).sendAsync.toScala.map(_.getLogs.asScala.toList)
117 |
118 | /** Polling method for a Whisper filter.
119 | *
120 | * Note: calling shh_getMessages will reset the buffer for this method to avoid duplicate messages.
121 | *
122 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges shh_getfilterchanges]] JSON-RPC endpoint.
123 | * @return List of messages since the last poll; could be Nil if nothing changed since the last poll */
124 | def filterChangesShh(filterId: FilterId): Future[List[ShhMessages.SshMessage]] =
125 | web3j.shhGetFilterChanges(filterId.value).sendAsync.toScala.map(_.getMessages.asScala.toList)
126 |
127 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice eth_gasprice]] JSON-RPC endpoint.
128 | * @return the current price per gas in wei */
129 | def gasPrice: Future[Ether] = web3j.ethGasPrice.sendAsync.toScala.map(x => Ether(x.getGasPrice))
130 |
131 | /** Used for submitting mining hash rate
132 | *
133 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate eth_submithashrate]] JSON-RPC endpoint.
134 | * @return true if submitting successfully */
135 | def hashRate(hashRate: String, clientId: String): Future[Boolean] =
136 | web3j.ethSubmitHashrate(hashRate, clientId).sendAsync.toScala.map(_.submissionSuccessful)
137 |
138 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate eth_hashrate]] JSON-RPC endpoint.
139 | * @return the number of hashes per second that the node is mining at */
140 | def hashRate: Future[BigInteger] = web3j.ethHashrate.sendAsync.toScala.map(_.getHashrate)
141 |
142 | /** Checks if the client hold the private keys for a given identity.
143 | *
144 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity shh_hasidentity]] JSON-RPC endpoint.
145 | * @return returns true if this client holds the private key for that identity */
146 | def hasIdentity(identityAddress: Address): Future[Boolean] =
147 | web3j.shhHasIdentity(identityAddress.value).sendAsync.toScala.map(_.hasPrivateKeyForIdentity)
148 |
149 | /** Retrieves binary data from the local database.
150 | *
151 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_gethex db_gethex]] JSON-RPC endpoint.
152 | * @return the retrieved value */
153 | @deprecated("deprecated", "")
154 | def hexFrom(databaseName: String, keyName: String): Future[String] =
155 | web3j.dbGetHex(databaseName, keyName).sendAsync.toScala.map(_.getStoredValue)
156 |
157 | /** Stores binary data in the local database.
158 | *
159 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_puthex db_puthex]] JSON-RPC endpoint.
160 | * @return true if the value was stored */
161 | @deprecated("deprecated", "")
162 | def hexTo(databaseName: String, keyName: String, dataToStore: String): Future[Boolean] =
163 | web3j.dbPutHex(databaseName, keyName, dataToStore).sendAsync.toScala.map(_.valueStored)
164 |
165 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening net_listening]] JSON-RPC endpoint.
166 | * @return true if this client is actively listening for network connections */
167 | def isListening: Future[Boolean] = web3j.netListening.sendAsync.toScala.map(_.isListening)
168 |
169 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining eth_mining]] JSON-RPC endpoint. */
170 | def isMining: Future[Boolean] = web3j.ethMining.sendAsync.toScala.map(_.isMining)
171 |
172 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing eth_syncing]] JSON-RPC endpoint. */
173 | def isSyncing: Future[Boolean] = web3j.ethSyncing.sendAsync.toScala.map(_.isSyncing)
174 |
175 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs eth_getlogs]] JSON-RPC endpoint.
176 | * @return List of all log items matching a given filter object */
177 | def logs(ethFilter: request.EthFilter): Future[List[EthLog.LogResult[_]]] =
178 | web3j.ethGetLogs(ethFilter).sendAsync.toScala.map(_.getLogs.asScala.toList)
179 |
180 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs eth_getfilterlogs]] JSON-RPC endpoint.
181 | * @return List of all log items with the matching filter id */
182 | def logs(filterId: FilterId): Future[List[EthLog.LogResult[_]]] =
183 | web3j.ethGetFilterLogs(filterId.value).sendAsync.toScala.map(_.getLogs.asScala.toList)
184 |
185 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages shh_getmessages]] JSON-RPC endpoint.
186 | * @return all Whisper messages matching a filter */
187 | def messages(filterId: FilterId): Future[List[ShhMessages.SshMessage]] =
188 | web3j.shhGetMessages(filterId.value).sendAsync.toScala.map(_.getMessages.asScala.toList)
189 |
190 | /** Creates a filter in the node, to notify when the state changes (logs).
191 | * To check if the state has changed, call `filterChanges`.
192 | *
193 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter eth_newblockfilter]] JSON-RPC endpoint.
194 | * @return filter id */
195 | def newBlockFilter: Future[FilterId] = web3j.ethNewBlockFilter.sendAsync.toScala.map(x => FilterId(x.getFilterId))
196 |
197 | /** Get the next available nonce before creating a transaction */
198 | // todo should a Nonce type be created?
199 | def nextNonce(address: Address): Future[Nonce] = nonce(address, LATEST)
200 |
201 | /** Creates a filter object, based on filter options, to notify when the state changes (logs).
202 | * To check if the state has changed, call `filterChanges`.
203 | *
204 | * Topics are order-dependent.
205 | * A transaction with a log with topics [A, B] will be matched by the following topic filters:
206 | *
207 | * - [] "anything"
208 | * - [A] "A in first position (and anything after)"
209 | * - [null, B] "anything in first position AND B in second position (and anything after)"
210 | * - [A, B] "A in first position AND B in second position (and anything after)"
211 | * - [ [A, B], [A, B] ] "(A OR B) in first position AND (A OR B) in second position (and anything after)"
212 | *
213 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter eth_newfilter]] JSON-RPC endpoint.
214 | * @return filter id */
215 | def newFilter(ethFilter: request.EthFilter): Future[FilterId] =
216 | web3j.ethNewFilter(ethFilter).sendAsync.toScala.map(x => FilterId(x.getFilterId))
217 |
218 | /** Create filter that notifies the client when whisper message is received that matches the filter options.
219 | *
220 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter shh_newfilter]] JSON-RPC endpoint.
221 | * @return The newly created filter as a BigInteger */
222 | def newFilter(shhFilter: request.ShhFilter): Future[FilterId] =
223 | web3j.shhNewFilter(shhFilter).sendAsync.toScala.map(x => FilterId(x.getFilterId))
224 |
225 | /** New Whisper group.
226 | *
227 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup shh_newgroup]] JSON-RPC endpoint.
228 | * @return address of the new group */
229 | def newGroup: Future[Address] = web3j.shhNewGroup.sendAsync.toScala.map(x => Address(x.getAddress))
230 |
231 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity shh_newidentity]] JSON-RPC endpoint.
232 | * @return address of the new whisper identity */
233 | def newIdentity: Future[Address] = web3j.shhNewIdentity.sendAsync.toScala.map(x => Address(x.getAddress))
234 |
235 | def newPendingTransactionFilter: Future[FilterId] =
236 | web3j.ethNewPendingTransactionFilter.sendAsync.toScala.map(x => FilterId(x.getFilterId))
237 |
238 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount eth_gettransactioncount]] JSON-RPC endpoint.
239 | * @see See [[https://github.com/ethereum/wiki/wiki/Glossary Glossary]]
240 | * @return the number of transactions sent from an address */
241 | def nonce(address: Address, defaultBlockParameter: DefaultBlockParameter): Future[Nonce] =
242 | web3j.ethGetTransactionCount(address.value, defaultBlockParameter).sendAsync.toScala.map(x => Nonce(x.getTransactionCount))
243 |
244 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount net_peercount]] JSON-RPC endpoint.
245 | * @return number of peers currently connected to this client */
246 | def peerCount: Future[BigInteger] = web3j.netPeerCount.sendAsync.toScala.map(_.getQuantity)
247 |
248 | /** Sends a whisper message.
249 | *
250 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post shh_post]] JSON-RPC endpoint.
251 | * @return true if the message was sent */
252 | def post(shhPost: request.ShhPost): Future[Boolean] = web3j.shhPost(shhPost).sendAsync.toScala.map(_.messageSent)
253 |
254 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendrawtransaction eth_sendrawtransaction]] JSON-RPC endpoint.
255 | * @return new message call transaction or a contract creation for signed transactions */
256 | def sendRawTransaction(signedTransactionData: SignedData): Future[TransactionHash] =
257 | web3j.ethSendRawTransaction(signedTransactionData.value).sendAsync.toScala.map(x => TransactionHash(x.getTransactionHash))
258 |
259 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction eth_sendtransaction]] JSON-RPC endpoint.
260 | * @return a new contract if the {{{Transaction.data}}} field contains code, else return a new transaction */
261 | def sendTransaction(transaction: request.Transaction): Future[TransactionHash] =
262 | web3j.ethSendTransaction(transaction).sendAsync.toScala.map(x => TransactionHash(x.getTransactionHash))
263 |
264 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3 web3_sha3]] JSON-RPC endpoint.
265 | * @param data the data to convert into an SHA3 hash
266 | * @return Keccak-256 hash (not the standardized SHA3-256 hash) of the given data */
267 | def sha3(data: String): Future[Keccak256Hash] = web3j.web3Sha3(data).sendAsync.toScala.map(x => Keccak256Hash(x.getResult))
268 |
269 | /** Calculates an Ethereum-specific signature with:
270 | * {{{sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))}}}
271 | *
272 | * By adding a prefix to the message makes the calculated signature recognisable as an Ethereum-specific signature.
273 | * This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.
274 | *
275 | * Note: the address to sign with must be unlocked.
276 | *
277 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign eth_sign]] JSON-RPC endpoint.
278 | * @return Signature */
279 | def sign(address: Address, sha3HashOfDataToSign: Keccak256Hash): Future[Signature] =
280 | web3j.ethSign(address.value, sha3HashOfDataToSign.value).sendAsync.toScala.map(x => Signature(x.getSignature))
281 |
282 | /** Obtains a string from the local database.
283 | *
284 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_getstring db_getstring]] JSON-RPC endpoint.
285 | * @return previously stored value */
286 | @deprecated("deprecated", "")
287 | def stringFrom(databaseName: String, keyName: String): Future[String] =
288 | web3j.dbGetString(databaseName, keyName).sendAsync.toScala.map(_.getStoredValue)
289 |
290 | /** Stores a string in the local database
291 | *
292 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_putstring db_putstring]] JSON-RPC endpoint.
293 | * @return true if the value was stored */
294 | @deprecated("deprecated", "")
295 | def stringTo(databaseName: String, keyName: String, stringToStore: String): Future[Boolean] =
296 | web3j.dbPutString(databaseName, keyName, stringToStore).sendAsync.toScala.map(_.valueStored)
297 |
298 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat eth_getstorageat]] JSON-RPC endpoint.
299 | * @return the value from a storage position at a given address */
300 | def storageAt(address: Address, position: BigInteger, defaultBlockParameter: DefaultBlockParameter): Future[String] =
301 | web3j.ethGetStorageAt(address.value, position, defaultBlockParameter).sendAsync.toScala.map(_.getData)
302 |
303 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex eth_gettransactionbyblockhashandindex]] JSON-RPC endpoint.
304 | * @return Some containing transaction information by block hash and transaction index position, or None if no matching transaction was found */
305 | def transactionByBlockHashAndIndex(blockHash: BlockHash, transactionIndex: BigInteger): Future[Option[Transaction]] =
306 | web3j.ethGetTransactionByBlockHashAndIndex(blockHash.value, transactionIndex).sendAsync.toScala.map(_.getTransaction.asScala)
307 |
308 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex eth_gettransactionbyblocknumberandindex]] JSON-RPC endpoint.
309 | * @return Some containing transaction information by block hash and transaction index position, or None if no matching transaction was found */
310 | def transactionByBlockNumberAndIndex(
311 | defaultBlockParameter: DefaultBlockParameter,
312 | transactionIndex: BigInteger
313 | ): Future[Option[Transaction]] =
314 | web3j
315 | .ethGetTransactionByBlockNumberAndIndex(defaultBlockParameter, transactionIndex)
316 | .sendAsync
317 | .toScala
318 | .map(_.getTransaction.asScala)
319 |
320 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash eth_gettransactionbyhash]] JSON-RPC endpoint.
321 | * @return Future containing Some(transaction object), or None when no transaction was found */
322 | def transactionByHash(transactionHash: TransactionHash): Future[Option[Transaction]] =
323 | web3j.ethGetTransactionByHash(transactionHash.value).sendAsync.toScala.map(_.getTransaction.asScala)
324 |
325 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt eth_gettransactionreceipt]] JSON-RPC endpoint.
326 | * @return the receipt of a transaction, identified by transaction hash. (Note: receipts are not available for pending transactions.) */
327 | def transactionReceipt(transactionHash: TransactionHash): Future[Option[TransactionReceipt]] =
328 | web3j.ethGetTransactionReceipt(transactionHash.value).sendAsync.toScala.map(_.getTransactionReceipt.asScala)
329 |
330 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash eth_getunclecountbyblockhash]] JSON-RPC endpoint.
331 | * @return the number of uncles in a block from a block matching the given block hash */
332 | def uncleCountByBlockHash(blockHash: BlockHash): Future[BigInteger] =
333 | web3j.ethGetUncleCountByBlockHash(blockHash.value).sendAsync.toScala.map(_.getUncleCount)
334 |
335 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber eth_getunclecountbyblocknumber]] JSON-RPC endpoint.
336 | * @return the number of uncles in a block from a block matching the given block number */
337 | def uncleCountByBlockNumber(defaultBlockParameter: DefaultBlockParameter): Future[BigInteger] =
338 | web3j.ethGetUncleCountByBlockNumber(defaultBlockParameter).sendAsync.toScala.map(_.getUncleCount)
339 |
340 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex eth_getunclebyblocknumberandindex]] JSON-RPC endpoint.
341 | * @return information about a uncle of a block by hash and uncle index position */
342 | def uncleByBlockNumberAndIndex(
343 | defaultBlockParameter: DefaultBlockParameter,
344 | transactionIndex: BigInteger
345 | ): Future[EthBlock.Block] =
346 | web3j.ethGetUncleByBlockNumberAndIndex(defaultBlockParameter, transactionIndex).sendAsync.toScala.map(_.getBlock)
347 |
348 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex eth_getunclebyblockhashandindex]] JSON-RPC endpoint.
349 | * @return information about a uncle of a block by hash and uncle index position */
350 | def uncleByBlockHashAndIndex(blockHash: BlockHash, transactionIndex: BigInteger): Future[EthBlock.Block] =
351 | web3j.ethGetUncleByBlockHashAndIndex(blockHash.value, transactionIndex).sendAsync.toScala.map(_.getBlock)
352 |
353 | /** Uninstalls a filter with the given id.
354 | * Should always be called when watch is no longer needed.
355 | *
356 | * Note: Filters time out when they aren't requested with filterChanges for a period of time.
357 | *
358 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter eth_uninstallfilter]] JSON-RPC endpoint.
359 | * @return true if the filter was successfully uninstalled */
360 | def uninstallFilter(filterId: FilterId): Future[Boolean] =
361 | web3j.ethUninstallFilter(filterId.value).sendAsync.toScala.map(_.isUninstalled)
362 |
363 | /** Uninstalls a Whisper filter with the given id.
364 | * Should always be called when watch is no longer needed.
365 | *
366 | * Note: Filters time out when they aren't requested with filterChanges for a period of time.
367 | *
368 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter shh_uninstallfilter]] JSON-RPC endpoint.
369 | * @return true if the filter was successfully uninstalled */
370 | def uninstallShhFilter(filterId: FilterId): Future[Boolean] =
371 | web3j.shhUninstallFilter(filterId.value).sendAsync.toScala.map(_.isUninstalled)
372 |
373 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientversion web3_clientversion]] JSON-RPC endpoint.
374 | * @return the Web3J client version used by this client */
375 | def versionWeb3J: Future[String] = web3j.web3ClientVersion.sendAsync.toScala.map(_.getWeb3ClientVersion)
376 |
377 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version net_version]] JSON-RPC endpoint.
378 | * @return the current network id */
379 | def versionNet: Future[String] = web3j.netVersion.sendAsync.toScala.map(_.getNetVersion)
380 |
381 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion eth_protocolversion]] JSON-RPC endpoint.
382 | * @return ethereum protocol version used by this client */
383 | def versionProtocol: Future[String] = web3j.ethProtocolVersion.sendAsync.toScala.map(_.getProtocolVersion)
384 |
385 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version shh_version]] JSON-RPC endpoint.
386 | * @return the current whisper protocol version. */
387 | def versionShh: Future[String] = web3j.shhVersion.sendAsync.toScala.map(_.getVersion)
388 |
389 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork eth_getwork]] JSON-RPC endpoint.
390 | * @return the hash of the current block, the seedHash, and the boundary condition to be met ("target").
391 | * The Array with the following properties:
392 | *
393 | * DATA, 32 Bytes - current block header pow-hash
394 | * DATA, 32 Bytes - the seed hash used for the DAG.
395 | * DATA, 32 Bytes - the boundary condition ("target"), 2^^256 / difficulty. */
396 | def work: Future[EthGetWork] = web3j.ethGetWork.sendAsync.toScala
397 |
398 | /** Used for submitting a proof-of-work solution.
399 | *
400 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork eth_submitwork]] JSON-RPC endpoint.
401 | * @return true if the provided solution is valid */
402 | // fixme What type of hash is headerPowHash?
403 | def work(nonce: Nonce, headerPowHash: Keccak256Hash, mixDigest: Digest): Future[Boolean] =
404 | web3j.ethSubmitWork(nonce.toString, headerPowHash.value, mixDigest.value).sendAsync.toScala.map(_.solutionValid)
405 | }
406 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/EthereumSynchronous.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j
2 |
3 | import java.math.BigInteger
4 | import org.web3j.protocol.Web3j
5 | import org.web3j.protocol.core.DefaultBlockParameter
6 | import org.web3j.protocol.core.DefaultBlockParameterName.LATEST
7 | import org.web3j.protocol.core.methods.request
8 | import org.web3j.protocol.core.methods.request.ShhFilter
9 | import org.web3j.protocol.core.methods.response.{EthBlock, EthCompileSolidity, EthGetWork, EthLog, ShhMessages, Transaction, TransactionReceipt}
10 | import scala.collection.compat._
11 | import scala.jdk.CollectionConverters._
12 | import scala.compat.java8.OptionConverters._
13 | import scala.collection.immutable.List
14 |
15 | /** All of the methods in this class block until a value is ready to be returned to the caller.
16 | * @param web3j can be shared with [[EthereumASynchronous]] */
17 | class EthereumSynchronous(val web3j: Web3j) {
18 |
19 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_accounts eth_accounts]] JSON-RPC endpoint.
20 | * @return the list of addresses owned by the client */
21 | def accounts: List[Address] = web3j.ethAccounts.send.getAccounts.asScala.toList.map(Address)
22 |
23 | /** Add the given identity address to the Whisper group.
24 | *
25 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_addtogroup shh_addtogroup]] JSON-RPC endpoint.
26 | * @return true if the identity was successfully added to the group */
27 | def addToGroup(identityAddress: Address): Boolean = web3j.shhAddToGroup(identityAddress.value).send.addedToGroup
28 |
29 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance eth_getbalance]] JSON-RPC endpoint.
30 | * @param defaultBlockParameter either an integer block number, or the string "latest", "earliest" or "pending".
31 | * See the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter specification]].
32 | * @return the balance of the account at given address */
33 | def balance(address: Address, defaultBlockParameter: DefaultBlockParameter): Ether =
34 | Ether(web3j.ethGetBalance(address.value, defaultBlockParameter).send.getBalance)
35 |
36 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash eth_getblockbyhash]] JSON-RPC endpoint.
37 | * @return Some(block object), or None if no block was found */
38 | def blockByHash(blockHash: BlockHash, returnFullTransactionObjects: Boolean): Option[EthBlock.Block] =
39 | Option(web3j.ethGetBlockByHash(blockHash.value, returnFullTransactionObjects).send.getBlock)
40 |
41 | def blockByNumber(
42 | defaultBlockParameter: DefaultBlockParameter,
43 | returnFullTransactionObjects: Boolean = false
44 | ): Option[EthBlock.Block] =
45 | Option(web3j.ethGetBlockByNumber(defaultBlockParameter, returnFullTransactionObjects).send.getBlock)
46 |
47 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_blocknumber eth_blocknumber]] JSON-RPC endpoint.
48 | * @return the number of the most recent block */
49 | // todo define a type for BlockNumber?
50 | def blockNumber: BigInteger = web3j.ethBlockNumber.send.getBlockNumber
51 |
52 | def blockTransactionCountByHash(blockHash: BlockHash): BigInteger =
53 | web3j.ethGetBlockTransactionCountByHash(blockHash.value).send.getTransactionCount
54 |
55 | def blockTransactionCountByNumber(defaultBlockParameter: DefaultBlockParameter): BigInteger =
56 | web3j.ethGetBlockTransactionCountByNumber(defaultBlockParameter).send.getTransactionCount
57 |
58 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_call eth_call]] JSON-RPC endpoint.
59 | * @return value of executed contract, without creating a transaction on the block chain */
60 | def call(transaction: request.Transaction, defaultBlockParameter: DefaultBlockParameter): String =
61 | web3j.ethCall(transaction, defaultBlockParameter).send.getValue
62 |
63 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcode eth_getcode]] JSON-RPC endpoint.
64 | * @return code at a given address */
65 | def code(address: Address, defaultBlockParameter: DefaultBlockParameter): String =
66 | web3j.ethGetCode(address.value, defaultBlockParameter).send.getCode
67 |
68 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_coinbase eth_coinbase]] JSON-RPC endpoint.
69 | * @return the client coinbase address */
70 | def coinbaseAddress: Address = Address(web3j.ethCoinbase.send.getAddress)
71 |
72 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilelll eth_compilelll]] JSON-RPC endpoint.
73 | * @return compiled LLL code */
74 | def compileLLL(sourceCode: LLLSource): LLLCompiled =
75 | LLLCompiled(web3j.ethCompileLLL(sourceCode.value).send.getCompiledSourceCode)
76 |
77 | def compileSerpent(sourceCode: SerpentSource): SerpentCompiled =
78 | SerpentCompiled(web3j.ethCompileSerpent(sourceCode.value).send.getCompiledSourceCode)
79 |
80 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_compilesolidity eth_compilesolidity]] JSON-RPC endpoint.
81 | * @return compiled Solidity code */
82 | def compileSolidity(sourceCode: SoliditySource): Map[String, EthCompileSolidity.Code] =
83 | web3j.ethCompileSolidity(sourceCode.value).send.getCompiledSolidity.asScala.toMap
84 |
85 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getcompilers eth_getcompilers]] JSON-RPC endpoint.
86 | * @return a list of available compilers found by the underlying Web3J library */
87 | def compilers: List[Compiler] = web3j.ethGetCompilers.send.getCompilers.asScala.toList.map(Compiler)
88 |
89 | /** Makes a call or transaction, which won't be added to the blockchain and returns the used gas, which can be used
90 | * for estimating the used gas.
91 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas eth_estimategas]] JSON-RPC endpoint.
92 | * @return amount of gas estimated */
93 | def estimateGas(transaction: request.Transaction): Ether = Ether(web3j.ethEstimateGas(transaction).send.getAmountUsed)
94 |
95 | /** Polling method for an eth filter.
96 | *
97 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges eth_getfilterchanges]] JSON-RPC endpoint.
98 | * @return List of log items since last poll, could be an empty array if nothing has changed since last poll */
99 | def filterChangesEth(filterId: FilterId): List[EthLog.LogResult[_]] =
100 | web3j.ethGetFilterChanges(filterId.value).send.getLogs.asScala.toList
101 |
102 | /** Polling method for a Whisper filter.
103 | *
104 | * Note: calling shh_getMessages will reset the buffer for this method to avoid duplicate messages.
105 | *
106 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getfilterchanges shh_getfilterchanges]] JSON-RPC endpoint.
107 | * @return List of messages since the last poll; could be Nil if nothing changed since the last poll */
108 | def filterChangesShh(filterId: FilterId): List[ShhMessages.SshMessage] =
109 | web3j.shhGetFilterChanges(filterId.value).send.getMessages.asScala.toList
110 |
111 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gasprice eth_gasprice]] JSON-RPC endpoint.
112 | * @return the current price per gas in wei */
113 | def gasPrice: Ether = Ether(web3j.ethGasPrice.send.getGasPrice)
114 |
115 | /** Query the hash rate.
116 | *
117 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_hashrate eth_hashrate]] JSON-RPC endpoint.
118 | * @return number of hashes per second that the node is mining at */
119 | def hashRate: BigInteger = web3j.ethHashrate.send.getHashrate
120 |
121 | /** Used for submitting mining hash rate
122 | *
123 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submithashrate eth_submithashrate]] JSON-RPC endpoint.
124 | * @return true if submitting successfully */
125 | def hashRate(hashRate: String, clientId: String): Boolean =
126 | web3j.ethSubmitHashrate(hashRate, clientId).send.submissionSuccessful
127 |
128 | /** Checks if the client hold the private keys for a given identity.
129 | *
130 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_hasidentity shh_hasidentity]] JSON-RPC endpoint.
131 | * @return returns true if this client holds the private key for that identity */
132 | def hasIdentity(identityAddress: Address): Boolean =
133 | web3j.shhHasIdentity(identityAddress.value).send.hasPrivateKeyForIdentity
134 |
135 | /** Retrieves binary data from the local database.
136 | *
137 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_gethex db_gethex]] JSON-RPC endpoint.
138 | * @return the retrieved value */
139 | @deprecated("deprecated", "")
140 | def hexFrom(databaseName: String, keyName: String): String =
141 | web3j.dbGetHex(databaseName, keyName).send.getStoredValue
142 |
143 | /** Stores binary data in the local database.
144 | *
145 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_puthex db_puthex]] JSON-RPC endpoint.
146 | * @return true if the value was stored */
147 | @deprecated("deprecated", "")
148 | def hexTo(databaseName: String, keyName: String, dataToStore: String): Boolean =
149 | web3j.dbPutHex(databaseName, keyName, dataToStore).send.valueStored
150 |
151 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#net_listening net_listening]] JSON-RPC endpoint.
152 | * @return true if this client is actively listening for network connections */
153 | def isListening: Boolean = web3j.netListening.send.isListening
154 |
155 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_mining eth_mining]] JSON-RPC endpoint. */
156 | def isMining: Boolean = web3j.ethMining.send.isMining
157 |
158 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_syncing eth_syncing]] JSON-RPC endpoint. */
159 | def isSyncing: Boolean = web3j.ethSyncing.send.isSyncing
160 |
161 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs eth_getlogs]] JSON-RPC endpoint.
162 | * @return List of all log items matching a given filter object */
163 | def logs(ethFilter: request.EthFilter): List[EthLog.LogResult[_]] =
164 | web3j.ethGetLogs(ethFilter).send.getLogs.asScala.toList
165 |
166 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterlogs eth_getfilterlogs]] JSON-RPC endpoint.
167 | * @return List of all log items with the matching filter id */
168 | def logs(filterId: FilterId): List[EthLog.LogResult[_]] =
169 | web3j.ethGetFilterLogs(filterId.value).send.getLogs.asScala.toList
170 |
171 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_getmessages shh_getmessages]] JSON-RPC endpoint.
172 | * @return all Whisper messages matching a filter */
173 | def messages(filterId: FilterId): List[ShhMessages.SshMessage] =
174 | web3j.shhGetMessages(filterId.value).send.getMessages.asScala.toList
175 |
176 | /** Creates a filter in the node, to notify when the state changes (logs).
177 | * To check if the state has changed, call `filterChanges`.
178 | *
179 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newblockfilter eth_newblockfilter]] JSON-RPC endpoint.
180 | * @return filter id */
181 | def newBlockFilter: FilterId = FilterId(web3j.ethNewBlockFilter.send.getFilterId)
182 |
183 | /** Creates a filter object, based on filter options, to notify when the state changes (logs).
184 | * To check if the state has changed, call `filterChanges`.
185 | *
186 | * Topics are order-dependent.
187 | * A transaction with a log with topics [A, B] will be matched by the following topic filters:
188 | *
189 | * - [] "anything"
190 | * - [A] "A in first position (and anything after)"
191 | * - [null, B] "anything in first position AND B in second position (and anything after)"
192 | * - [A, B] "A in first position AND B in second position (and anything after)"
193 | * - [ [A, B], [A, B] ] "(A OR B) in first position AND (A OR B) in second position (and anything after)"
194 | *
195 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter eth_newfilter]] JSON-RPC endpoint.
196 | * @return filter id */
197 | def newFilter(ethFilter: request.EthFilter): FilterId = FilterId(web3j.ethNewFilter(ethFilter).send.getFilterId)
198 |
199 | /** Create filter that notifies the client when whisper message is received that matches the filter options.
200 | *
201 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newfilter shh_newfilter]] JSON-RPC endpoint.
202 | * @return The newly created filter as a BigInteger */
203 | def newFilter(shhFilter: ShhFilter): FilterId = FilterId(web3j.shhNewFilter(shhFilter).send.getFilterId)
204 |
205 | /** New Whisper group.
206 | *
207 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newgroup shh_newgroup]] JSON-RPC endpoint.
208 | * @return address of the new group */
209 | def newGroup: Address = Address(web3j.shhNewGroup.send.getAddress)
210 |
211 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_newidentity shh_newidentity]] JSON-RPC endpoint.
212 | * @return address of the new whisper identity */
213 | def newIdentity: Address = Address(web3j.shhNewIdentity.send.getAddress)
214 |
215 | def newPendingTransactionFilter: FilterId = FilterId(web3j.ethNewPendingTransactionFilter.send.getFilterId)
216 |
217 | /** Get the next available nonce before creating a transaction */
218 | def nextNonce(address: Address): Nonce = nonce(address, LATEST)
219 |
220 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount eth_gettransactioncount]] JSON-RPC endpoint.
221 | * @see See [[https://github.com/ethereum/wiki/wiki/Glossary Glossary]]
222 | * @return the number of transactions sent from an address */
223 | def nonce(address: Address, defaultBlockParameter: DefaultBlockParameter): Nonce =
224 | Nonce(web3j.ethGetTransactionCount(address.value, defaultBlockParameter).send.getTransactionCount)
225 |
226 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#net_peercount net_peercount]] JSON-RPC endpoint.
227 | * @return number of peers currently connected to this client */
228 | def peerCount: BigInteger = web3j.netPeerCount.send.getQuantity
229 |
230 | /** Sends a whisper message.
231 | *
232 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_post shh_post]] JSON-RPC endpoint.
233 | * @return true if the message was sent */
234 | def post(shhPost: request.ShhPost): Boolean = web3j.shhPost(shhPost).send.messageSent
235 |
236 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendrawtransaction eth_sendrawtransaction]] JSON-RPC endpoint.
237 | * @return new message call transaction or a contract creation for signed transactions */
238 | def sendRawTransaction(signedTransactionData: SignedData): TransactionHash=
239 | TransactionHash(web3j.ethSendRawTransaction(signedTransactionData.value).send.getTransactionHash)
240 |
241 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction eth_sendtransaction]] JSON-RPC endpoint.
242 | * @return a new contract if the {{{Transaction.data}}} field contains code, else return a new transaction */
243 | def sendTransaction(transaction: request.Transaction): TransactionHash =
244 | TransactionHash(web3j.ethSendTransaction(transaction).send.getTransactionHash)
245 |
246 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_sha3 web3_sha3]] JSON-RPC endpoint.
247 | * @param data the data to convert into an SHA3 hash
248 | * @return Keccak-256 hash (not the standardized SHA3-256 hash) of the given data */
249 | def sha3(data: String): Keccak256Hash = Keccak256Hash(web3j.web3Sha3(data).send.getResult)
250 |
251 | /** Calculates an Ethereum-specific signature with:
252 | * {{{sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))}}}
253 | *
254 | * By adding a prefix to the message makes the calculated signature recognisable as an Ethereum-specific signature.
255 | * This prevents misuse where a malicious DApp can sign arbitrary data (e.g. transaction) and use the signature to impersonate the victim.
256 | *
257 | * Note: the address to sign with must be unlocked.
258 | *
259 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign eth_sign]] JSON-RPC endpoint.
260 | * @return Signature */
261 | def sign(address: Address, sha3HashOfDataToSign: String): Signature =
262 | Signature(web3j.ethSign(address.value, sha3HashOfDataToSign).send.getSignature)
263 |
264 | /** Obtains a string from the local database.
265 | *
266 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_getstring db_getstring]] JSON-RPC endpoint.
267 | * @return previously stored value */
268 | @deprecated("deprecated", "")
269 | def stringFrom(databaseName: String, keyName: String): String =
270 | web3j.dbGetString(databaseName, keyName).send.getStoredValue
271 |
272 | /** Stores a string in the local database
273 | *
274 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#db_putstring db_putstring]] JSON-RPC endpoint.
275 | * @return true if the value was stored */
276 | @deprecated("deprecated", "")
277 | def stringTo(databaseName: String, keyName: String, stringToStore: String): Boolean =
278 | web3j.dbPutString(databaseName, keyName, stringToStore).send.valueStored
279 |
280 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat eth_getstorageat]] JSON-RPC endpoint.
281 | * @return the value from a storage position at a given address */
282 | def storageAt(address: Address, position: BigInteger, defaultBlockParameter: DefaultBlockParameter): String =
283 | web3j.ethGetStorageAt(address.value, position, defaultBlockParameter).send.getData
284 |
285 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblockhashandindex eth_gettransactionbyblockhashandindex]] JSON-RPC endpoint.
286 | * @return Some containing transaction information by block hash and transaction index position, or None if no matching transaction was found */
287 | def transactionByBlockHashAndIndex(blockHash: BlockHash, transactionIndex: BigInteger): Option[Transaction] =
288 | web3j.ethGetTransactionByBlockHashAndIndex(blockHash.value, transactionIndex).send.getTransaction.asScala
289 |
290 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyblocknumberandindex eth_gettransactionbyblocknumberandindex]] JSON-RPC endpoint.
291 | * @return Some containing transaction information by block hash and transaction index position, or None if no matching transaction was found */
292 | def transactionByBlockNumberAndIndex(
293 | defaultBlockParameter: DefaultBlockParameter,
294 | transactionIndex: BigInteger
295 | ): Option[Transaction] =
296 | web3j.ethGetTransactionByBlockNumberAndIndex(defaultBlockParameter, transactionIndex).send.getTransaction.asScala
297 |
298 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash eth_gettransactionbyhash]] JSON-RPC endpoint.
299 | * @return Future containing Some(transaction object), or None when no transaction was found */
300 | def transactionByHash(transactionHash: TransactionHash): Option[Transaction] =
301 | web3j.ethGetTransactionByHash(transactionHash.value).send.getTransaction.asScala
302 |
303 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt eth_gettransactionreceipt]] JSON-RPC endpoint.
304 | * @return the receipt of a transaction, identified by transaction hash. (Note: receipts are not available for pending transactions.) */
305 | def transactionReceipt(transactionHash: TransactionHash): Option[TransactionReceipt] =
306 | web3j.ethGetTransactionReceipt(transactionHash.value).send.getTransactionReceipt.asScala
307 |
308 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblocknumberandindex eth_getunclebyblocknumberandindex]] JSON-RPC endpoint.
309 | * @return information about a uncle of a block by hash and uncle index position */
310 | def uncleByBlockNumberAndIndex(defaultBlockParameter: DefaultBlockParameter, transactionIndex: BigInteger): EthBlock.Block =
311 | web3j.ethGetUncleByBlockNumberAndIndex(defaultBlockParameter, transactionIndex).send.getBlock
312 |
313 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclebyblockhashandindex eth_getunclebyblockhashandindex]] JSON-RPC endpoint.
314 | * @return information about a uncle of a block by hash and uncle index position */
315 | def uncleByBlockHashAndIndex(blockHash: BlockHash, transactionIndex: BigInteger): EthBlock.Block =
316 | web3j.ethGetUncleByBlockHashAndIndex(blockHash.value, transactionIndex).send.getBlock
317 |
318 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblockhash eth_getunclecountbyblockhash]] JSON-RPC endpoint.
319 | * @return the number of uncles in a block from a block matching the given block hash */
320 | def uncleCountByBlockHash(blockHash: BlockHash): BigInteger =
321 | web3j.ethGetUncleCountByBlockHash(blockHash.value).send.getUncleCount
322 |
323 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getunclecountbyblocknumber eth_getunclecountbyblocknumber]] JSON-RPC endpoint.
324 | * @return the number of uncles in a block from a block matching the given block number */
325 | def uncleCountByBlockNumber(defaultBlockParameter: DefaultBlockParameter): BigInteger =
326 | web3j.ethGetUncleCountByBlockNumber(defaultBlockParameter).send.getUncleCount
327 |
328 | /** Uninstalls a filter with given id.
329 | * Should always be called when watch is no longer needed.
330 | *
331 | * Note: Filters time out when they aren't requested with filterChanges for a period of time.
332 | *
333 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_uninstallfilter eth_uninstallfilter]] JSON-RPC endpoint.
334 | * @return true if the filter was successfully uninstalled */
335 | def uninstallFilter(filterId: FilterId): Boolean =
336 | web3j.ethUninstallFilter(filterId.value).send.isUninstalled
337 |
338 | /** Uninstalls a Whisper filter with the given id.
339 | * Should always be called when watch is no longer needed.
340 | *
341 | * Note: Filters time out when they aren't requested with filterChanges for a period of time.
342 | *
343 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_uninstallfilter shh_uninstallfilter]] JSON-RPC endpoint.
344 | * @return true if the filter was successfully uninstalled */
345 | def uninstallShhFilter(filterId: FilterId): Boolean =
346 | web3j.shhUninstallFilter(filterId.value).send.isUninstalled
347 |
348 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#web3_clientversion web3_clientversion]] JSON-RPC endpoint.
349 | * @return the Web3J client version used by this client */
350 | def versionWeb3J: String = web3j.web3ClientVersion.send.getWeb3ClientVersion
351 |
352 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version net_version]] JSON-RPC endpoint.
353 | * @return the current network id */
354 | def versionNet: String = web3j.netVersion.send.getNetVersion
355 |
356 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_protocolversion eth_protocolversion]] JSON-RPC endpoint.
357 | * @return ethereum protocol version used by this client */
358 | def versionProtocol: String = web3j.ethProtocolVersion.send.getProtocolVersion
359 |
360 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#shh_version shh_version]] JSON-RPC endpoint.
361 | * @return the current whisper protocol version. */
362 | def versionShh: String = web3j.shhVersion.send.getVersion
363 |
364 | /** Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getwork eth_getwork]] JSON-RPC endpoint.
365 | * @return the hash of the current block, the seedHash, and the boundary condition to be met ("target").
366 | * The Array with the following properties:
367 | *
368 | * DATA, 32 Bytes - current block header pow-hash
369 | * DATA, 32 Bytes - the seed hash used for the DAG.
370 | * DATA, 32 Bytes - the boundary condition ("target"), 2^^256 / difficulty. */
371 | def work: EthGetWork = web3j.ethGetWork.send
372 |
373 | /** Used for submitting a proof-of-work solution.
374 | *
375 | * Invokes the [[https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_submitwork eth_submitwork]] JSON-RPC endpoint.
376 | * @return true if the provided solution is valid */
377 | // todo what type of Hash should headerPowHash be?
378 | def work(nonce: Nonce, headerPowHash: Keccak256Hash, mixDigest: Digest): Boolean =
379 | web3j.ethSubmitWork(nonce.toString, headerPowHash.value, mixDigest.value).send.solutionValid
380 | }
381 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/InfuraNetwork.java:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j;
2 |
3 | /** From the [[https://docs.web3j.io/transactions.html#ethereum-testnets web3j testnet docs]]:
4 | * For development, its recommended you use the Rinkeby (geth only) or Kovan (Parity only) test networks.
5 | * This is because they use a Proof of Authority (PoA) consensus mechanism,
6 | * ensuring transactions and blocks are created in a consistent and timely manner.
7 | * The Ropsten testnet, although closest to the Mainnet as it uses Proof of Work (PoW) consensus,
8 | * has been subject to attacks in the past and tends to be more problematic for developers. */
9 | public enum InfuraNetwork {
10 | MAINNET, KOVAN, RINKEBY, ROPSTEN
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/ValueClasses.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j
2 |
3 | import java.math.BigInteger
4 | import org.web3j.protocol.core.methods.response.EthCompileSolidity
5 |
6 | case class Address(value: String) extends AnyVal {
7 | @inline override def toString: String = value.toString
8 | }
9 |
10 | case class Compiler(value: String) extends AnyVal {
11 | @inline override def toString: String = value.toString
12 | }
13 |
14 | case class Digest(value: String) extends AnyVal {
15 | @inline override def toString: String = value.toString
16 | }
17 |
18 | // @see See [[https://github.com/ethereum/wiki/wiki/Ethash Ethash]] for proof of work
19 | case class EtHash(value: String) extends AnyVal {
20 | @inline override def toString: String = value.toString
21 | }
22 |
23 | case class BlockHash(value: String) extends AnyVal {
24 | @inline override def toString: String = value.toString
25 | }
26 |
27 | case class FilterId(value: BigInteger) extends AnyVal {
28 | @inline override def toString: String = value.toString
29 | }
30 |
31 | case class LLLCompiled(value: String) extends AnyVal {
32 | @inline override def toString: String = value.toString
33 | }
34 |
35 | case class LLLSource(value: String) extends AnyVal {
36 | @inline override def toString: String = value.toString
37 | }
38 |
39 | /** An account nonce is a transaction counter, provided by Ethereum for each Account.
40 | * Nonces prevent replay attacks wherein a transaction sending Ether from A to B can be replayed by B over and over to
41 | * continually drain A's balance.
42 | * @see See [[https://github.com/ethereum/wiki/wiki/Glossary Glossary]] */
43 | case class Nonce(value: BigInt) extends AnyVal {
44 | @inline def bigInteger: BigInteger = value.bigInteger
45 |
46 | @inline override def toString: String = value.toString
47 | }
48 |
49 | case class SerpentCompiled(value: String) extends AnyVal {
50 | @inline override def toString: String = value.toString
51 | }
52 |
53 | case class SerpentSource(value: String) extends AnyVal {
54 | @inline override def toString: String = value.toString
55 | }
56 |
57 | /** The SHA3 hash is more properly referred to as
58 | * [[https://ethereum.stackexchange.com/questions/550/which-cryptographic-hash-function-does-ethereum-use Keccak-256]] */
59 | // todo better to use value classes to indicate functionality, not how something was created. Delete this type and replace by one of the others, or rename this
60 | case class Keccak256Hash(value: String) extends AnyVal {
61 | @inline override def toString: String = value.toString
62 | }
63 |
64 | case class Signature(value: String) extends AnyVal {
65 | @inline override def toString: String = value.toString
66 | }
67 |
68 | case class SignedData(value: String) extends AnyVal {
69 | @inline override def toString: String = value.toString
70 | }
71 |
72 | /** Web3J already has [[EthCompileSolidity.Code]] to represent Solidity compiled code */
73 | case class SoliditySource(value: String) extends AnyVal {
74 | @inline override def toString: String = value.toString
75 | }
76 |
77 | case class TransactionHash(value: String) extends AnyVal {
78 | @inline override def toString: String = value.toString
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/Web3JScala.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics.web3j
2 |
3 | import com.micronautics.web3j.InfuraNetwork._
4 | import org.web3j.protocol.Web3j
5 | import org.web3j.protocol.http.HttpService
6 | import org.web3j.protocol.infura.InfuraHttpService
7 | import io.reactivex.{Flowable, Observable}
8 | import scala.concurrent.ExecutionContext
9 |
10 | /** [[https://www.web3j.io Web3J]] builders and stateless methods. */
11 | object Web3JScala {
12 | lazy val cmd: Cmd = new Cmd
13 |
14 | /** @see See [[https://docs.web3j.io/management_apis.html?highlight=httpservice Management APIs]] */
15 | def fromHttp(url: String = "http://localhost:8545"): Web3j = {
16 | val web3j = Web3j.build(new HttpService(url))
17 | verifyConnection(web3j)
18 | web3j
19 | }
20 |
21 | /** @see See [[http://www.ziggify.com/blog/blockchain-stack-1-installing-ethereum-geth-smart-contract/ Installing Ethereum Geth and your first smart contract]]
22 | * @see See the [[http://faucet.ropsten.be:3001/ Ethereum Ropsten Faucet]]
23 | * @see See [[https://docs.web3j.io/infura.html Using Infura with web3j]]
24 | * @param network defaults to the Ropsten test network */
25 | def fromInfura(token: String, network: InfuraNetwork = ROPSTEN): Web3j = {
26 | val web3j = Web3j.build(new InfuraHttpService(s"https://${ network.name }.infura.io/$token"))
27 | verifyConnection(web3j)
28 | web3j
29 | }
30 |
31 | /** Invokes fn on all elements observed from the given Observable[T] */
32 | def observe[T](observable: Observable[T])
33 | (fn: T => Unit): Unit =
34 | observable.subscribe(fn(_))
35 |
36 | /** Only runs fn on the first n elements observed from the given Observable[T] */
37 | def observe[T](n: Int)
38 | (observable: Flowable[T])
39 | (fn: T => Unit): Unit =
40 | observable.limit(n.toLong).doOnEach { t =>
41 | fn(t.getValue)
42 | }
43 |
44 | /** Compile the smart contract.
45 | * Note that `solc` generates [[https://en.wikipedia.org/wiki/Camel_case camelCase]] names from
46 | * [[https://en.wikipedia.org/wiki/Snake_case snake_case]] names.
47 | * {{{solc --bin --abi --optimize --overwrite -o abi/ src/test/resources/basic_info_getter.sol}}} */
48 | def solc(solCFileName: String, outputDirectory: String="abi/"): String = cmd.getOutputFrom(
49 | "solc",
50 | "--bin",
51 | "--abi",
52 | "--optimize",
53 | "--overwrite",
54 | "-o", outputDirectory,
55 | solCFileName
56 | )
57 |
58 | /** Verify web3j is connected to a JSON-RPC endpoint */
59 | def verifyConnection(web3j: Web3j): Boolean = try {
60 | web3j.web3ClientVersion.send.getWeb3ClientVersion
61 | true
62 | } catch {
63 | case e: Exception =>
64 | println(s"${ e.getMessage }. Is geth or eth running?")
65 | System.exit(0)
66 | false
67 | }
68 |
69 | /** Generate the wrapper code from the compiled smart contract using web3j’s command-line tools
70 | * The `bin` and `abi` files are both read from the same directory, specified by `-o`.
71 | * {{{bin/web3j solidity generate abi/basic_info_getter.bin abi/basic_info_getter.abi -o abiWrapper/ -p com.micronautics.solidity}}} */
72 | def wrapAbi(
73 | filename: String,
74 | packageName: String = "com.micronautics.solidity",
75 | inputDirectory: String = "abi/",
76 | outputDirectory: String = "abiWrapper/"
77 | ): String = cmd.getOutputFrom(
78 | "bin/web3j", "solidity",
79 | "generate", s"$inputDirectory/${ toCamelCase(filename) }.bin", s"$inputDirectory/${ toCamelCase(filename) }.abi",
80 | "-o", outputDirectory,
81 | "-p", packageName
82 | )
83 |
84 | protected def toCamelCase(s: String): String = {
85 | val words = s.split("_")
86 | val tail = words.tail.map { word => word.head.toUpper.toString + word.tail }
87 | words.head + tail.mkString
88 | }
89 | }
90 |
91 | /** Wrapper for Web3J */
92 | class Web3JScala(val web3j: Web3j)
93 | (implicit ec: ExecutionContext) {
94 | lazy val async = new EthereumASynchronous(web3j)
95 | lazy val sync = new EthereumSynchronous(web3j)
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/scala/com/micronautics/web3j/package.scala:
--------------------------------------------------------------------------------
1 | package com.micronautics
2 |
3 | import org.web3j.protocol.core.methods.response
4 |
5 | /**
6 | * This project is an idiomatic Scala wrapper around [[https://www.web3j.io Web3J]] for Ethereum.
7 | * This project is built with Scala 2.12, and requires the Java 8 runtime; it is not yet compatible with Java 9.
8 | *
9 | * This project promotes idiomatic Scala in the following ways:
10 | * - Variables and no-argument methods are actually names of properties, so `set` and `get` prefixes are not used.
11 | * This means some properties do not have exactly the same name as their Web3J counterpart.
12 | * - Zero-argument methods only require parentheses if they perform side effects.
13 | * - Scala data types are used to the maximum extent that makes sense.
14 | * For example, [[scala.concurrent.Future]].
15 | * - A functional programming style is encouraged by always returning immutable data types from methods.
16 | * For example, [[scala.collection.immutable.List]]
17 | *
18 | * The [[https://github.com/ethereum/wiki/wiki/JSON-RPC Ethereum JSON-RPC documentation]]
19 | * was the source of many the comments incorporated into this Scaladoc.
20 | *
21 | * The JSON-RPC [[https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter default block parameter]]
22 | * can represent a `QUANTITY` or a `TAG`.
23 | * Quantities are expressed as integer block numbers, and tags are strings with one of the values "latest", "earliest" or "pending".
24 | * The [[https://jar-download.com/javaDoc/org.web3j/core/3.0.2/index.html?org/web3j/protocol/core/DefaultBlockParameter.html Java implementation]]
25 | * performs the same function as the underlying JSON-RPC implementation.
26 | *
27 | * [[https://github.com/ethereum/wiki/wiki/Whisper Whisper]]
28 | * is an experimental communication protocol of the Ethereum P2P protocol suite that allows
29 | * for messaging between users' DApps (Ethereum Distributed Applications).
30 | * Whisper uses the same network that the blockchain runs on.
31 | * The protocol is separate from the blockchain, so smart contracts do not have access to whispered messages.
32 | *
33 | * [[https://jar-download.com/javaDoc/org.web3j/core/3.0.2/index.html?org/web3j/protocol/core/methods/response/EthBlock.html EthBlock]]
34 | * and its internal types such as
35 | * [[https://jar-download.com/javaDoc/org.web3j/core/3.0.2/index.html?org/web3j/protocol/core/methods/response/EthBlock.Block.html Block]],
36 | * [[https://jar-download.com/javaDoc/org.web3j/core/3.0.2/index.html?org/web3j/protocol/core/methods/response/EthBlock.TransactionObject.html TransactionObject]] and
37 | * [[https://jar-download.com/javaDoc/org.web3j/core/3.0.2/index.html?org/web3j/protocol/core/methods/response/EthBlock.TransactionResult.html TransactionResult]]
38 | * are returned by the following methods of [[com.micronautics.web3j.EthereumSynchronous]] and [[com.micronautics.web3j.EthereumASynchronous]]:
39 | * `blockByHash`, `blockByNumber`, `uncleByBlockHashAndIndex`, `uncleByBlockNumberAndIndex`.
40 | * */
41 | package object web3j {
42 | /** Enriches `response.EthBlock.Block` with convenience methods */
43 | implicit class RichBlock(block: response.EthBlock.Block) {
44 | def javaTime = new java.util.Date(block.getTimestamp.longValue * 1000)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/resources/basic_info_getter.sol:
--------------------------------------------------------------------------------
1 | /* From https://raw.githubusercontent.com/fivedogit/solidity-baby-steps/master/contracts/15_basic_info_getter.sol
2 | * This is a demonstration of the various global variables available to contracts.
3 | * This list is probably not exhaustive, especially weeks and months from now. (9/2015) */
4 |
5 | pragma solidity ^0.4.18;
6 |
7 | contract basicInfoGetter {
8 | address creator;
9 |
10 | constructor() public {
11 | creator = msg.sender;
12 | }
13 |
14 | function getCurrentMinerAddress() public view returns (address) { // get CURRENT block miner's address,
15 | // not necessarily the address of the miner when this block was born
16 | return block.coinbase;
17 | }
18 |
19 | function getCurrentDifficulty() public view returns (uint) {
20 | return block.difficulty;
21 | }
22 |
23 | function getCurrentGaslimit() public view returns (uint) { // the most gas that can be spent on any given transaction right now
24 | return block.gaslimit;
25 | }
26 |
27 | function getCurrentBlockNumber() public view returns (uint) {
28 | return block.number;
29 | }
30 |
31 | function getBlockTimestamp() public view returns (uint) { // returns current block timestamp in SECONDS (not ms) from epoch
32 | return block.timestamp;
33 | // also "now" == "block.timestamp", as in "return now;"
34 | }
35 |
36 | function getMsgData() public pure returns (bytes) { // The data of a call to this function. Always returns "0xc8e7ca2e" for me.
37 | // adding an input parameter would probably change it with each diff call?
38 | return msg.data;
39 | }
40 |
41 | function getMsgSender() public view returns (address) { // Returns the address of whomever made this call
42 | // (i.e. not necessarily the creator of the contract)
43 | return msg.sender;
44 | }
45 |
46 | function getMsgValue() public payable returns (uint) { // returns amt of wei sent with this call
47 | return msg.value;
48 | }
49 |
50 | /*** A note about gas and gasprice:
51 | Every transaction must specify a quantity of "gas" that it is willing to consume (called startgas),
52 | and the fee that it is willing to pay per unit gas (gasprice). At the start of execution,
53 | startgas * gasprice ether are removed from the transaction sender's account.
54 | Whatever is not used is immediately refunded.
55 | */
56 |
57 | function getMsgGas() public view returns (uint) {
58 | return gasleft();
59 | }
60 |
61 | function getTxGasprice() public view returns (uint) {
62 | return tx.gasprice; // "gasprice" is the amount of gas the sender was *willing* to pay. 50000000 for me. (geth default)
63 | }
64 |
65 | function getTxOrigin() public view returns (address) { // returns sender of the transaction
66 | // What if there is a chain of calls? I think it returns the first sender, whoever provided the gas.
67 | return msg.sender;
68 | }
69 |
70 | function getContractAddress() public view returns (address) {
71 | return this;
72 | }
73 |
74 | function getContractBalance() public view returns (uint) {
75 | return address(this).balance;
76 | }
77 |
78 | /**********
79 | Standard kill() function to recover funds
80 | **********/
81 |
82 | function kill() public {
83 | if (msg.sender == creator)
84 | selfdestruct(creator);
85 | // kills this contract and sends remaining funds back to creator
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/test/scala/EtherTest.scala:
--------------------------------------------------------------------------------
1 | import com.micronautics.web3j.Ether
2 | import com.micronautics.web3j.Ether._
3 | import org.scalatest._
4 | import org.scalatest.Matchers._
5 |
6 | class EtherTest extends WordSpec {
7 | val wei: Ether = Ether(e(0))
8 | val kWei: Ether = Ether(e(3))
9 | val mWei: Ether = Ether(e(6))
10 | val gWei: Ether = Ether(e(9))
11 | val szabo: Ether = Ether(e(12))
12 | val finney: Ether = Ether(e(15))
13 | val ether: Ether = Ether(e(18))
14 | val kEther: Ether = Ether(e(21))
15 | val mEther: Ether = Ether(e(24))
16 | val gEther: Ether = Ether(e(27))
17 |
18 | "Ether" should {
19 | "compare" in {
20 | wei shouldBe wei
21 | kWei should be > wei
22 | kWei should be >= wei
23 | wei should be < kWei
24 | wei should be <= kWei
25 | }
26 |
27 | "support math" in {
28 | wei + wei shouldBe Ether(2)
29 | wei - 1 shouldBe Ether.zero
30 | wei - 2 shouldBe Ether(-1)
31 | wei + 2 shouldBe Ether(3)
32 | wei * 4 shouldBe Ether(4)
33 |
34 | kWei + kWei shouldBe Ether(e(3) * 2)
35 | kWei - 1000 shouldBe Ether.zero
36 | kWei - 2000 shouldBe Ether(e(3) * -1)
37 | kWei + 2000 shouldBe Ether(e(3) * 3)
38 | kWei * 4 shouldBe Ether(e(3) * 4)
39 | }
40 |
41 | "convert properly" in {
42 | Ether.fromWei(BigInt(1)) shouldBe wei
43 | Ether.fromWei(BigDecimal(1)) shouldBe wei
44 | Ether.fromWei(1) shouldBe wei
45 | Ether.fromWei(1.0) shouldBe wei
46 | Ether.fromWei(1.0) shouldBe wei
47 | Ether.fromWei(1) shouldBe wei
48 |
49 | Ether.fromKWei(BigInt(1)) shouldBe kWei
50 | Ether.fromKWei(BigDecimal(1)) shouldBe kWei
51 | Ether.fromKWei(1) shouldBe kWei
52 | Ether.fromKWei(1.0) shouldBe kWei
53 | Ether.fromKWei(1.0) shouldBe kWei
54 | Ether.fromKWei(1) shouldBe kWei
55 |
56 | Ether.fromMWei(BigInt(1)) shouldBe mWei
57 | Ether.fromMWei(BigDecimal(1)) shouldBe mWei
58 | Ether.fromMWei(1) shouldBe mWei
59 | Ether.fromMWei(1.0) shouldBe mWei
60 | Ether.fromMWei(1.0) shouldBe mWei
61 | Ether.fromMWei(1) shouldBe mWei
62 |
63 | Ether.fromGWei(BigInt(1)) shouldBe gWei
64 | Ether.fromGWei(BigDecimal(1)) shouldBe gWei
65 | Ether.fromGWei(1) shouldBe gWei
66 | Ether.fromGWei(1.0) shouldBe gWei
67 | Ether.fromGWei(1.0) shouldBe gWei
68 | Ether.fromGWei(1) shouldBe gWei
69 |
70 | Ether.fromSzabo(BigInt(1)) shouldBe szabo
71 | Ether.fromSzabo(BigDecimal(1)) shouldBe szabo
72 | Ether.fromSzabo(1) shouldBe szabo
73 | Ether.fromSzabo(1.0) shouldBe szabo
74 | Ether.fromSzabo(1.0) shouldBe szabo
75 | Ether.fromSzabo(1) shouldBe szabo
76 |
77 | Ether.fromFinney(BigInt(1)) shouldBe finney
78 | Ether.fromFinney(BigDecimal(1)) shouldBe finney
79 | Ether.fromFinney(1) shouldBe finney
80 | Ether.fromFinney(1.0) shouldBe finney
81 | Ether.fromFinney(1.0) shouldBe finney
82 | Ether.fromFinney(1) shouldBe finney
83 |
84 | Ether.fromEther(BigInt(1)) shouldBe ether
85 | Ether.fromEther(BigDecimal(1)) shouldBe ether
86 | Ether.fromEther(1) shouldBe ether
87 | Ether.fromEther(1.0) shouldBe ether
88 | Ether.fromEther(1.0) shouldBe ether
89 | Ether.fromEther(1) shouldBe ether
90 |
91 | Ether.fromKEther(BigInt(1)) shouldBe kEther
92 | Ether.fromKEther(BigDecimal(1)) shouldBe kEther
93 | Ether.fromKEther(1) shouldBe kEther
94 | Ether.fromKEther(1.0) shouldBe kEther
95 | Ether.fromKEther(1.0) shouldBe kEther
96 | Ether.fromKEther(1) shouldBe kEther
97 |
98 | Ether.fromMEther(BigInt(1)) shouldBe mEther
99 | Ether.fromMEther(BigDecimal(1)) shouldBe mEther
100 | Ether.fromMEther(1) shouldBe mEther
101 | Ether.fromMEther(1.0) shouldBe mEther
102 | Ether.fromMEther(1.0) shouldBe mEther
103 | Ether.fromMEther(1) shouldBe mEther
104 |
105 | Ether.fromGEther(BigInt(1)) shouldBe gEther
106 | Ether.fromGEther(BigDecimal(1)) shouldBe gEther
107 | Ether.fromGEther(1) shouldBe gEther
108 | Ether.fromGEther(1.0) shouldBe gEther
109 | Ether.fromGEther(1.0) shouldBe gEther
110 | Ether.fromGEther(1) shouldBe gEther
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------