Clojurescript re-mount module, that takes care of loading Ethereum smart-contract files.
This module is available as a Maven artifact from Clojars. The latest released version is:
Include [district.ui.smart-contracts]
in your CLJS file, where you use mount/start
Warning: district0x modules are still in early stages, therefore API can change in a future.
This namespace contains smart-contracts mount module. Once you start mount it'll take care of loading smart contract files.
You can pass following args to initiate this module:
:disable-loading-at-start?
Pass true if you don't want load ABIs or BINs at start:contracts
A map of smart-contracts to load:load-bin?
Pass true if you want to load BIN files as well:format
The compiled contracts output format, can be one of :solc-abi-bin :truffle-json:load-method
How to take contracts content to the browser. Possible values :request(default), :use-loaded (see adding abis into js bundle):contracts-path
Path where contracts should be loaded from. Default: "./contracts/build/"
:contracts-version
Pass some version for bypassing browser's cache after deploying new contracts to production.
Pass :no-cache
if you want to invalidate browser cache on every request (useful for development):request-timeout
Request timeout for loading files. Default: 10000 (10s)Passed :contracts
should have following format:
(ns my-district.smart-contracts)
(def smart-contracts
{:my-contract {:name "MyContract" ;; ABI and BIN is loaded by this name
:address "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98"
;; optional, if not provided, will try to load
:abi nil
;; optional, if not provided, will try to load
:bin nil
;; optional, path would overwrite generic :contracts-path
:path nil
;; optional, path would overwrite generic :contracts-version
:version nil}})
Starting the module may look like this:
(ns my-district.core
(:require [mount.core :as mount]
[district.ui.smart-contracts]
[my-district.smart-contracts]))
(-> (mount/with-args
{:web3 {:url "https://mainnet.infura.io/"}
:smart-contracts {:contracts my-district.smart-contracts/smart-contracts
:contracts-path "./"}})
(mount/start))
In order to use the option :load-method :use-loaded you need to provide some info at build time so contracts abis can be included in the bundle. You provide this information via environment variables at build time.
Example:
SMART_CONTRACTS=./src/memefactory/shared/smart_contracts.cljs
SMART_CONTRACTS_BUILD_PATH=./resources/public/contracts/build/
SMART_CONTRACTS_SKIP=ds-guard,param-change-registry-db,meme-registry-db,minime-token-factory
Be aware that using this method is only supported for contracts compiled in the truffle json format.
re-frame subscriptions provided by this module:
::contracts
Returns all contracts.
::contract [contract-key]
Returns contract by contract-key
::contract-address [contract-key]
Returns address of a contract.
::contract-abi [contract-key]
Returns ABI of a contract.
::contract-bin [contract-key]
Returns BIN of a contract.
::contract-name [contract-key]
Returns name of a contract.
::instance [contract-key]
Returns web3 instance of a contract.
(ns my-district.home-page
(:require [district.ui.smart-contracts.subs :as contracts-subs]
[re-frame.core :refer [subscribe]]))
(defn home-page []
(let [contract-abi (subscribe [::contracts-subs/contract-abi :my-contract])]
(fn []
[:div "MyContract ABI is: " @contract-abi])))
re-frame events provided by this module:
::load-contracts [opts]
Loads smart contracts. Pass same args as to mount start.
::contract-loaded
Event fired when a single file was loaded. Either ABI or BIN.
::contracts-loaded
Event fired when all smart contract files have been loaded. Use this event to hook into event flow from your modules. One example using re-frame-forward-events-fx may look like this:
(ns my-district.events
(:require [district.ui.smart-contracts.events :as contracts-events]
[re-frame.core :refer [reg-event-fx]]
[day8.re-frame.forward-events-fx]))
(reg-event-fx
::my-event
(fn []
{:register :my-forwarder
:events #{::contracts-events/contracts-loaded}
:dispatch-to [::do-something]}))
::set-contract [contract-key contract]
Sets new contract into re-frame db
::contract-load-failed
Fired when there was an error loading contract file
Events useful for deploying contracts. This namespace is meant to be used only in tests or very simple apps. Any larger application should be doing smart-contract deployment on server-side via district-server-smart-contracts.
::deploy-contract [contract-key opts]
Deploys a smart-contract of key contract-key
and saves new address into re-frame db.
(ns my-district.core
(:require [mount.core :as mount]
[district.ui.smart-contracts]
[district.ui.smart-contracts.deploy-events :as deploy-events]
[district.ui.smart-contracts.queries :as queries]))
(-> (mount/with-args
{:web3 {:url "http://localhost:8549"}
:smart-contracts
{:disable-loading-at-start? true
:contracts {:deploy-test-contract {:name "DeployTestContract"
:abi (js/JSON.parse "[{\"inputs\":[{\"name\":\"someNumber\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]")
:bin "0x60606040523415600e57600080fd5b604051602080607183398101604052808051915050801515602e57600080fd5b50603580603c6000396000f3006060604052600080fd00a165627a7a72305820f6c231e485f5b65831c99412cbcad5b4e41a4b69d40f3d4db8de3a38137701fb0029"}}}})
(mount/start))
(dispatch [::deploy-events/deploy-contract :deploy-test-contract {:gas 4500000
:arguments [1]
:from "0xb2930b35844a230f00e51431acae96fe543a0347"
:on-success [::optional-callback]
:on-error [::optional-error-callback]}])
When successfully deployed, you'll be able to access contract instance and address same way as other contracts
(queries/contract-address db :deploy-test-contract)
(queries/instance db :deploy-test-contract)
::contract-deploy-failed
Event fired when deploying a contract failed.
DB queries provided by this module:
You should use them in your events, instead of trying to get this module's
data directly with get-in
into re-frame db.
contracts [db]
Works the same way as sub ::contracts
contract [db contract-key]
Works the same way as sub ::contract
contract-address [db contract-key]
Works the same way as sub ::contract-address
contract-abi [db contract-key]
Works the same way as sub ::contract-abi
contract-bin [db contract-key]
Works the same way as sub ::contract-bin
contract-name [db contract-key]
Works the same way as sub ::contract-name
instance [db contract-key]
Works the same way as sub ::instance
merge-contracts [db contracts]
Merges contracts and returns new re-frame db
merge-contract [db contract-key]
Merges a contract and returns new re-frame db
assoc-contract-abi [db contract-key abi]
Associates ABI to contract and returns new re-frame db
assoc-contract-bin [db contract-key bin]
Associates BIN to contract and returns new re-frame db
lein deps
# Start ganache blockchain with 1s block time
ganache-cli -p 8549 -b 1 --noVMErrorsOnRPCResponse
# To run tests and rerun on changes
lein doo chrome tests
Can you improve this documentation? These fine people already did:
madvas & Juan MonettaEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close