Clojurescript re-mount module, that helps managing web3 smart-contract transactions in following ways:
- Serves as central place to fire re-frame events after all transaction related events. Other modules can then easily hook into those events and provide additional features on top of it. Example of such module is district-ui-web3-tx-log-core.
- It stores transaction data in browser's localstorage, so they're persisted between sessions.
- It loads and uses recommended gas prices from ETH Gas Station.
Include [district.ui.web3-tx]
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.web3-tx
- district.ui.web3-tx.subs
- district.ui.web3-tx.events
- ::send-tx
- ::watch-pending-txs
- ::tx-hash
- ::tx-hash-error
- ::tx-success
- ::tx-error
- ::tx-receipt
- ::tx-loaded
- ::add-tx
- ::set-tx
- ::remove-tx
- ::clear-localstorage
- ::watch-recommended-gas-prices
- ::load-recommended-gas-prices
- ::set-recommended-gas-prices
- ::set-recommended-gas-price-option
- ::stop-watching-recommended-gas-prices
- district.ui.web3-tx.queries
This namespace contains web3-tx mount module.
You can pass following args to initiate this module:
:disable-using-localstorage?
Pass true if you don't want to store transaction data in a browser's localstorage:disable-loading-recommended-gas-prices?
Pass true if you don't want to load recommended gas prices:recommended-gas-prices-load-interval
Interval at which recommended gas prices should be loaded. Default 30000 (30 seconds):recommended-gas-price-option
Option which should be used from recommended gas prices. Possible options::fastest
,:fast
,:average
,:safe-low
. Default::average
(ns my-district.core
(:require [mount.core :as mount]
[district.ui.web3-tx]))
(-> (mount/with-args
{:web3 {:url "https://mainnet.infura.io/"}
:web3-tx {:disable-using-localstorage? true
:recommended-gas-price-option :safe-low}})
(mount/start))
re-frame subscriptions provided by this module:
Returns map of all transactions. Optionally, you can provide filter opts if you want to filter only transactions with a specific property in
tx data. For example it can be :status
, :from
, :to
.
There are 3 possible transaction statuses:
:tx.status/success
:tx.status/pending
:tx.status/error
(ns my-district.core
(:require [mount.core :as mount]
[district.ui.web3-tx :as subs]))
(defn home-page []
(let [pending-txs (subscribe [::subs/txs {:status :tx.status/pending}])]
(fn []
[:div "Your pending transactions: "]
(for [[tx-hash tx] @pending-txs]
[:div
{:key tx-hash}
"Transaction hash: " tx-hash]))))
Returns transaction with transaction hash tx-hash
Returns recommended has prices loaded from ETH Gas Station.
@(subscribe [::subs/recommended-gas-prices])
;; => {
;; :fast 9000000000
;; :fastest 20000000000
;; :speed 0.9819364005608542
;; :safe-low 1000000000
;; :avg-wait 1.5
;; :fastest-wait 0.4
;; :safe-low-wait 14
;; :block-num 7820908
;; :average 3000000000
;; :fast-wait 0.5
;; :block-time 12.660377358490566}
Returns recommended has price at key `recommended-gas-price-option``.
@(subscribe [::subs/recommended-gas-price])
;; => 3000000000
Returns option which will be used for gas prices.
@(subscribe [::subs/recommended-gas-price-option])
;; => :fastest
re-frame events provided by this module:
Sends Ethereum transaction. Pass same arguments as you'd pass to web3/call for state changing contract function.
(dispatch [::events/send-tx {:instance MintableToken
:fn :mint
:args [(first accounts) (web3/to-wei 1 :ether)]
:tx-opts {:from (first accounts) :gas 4500000}
:on-tx-hash [::tx-hash]
:on-tx-hash-n [[::tx-hash]]
:on-tx-hash-error [::tx-hash-error]
:on-tx-hash-error-n [[::tx-hash-error]]
:on-tx-success [::tx-success]
:on-tx-success-n [[::tx-success]]
:on-tx-error [::tx-error]
:on-tx-error-n [[::tx-error]]}])
Starts watching currently pending transactions. This event is fired at mount start.
Event fired when a transaction was sent and transaction hash was obtained. Use this event to hook into event flow.
Event fired when there was an error sending transaction. Use this event to hook into event flow.
Event fired when transaction was successfully processed. Use this event to hook into event flow.
(ns my-district.events
(:require [district.ui.web3-tx.events :as tx-events]
[re-frame.core :refer [reg-event-fx]]
[day8.re-frame.forward-events-fx]))
(reg-event-fx
::my-event
(fn []
{:register :my-forwarder
:events #{::tx-events/tx-success}
:dispatch-to [::do-something-after-tx-success]}))
Event fired when there was an error processing a tx. Use this event to hook into event flow.
Event fired when receipt for a tx was loaded. No matter if tx succeeded or failed. Use this event to hook into event flow.
After tx-receipt is fired, this module will also load a transaction (web3.eth.getTransaction
). This event is fired when
a transaction is loaded. Use this event to hook into event flow.
Adds new transaction hash into db, sets it as :tx.status/pending
.
Updates a transaction.
Removes transaction.
Clears transactions from localstorage.
Will start loading recommended gas prices at configured interval.
Loads recommended gas prices from ETH Gas Station and sets results into re-frame db.
Sets results from load-recommended-gas-prices
into re-frame db.
Sets option from recommended gas prices, that will be used for transaction gas price.
Stops loading interval for recommended gas prices.
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 ::txs
Works the same way as sub ::tx
Returns true is using localstorage is disabled.
Merges tx data into a transaction with hash tx-hash
and returns new re-frame db.
Removes transaction and returns new re-frame db.
Merges transactions and returns new re-frame db.
Merges recommended gas prices and returns new re-frame db.
Works the same way as sub ::recommended-gas-prices
.
Associates gas price option that will be used for transaction gas price.
Works the same way as sub ::recommended-gas-price-option
.
Works the same way as sub ::recommended-gas-price
.
Associates an opt into this module state. For internal purposes mainly.
- Setup local testnet
-
spin up a testnet instance in a separate shell
npx truffle develop
-
migrate contracts in
contracts/
foldernpx truffle migrate --network ganache --reset
- Run test suite:
- Browser
npx shadow-cljs watch test-browser
- open https://d0x-vm:6502
- tests refresh automatically on code change
- CI (Headless Chrome, Karma)
npx shadow-cljs compile test-ci
CHROME_BIN=`which chromium-browser` npx karma start karma.conf.js --single-run
- Build
- on merging pull request to master on GitHub, CI builds & publishes new version automatically
- update version in
build.clj
- to build:
clj -T:build jar
- to release:
clj -T:build deploy
(needsCLOJARS_USERNAME
andCLOJARS_PASSWORD
env vars to be set)