Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.10.0"]
[org.web3j/core "4.8.4"]
[org.web3j/web3j-evm "4.8.4"]]
[org.web3j/web3j-evm "4.8.4"]
[org.web3j/codegen "4.8.4"]
[org.web3j/web3j-sokt "0.2.1"]]
:repositories [["jcenter" {:url "https://jcenter.bintray.com/"}]
["releases" {:url "https://repo.clojars.org"
:creds :gpg}]]
:repl-options {:init-ns web3clj.core})
:repl-options {:init-ns web3clj.core}
:java-source-paths ["src/java"])
22 changes: 22 additions & 0 deletions resources/contracts/Inbox.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// compiler version pinning
pragma solidity ^0.4.17;

// define a new contract
contract Inbox {
// storage variable which is stored on the blockchain
string public message;

// constructor, invoked when we deploy contract to blockchain
function Inbox(string newMessage) public {
message = newMessage;
}

function setMessage(string newMessage) public {
message = newMessage;
}

// function-name() function-type return-type
function getMessage() public view returns (string) {
return message;
}
}
118 changes: 118 additions & 0 deletions src/java/web3clj/solc/Inbox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package web3clj.solc;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;

/**
* <p>Auto generated code.
* <p><strong>Do not modify!</strong>
* <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
* or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the
* <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 4.8.4.
*/
@SuppressWarnings("rawtypes")
public class Inbox extends Contract {
public static final String BINARY = "608060405234801561001057600080fd5b50604051610514380380610514833981018060405281019080805182019291905050508060009080519060200190610049929190610050565b50506100f5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061009157805160ff19168380011785556100bf565b828001600101855582156100bf579182015b828111156100be5782518255916020019190600101906100a3565b5b5090506100cc91906100d0565b5090565b6100f291905b808211156100ee5760008160009055506001016100d6565b5090565b90565b610410806101046000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063368b87721461005c578063ce6d41de146100c5578063e21f37ce14610155575b600080fd5b34801561006857600080fd5b506100c3600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506101e5565b005b3480156100d157600080fd5b506100da6101ff565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561011a5780820151818401526020810190506100ff565b50505050905090810190601f1680156101475780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561016157600080fd5b5061016a6102a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101aa57808201518184015260208101905061018f565b50505050905090810190601f1680156101d75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101fb92919061033f565b5050565b606060008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102975780601f1061026c57610100808354040283529160200191610297565b820191906000526020600020905b81548152906001019060200180831161027a57829003601f168201915b5050505050905090565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103375780601f1061030c57610100808354040283529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061038057805160ff19168380011785556103ae565b828001600101855582156103ae579182015b828111156103ad578251825591602001919060010190610392565b5b5090506103bb91906103bf565b5090565b6103e191905b808211156103dd5760008160009055506001016103c5565b5090565b905600a165627a7a723058201a8692b28f48880175c7f0e650864d1e809dd193a465ffb1ed74696155cbc0740029";

public static final String FUNC_SETMESSAGE = "setMessage";

public static final String FUNC_GETMESSAGE = "getMessage";

public static final String FUNC_MESSAGE = "message";

@Deprecated
protected Inbox(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
}

protected Inbox(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
}

@Deprecated
protected Inbox(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}

protected Inbox(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
}

public RemoteFunctionCall<TransactionReceipt> setMessage(String newMessage) {
final Function function = new Function(
FUNC_SETMESSAGE,
Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(newMessage)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}

public RemoteFunctionCall<String> getMessage() {
final Function function = new Function(FUNC_GETMESSAGE,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
return executeRemoteCallSingleValueReturn(function, String.class);
}

public RemoteFunctionCall<String> message() {
final Function function = new Function(FUNC_MESSAGE,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
return executeRemoteCallSingleValueReturn(function, String.class);
}

@Deprecated
public static Inbox load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
return new Inbox(contractAddress, web3j, credentials, gasPrice, gasLimit);
}

@Deprecated
public static Inbox load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
return new Inbox(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}

public static Inbox load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
return new Inbox(contractAddress, web3j, credentials, contractGasProvider);
}

public static Inbox load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
return new Inbox(contractAddress, web3j, transactionManager, contractGasProvider);
}

public static RemoteCall<Inbox> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, String newMessage) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(newMessage)));
return deployRemoteCall(Inbox.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor);
}

public static RemoteCall<Inbox> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, String newMessage) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(newMessage)));
return deployRemoteCall(Inbox.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor);
}

@Deprecated
public static RemoteCall<Inbox> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String newMessage) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(newMessage)));
return deployRemoteCall(Inbox.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor);
}

@Deprecated
public static RemoteCall<Inbox> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String newMessage) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(newMessage)));
return deployRemoteCall(Inbox.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor);
}
}
119 changes: 119 additions & 0 deletions src/web3clj/solc.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
(ns web3clj.solc
(:require
[clojure.java.io :as io]
[web3clj.core :as w3cljc]
[web3clj.crypto :as w3cljcrypto]
[web3clj.evm :as w3cljevm]
[web3clj.protocol :as w3cljproto]
[web3clj.utils :as wu]
[web3clj.utils.numeric :as wun])
(:import
org.web3j.codegen.SolidityFunctionWrapperGenerator
(org.web3j.crypto
Credentials
WalletUtils)
(org.web3j.protocol
Web3j
Web3jService)
org.web3j.protocol.http.HttpService
(org.web3j.sokt
MainKt
SolcArguments
SolcInstance
SolcOutput
SolidityFile)))


(defn compile-contract
"Compile a given contract from a file and
return compiled information. Shape of returned
data :
{:abi <compiled-abi>
:bytecode <compiled-bytecode>
:ast <compiled-ast>}"
[file contract & {out :out solc-args :solc-args
:or {out "/tmp"
solc-args [SolcArguments/AST
SolcArguments/BIN
SolcArguments/ABI
SolcArguments/OVERWRITE
(.param (SolcArguments/OUTPUT_DIR)
(wu/func0 out))]}}]
(let [sol-file (SolidityFile. file)
solc (.getCompilerInstance sol-file ".web3j" false)
solc-args (into-array SolcArguments solc-args)]
(when (= 0 (.getExitCode (.execute solc solc-args)))
{:abi (slurp (str out "/" contract ".abi"))
:bytecode (slurp (str out "/" contract ".bin"))
:ast (slurp (str out "/" contract ".sol.ast"))})))


(defn generate-solidity-wrappers
"Generate java wrappers from compiled solidity contract files.
Alternatively you can use the ~web3j generate solidity~ cli tool
Note: this does not seem to work with codegen 5.0.0, works with 4.8.4!"
[^String bytecode-file
^String abi-file
^String java-src-path
contract-name
package-name]
(let [gen-wrapper (SolidityFunctionWrapperGenerator. (io/file bytecode-file)
(io/file abi-file)
(io/file java-src-path)
contract-name
package-name
true ; useJavaNativeTypes
true ; useJavaPrimitiveTypes
20)] ; address length in bytes, default is 20

(.generate gen-wrapper)))


(defn create-compiled-contract
"Compile solidity contract and spit it out to
files
Returns: dictionary with :abi and :bytecode keys"
[file contract-name out-path]
(let [{:keys [abi bytecode] :as out} (compile-contract file contract-name :out out-path)
file-name (str out-path "/" contract-name)]
(io/make-parents file-name)
(spit (str file-name ".abi") abi)
(spit (str file-name ".bytecode") bytecode)
out))


(comment
(let [{:keys [abi bytecode]} (create-compiled-contract "resources/contracts/Inbox.sol"
"Inbox"
"resources/out")]
(println "ABI is " abi))
(generate-solidity-wrappers "resources/out/Inbox.bytecode"
"resources/out/Inbox.abi"
"src/java"
"Inbox"
"web3clj.solc")
;; At this point you will need to restart the repl for it
;; to load this namespace.

(import web3clj.solc.Inbox)

;; Deploy a smart contract
(def web3-ganache (Web3j/build (HttpService. "http://localhost:7545")))
;; These credentials determine the author of the contract deployment
(def pr-key "8b246c57e1eb7ccec7705ce7889144292c37e02bec747da104b8981fdfb9fcfe")
(def local-wallet (Credentials/create pr-key))

(def inbox-contract (.send (Inbox/deploy web3-ganache
local-wallet
;; this comes from the ganache settings
(wun/->big-integer 20000000000)
;; eventually we required 302737 of gas
(wun/->big-integer 2000000)
"hello world")))

;; get the message from contract
(def contract-message (.send (.getMessage inbox-contract)))

;; update the message
;; who decides the gas price and gas limit on these transactions?
(.send (.setMessage inbox-contract "bye for now")))
12 changes: 11 additions & 1 deletion src/web3clj/utils.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns web3clj.utils
(:import [java.math BigDecimal]
[org.web3j.utils Convert Convert$Unit]))
[org.web3j.utils Convert Convert$Unit]
(kotlin.jvm.functions Function0)))

(def WEI Convert$Unit/WEI)
(def KWEI Convert$Unit/KWEI)
Expand Down Expand Up @@ -54,3 +55,12 @@
(defn wei->kether [kether-amount] (<-wei kether-amount KETHER))
(defn wei->mether [mether-amount] (<-wei mether-amount METHER))
(defn wei->gether [gether-amount] (<-wei gether-amount GETHER))


(defn func0
"A wrapper around the Function0 interface"
[s]
(reify Function0
(invoke
[this]
s)))