Liking cljdoc? Tell your friends :D

district-ui-smart-contracts

Build Status

Clojurescript re-mount module, that takes care of loading Ethereum smart-contract files.

Installation

This module is available as a Maven artifact from Clojars. The latest released version is:
Clojars Project

Include [district.ui.smart-contracts] in your CLJS file, where you use mount/start

API Overview

Warning: district0x modules are still in early stages, therefore API can change in a future.

district.ui.smart-contracts

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))

Adding abis into js bundle

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.

district.ui.smart-contracts.subs

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])))

district.ui.smart-contracts.events

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

district.ui.smart-contracts.deploy-events

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.

district.ui.smart-contracts.queries

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

Dependency on other district UI modules

Development

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 Monetta
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close