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.
- district.ui.smart-contracts
- district.ui.smart-contracts.subs
- district.ui.smart-contracts.events
- district.ui.smart-contracts.deploy-events
- district.ui.smart-contracts.queries
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:
Returns all contracts.
Returns contract by contract-key
Returns address of a contract.
Returns ABI of a contract.
Returns BIN of a contract.
Returns name of a contract.
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:
Loads smart contracts. Pass same args as to mount start.
Event fired when a single file was loaded. Either ABI or BIN.
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]}))
Sets new contract into re-frame db
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.
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)
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.
Works the same way as sub ::contracts
Works the same way as sub ::contract
Works the same way as sub ::contract-address
Works the same way as sub ::contract-abi
Works the same way as sub ::contract-bin
Works the same way as sub ::contract-name
Works the same way as sub ::instance
Merges contracts and returns new re-frame db
Merges a contract and returns new re-frame db
Associates ABI to contract and returns new re-frame db
Associates BIN to contract and returns new re-frame db
yarn install
# Start ganache blockchain with 1s block time
ganache-cli -p 8549 -b 1 --noVMErrorsOnRPCResponse
- Build:
npx shadow-cljs watch test-browser
- Tests: http://d0x-vm:6502
- Build:
npx shadow-cljs compile test-ci
- Tests:
CHROME_BIN=`which chromium-browser` npx karma start karma.conf.js --single-run
- Build:
clj -T:build jar
- Release:
clj -T:build deploy