Added kyber extension
Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
parent
8ef905edfb
commit
16b657d6ee
|
@ -0,0 +1,227 @@
|
|||
{meta {:name "Kyber UI"
|
||||
:description "Kyber exchange"
|
||||
:documentation ""}
|
||||
|
||||
events/on-transaction-receipt
|
||||
(let [{value :value} properties]
|
||||
[store/put {:key "RECEIPT" :value value}])
|
||||
|
||||
events/on-trade-result
|
||||
(let [{value :value} properties]
|
||||
[ethereum/await-transaction-receipt {:interval 1000 :value value :on-success [on-transaction-receipt]}])
|
||||
|
||||
events/trade
|
||||
(let [{src-address :src-address dest-address :dest-address amount-in-wei :amount-in-wei address :address slippage :slippage} properties]
|
||||
[ethereum/send-transaction {:to "0x818E6FECD516Ecc3849DAf6845e3EC868087B755"
|
||||
:method "trade(address,uint256,address,address,uint256,uint256,address)"
|
||||
:gas "600000"
|
||||
:params [src-address amount-in-wei dest-address address "57896044618658097711785492504343953926634992332820282019728792003956564819968" slippage "0xD8a38Ae058fB6a6A6CB9517cF9Bc1730a6E15617"]
|
||||
:on-success [on-trade-result]}])
|
||||
events/approve
|
||||
(let [{src-address :src-address dest-address :dest-address address :address amount-in-wei :amount-in-wei slippage :slippage} properties]
|
||||
;; Approve Kyber contract for further transfer
|
||||
[ethereum/send-transaction {:to src-address
|
||||
:method "approve(address,uint256)"
|
||||
:params ["0x818E6FECD516Ecc3849DAf6845e3EC868087B755" amount-in-wei]
|
||||
:gas "100000"
|
||||
:on-success [trade {:address address :amount-in-wei amount-in-wei :slippage slippage :src-address src-address :dest-address dest-address}]}])
|
||||
|
||||
views/render-token
|
||||
(let [{name :name {source :source} :icon} properties]
|
||||
[view {:style {:height 64 :margin-horizontal 16 :flex-direction :row :align-items :center}}
|
||||
[image {:source source :style {:width 40 :height 40}}]
|
||||
[text {:style {:margin-left 16 :font-size 16 :color :black}} name]])
|
||||
|
||||
events/aputs
|
||||
(let [{key :key selection :selection source :source symbol :symbol rate :rate value :value} properties]
|
||||
[store/puts {:value [{:key key :value {:selection selection :source source :symbol symbol}}
|
||||
{:key "RATE" :value {:value rate}}
|
||||
{:key "AMOUNT-TO-RECEIVE" :value value}]}])
|
||||
|
||||
events/on-rate-result
|
||||
(let [{key :key amount :amount selection :selection source :source symbol :symbol [_ slippage :as result] :value} properties]
|
||||
[arithmetic {:operation :times :values [amount slippage]
|
||||
:on-result [aputs {:key key :amount amount :rate result :selection selection :source source :symbol symbol}]}])
|
||||
|
||||
;; TODO Consider Kyber tokens list (require view lifecycle?)
|
||||
;; TODO react on amount changes too
|
||||
;; TODO hook completion screens (require case support?)
|
||||
;; TODO proper error handling
|
||||
|
||||
events/on-src-rate-params-change
|
||||
(let [{key :key amount :amount amount-in-wei :amount-in-wei dest-address :dest-address address :address selection :name {source :source} :icon symbol :symbol} properties]
|
||||
[ethereum/call {:to "0x818E6FECD516Ecc3849DAf6845e3EC868087B755"
|
||||
:method "getExpectedRate(address,address,uint256)"
|
||||
:params [address dest-address amount-in-wei]
|
||||
:outputs ["uint256" "uint256"]
|
||||
:on-success [on-rate-result {:key key :amount amount :selection selection :source source :symbol symbol}]}])
|
||||
|
||||
events/on-dest-rate-params-change
|
||||
(let [{key :key amount :amount amount-in-wei :amount-in-wei src-address :src-address address :address selection :name {source :source} :icon symbol :symbol} properties]
|
||||
[ethereum/call {:to "0x818E6FECD516Ecc3849DAf6845e3EC868087B755"
|
||||
:method "getExpectedRate(address,address,uint256)"
|
||||
:params [src-address address amount-in-wei]
|
||||
:outputs ["uint256" "uint256"]
|
||||
:on-success [on-rate-result {:key key :amount amount :selection selection :source source :symbol symbol}]}])
|
||||
|
||||
events/bputs
|
||||
(let [{amount :amount rate :rate value :value} properties]
|
||||
[store/puts {:value [{:key "RATE" :value {:value rate}}
|
||||
{:key "AMOUNT" :value amount}
|
||||
{:key "AMOUNT-TO-RECEIVE" :value value}]}])
|
||||
|
||||
events/on-amount-rate-result
|
||||
(let [{amount :amount [_ slippage :as result] :result} properties]
|
||||
[arithmetic {:operation :times :values [amount slippage]
|
||||
:on-result [bputs {:amount amount :rate result}]}])
|
||||
|
||||
events/on-amount-params-change
|
||||
(let [{amount :value src-address :src-address dest-address :dest-address} properties]
|
||||
[ethereum/call {:to "0x818E6FECD516Ecc3849DAf6845e3EC868087B755"
|
||||
:method "getExpectedRate(address,address,uint256)"
|
||||
:params [src-address dest-address amount-in-wei]
|
||||
:outputs ["uint256" "uint256"]
|
||||
:on-success [on-amount-rate-result {:amount amount}]}])
|
||||
|
||||
events/store-amount
|
||||
(let [{amount :value} properties]
|
||||
[store/put {:key "AMOUNT" :value amount}])
|
||||
|
||||
views/sign-to-confirm
|
||||
(let [{color :color} properties]
|
||||
[view {:style {:flex-direction :row :margin-vertical 14 :align-items :center}}
|
||||
[view {:style {:flex 1}}]
|
||||
[text {:style {:color color :font-size 15 :margin-right 5}} "Sign to confirm"]
|
||||
[icon {:key :icons/forward :color color}]])
|
||||
|
||||
views/transaction-failed-panel
|
||||
(let [{} properties]
|
||||
[view {:style {:flex 1 :background-color "#4360df"}}
|
||||
[view {:style {:flex 1 :justify-content :center :align-items :center}}
|
||||
[view {:style {:background-color :white :width 56 :height 56 :border-radius 28 :align-items :center :justify-content :center}}
|
||||
[icon {:key :icons/ok :color "#4360df"}]]
|
||||
[text {:style {:color :white :font-size 17 :margin-top 16}} "Transaction Failed"]
|
||||
[text {:style {:color "rgba(255,255,255,0.6)" :font-size 15 :margin-top 8}} "Sorry :("]
|
||||
[view {:style {:height 1 :background-color :white :opacity 0.2}}]
|
||||
[view {:style {:flex 1}}]
|
||||
[touchable-opacity {:on-press [store/put {:key "completed?" :value false}]}
|
||||
[text {:style {:color :white :font-size 15 :margin-top 16}} "Try again"]]]])
|
||||
|
||||
views/transaction-pending-panel
|
||||
(let [{} properties]
|
||||
[view {:style {:flex 1 :background-color "#4360df"}}
|
||||
[view {:style {:flex 1 :justify-content :center :align-items :center :margin-top 200}}
|
||||
[view {:style {:background-color :white :width 56 :height 56 :border-radius 28 :align-items :center :justify-content :center}}
|
||||
[icon {:key :icons/ok :color "#4360df"}]]
|
||||
[text {:style {:color :white :font-size 17 :margin-top 16}} "Transaction Pending"]
|
||||
[text {:style {:color "rgba(255,255,255,0.6)" :font-size 15 :margin-top 8 :margin-horizontal 40}}
|
||||
"Your transaction is pending confirmation on the blockchain. You can check its status in your transaction history."]
|
||||
[view {:style {:flex 1}}]
|
||||
[view {:style {:height 1 :background-color :white :opacity 0.2}}]
|
||||
[touchable-opacity {:on-press [store/put {:key "completed?" :value false}]}
|
||||
[text {:style {:color :white :font-size 15 :margin-bottom 14 :margin-top 18}} "Back to wallet"]]]])
|
||||
|
||||
views/transaction-completed-panel
|
||||
(let [{tokenname1 :tokenname1 tokenname2 :tokenname2 source1 :source1 source2 :source2 address :address} properties]
|
||||
[view {:style {:flex 1 :background-color "#4360df"}}
|
||||
[view {:style {:flex 1 :justify-content :center :align-items :center}}
|
||||
[view {:style {:background-color :white :width 56 :height 56 :border-radius 28 :align-items :center :justify-content :center}}
|
||||
[icon {:key :icons/ok :color "#4360df"}]]
|
||||
[text {:style {:color :white :font-size 17 :margin-top 16}} "Transaction Confirmed"]
|
||||
[view {:style {:height 1 :background-color :white :opacity 0.2}}]
|
||||
[touchable-opacity {:on-press [store/put {:key "completed?" :value false}]}
|
||||
[text {:style {:color :white :font-size 15 :margin-top 16}} "Back to exchange"]]]
|
||||
[view {:style {:flex 1 :background-color :white :padding-horizontal 16 :padding-top 23}}
|
||||
[text {:style {:font-size 15}} "You exchanged"]
|
||||
[view {:style {:border-color "#EEF2F5" :border-radius 8 :border-width 1 :flex-direction :row :margin-top 6 :padding 15 :align-items :center}}
|
||||
[image {:source source1 :style {:width 30 :height 30}}]
|
||||
[text {:style {:flex 1 :font-size 15 :margin-left 12}} tokenname1]]
|
||||
[view {:style {:flex 1}}]
|
||||
[text {:style {:font-size 15}} "You received"]
|
||||
[view {:style {:border-color "#EEF2F5" :border-radius 8 :border-width 1 :flex-direction :row :margin-top 6 :padding 15 :align-items :center}}
|
||||
[image {:source source2 :style {:width 30 :height 30}}]
|
||||
[text {:style {:flex 1 :font-size 15 :margin-left 12}} tokenname2]]
|
||||
[view {:style {:flex 1}}]]])
|
||||
|
||||
views/transaction-panel
|
||||
(let [m properties
|
||||
{status :status} [store/get {:key "RECEIPT"}]]
|
||||
(if status
|
||||
[transaction-completed-panel m]
|
||||
[transaction-pending-panel m]))
|
||||
|
||||
views/kyber-panel
|
||||
{:component-will-mount [store/clear-all]
|
||||
:view
|
||||
(let [{address :address} properties
|
||||
visible-tokens [wallet/tokens {:visible true}]
|
||||
tokens [wallet/tokens]
|
||||
{tokenname1 :selection source1 :source src-symbol :symbol} [store/get {:key "SRC"}]
|
||||
{tokenname2 :selection source2 :source dest-symbol :symbol} [store/get {:key "DEST"}]
|
||||
completed? [store/get {:key "completed?"}]
|
||||
amount [store/get {:key "AMOUNT"}]
|
||||
amount-to-receive-in-wei [store/get {:key "AMOUNT-TO-RECEIVE"}]
|
||||
{[expected slippage-in-wei] :value} [store/get {:key "RATE"}]
|
||||
{slippage :amount} [wallet/token {:token "ETH" :amount-in-wei slippage-in-wei}] ;; Kyber returns slippage with 18 decimals
|
||||
{amount-to-receive :amount} [wallet/token {:token "ETH" :amount-in-wei amount-to-receive-in-wei}]
|
||||
{src-decimals :decimals src-address :address amount-in-wei :amount-in-wei} [wallet/token {:token src-symbol :amount amount}]
|
||||
{dest-decimals :decimals dest-address :address} [wallet/token {:token dest-symbol}]
|
||||
{balance :value} [wallet/balance {:token src-symbol}]]
|
||||
(if completed?
|
||||
[transaction-panel {:source1 source1 :source2 source2 :tokenname1 tokenname1 :tokenname2 tokenname2 :address completed?}]
|
||||
[view {:style {:flex 1 :background-color "#4360df" :padding-horizontal 16 :padding-top 20}}
|
||||
[scroll-view {:keyboard-should-persist-taps :always}
|
||||
[view {:style {:flex 1}}
|
||||
[text {:style {:color :white :font-size 15}} "I want to exchange"]
|
||||
[touchable-opacity {:on-press [selection-screen {:title "Choose asset" :items visible-tokens :on-select [on-src-rate-params-change {:key "SRC" :amount amount :dest-address dest-address :amount-in-wei amount-in-wei}]
|
||||
:render [render-token] :extractor-key :name}]}
|
||||
[view {:style {:flex-direction :row :margin-top 8 :border-radius 8 :height 52 :background-color "rgba(255,255,255,0.1)"
|
||||
:align-items :center :padding-horizontal 14}}
|
||||
[image {:source source1 :style {:width 30 :height 30}}]
|
||||
(if tokenname1
|
||||
[view {:style {:flex 1 :flex-direction :column}}
|
||||
[view {:style {:flex-direction :row}}
|
||||
[text {:style {:margin-left 16 :color :white :font-size 15}} tokenname1]
|
||||
[text {:style {:margin-left 16 :color :white :font-size 15 :opacity 0.6}} src-symbol]]
|
||||
[text {:style {:margin-left 16 :color :white :font-size 15 :opacity 0.6}} "Available: ${balance}"]]
|
||||
[text {:style {:flex 1 :color :white :margin-left 12}} "Select token"])
|
||||
[icon {:key :icons/forward :color :white}]]]
|
||||
[text {:style {:color :white :font-size 15 :margin-top 28}} "Amount"]
|
||||
[view {:style {:flex-direction :row :margin-top 8 :border-radius 8 :height 52 :background-color "rgba(255,255,255,0.1)"
|
||||
:align-items :center :padding-horizontal 14 :margin-bottom 32}}
|
||||
[input {:style {:color :white :flex 1} :placeholder "Specify amount..." :placeholder-text-color "rgba(255,255,255,0.6)" :selection-color :white :keyboard-type :decimal-pad
|
||||
:on-change [store-amount {:amount amount :src-address src-address :dest-address dest-address}]}]]
|
||||
[view {:style {:flex 1}}]
|
||||
[view {:style {:height 1 :background-color :white :opacity 0.2}}]
|
||||
[view {:style {:flex 1}}]
|
||||
[text {:style {:color :white :font-size 15 :margin-top 32}} "I want to recieve"]
|
||||
[touchable-opacity {:on-press [selection-screen {:title "Choose asset" :items tokens :on-select [on-dest-rate-params-change {:key "DEST" :amount amount :src-address src-address :amount-in-wei amount-in-wei}]
|
||||
:render [render-token] :extractor-key :name}]}
|
||||
[view {:style {:flex-direction :row :margin-top 8 :border-radius 8 :height 52 :background-color "rgba(255,255,255,0.1)"
|
||||
:align-items :center :padding-horizontal 14}}
|
||||
(when source2
|
||||
[image {:source source2 :style {:width 30 :height 30}}])
|
||||
(if tokenname2
|
||||
[view {:style {:flex 1 :flex-direction :row}}
|
||||
[text {:style {:margin-left 16 :color :white :font-size 15}} tokenname2]
|
||||
[text {:style {:margin-left 16 :color :white :font-size 15 :opacity 0.6}} dest-symbol]]
|
||||
[text {:style {:flex 1 :color :white :margin-left 12}} "Select token"])
|
||||
[icon {:key :icons/forward :color :white}]]]
|
||||
[text {:style {:color :white :opacity 0.6 :font-size 15 :margin-top 28}} "Amount to receive"]
|
||||
[view {:style {:flex-direction :row :margin-top 8 :border-radius 8 :height 52 :border-color "rgba(255,255,255,0.1)" :border-width 1
|
||||
:align-items :center :padding-horizontal 14}}
|
||||
[text {:style {:color :white}} amount-to-receive]]
|
||||
(when slippage
|
||||
[text {:style {:margin-top 16 :color :white :opacity 0.6}} "1 ${src-symbol} = ${slippage} ${dest-symbol}"])
|
||||
[view {:style {:flex 1}}]
|
||||
[text {:style {:color :white :opacity 0.6}} "Powered by Kyber Network"]
|
||||
[view {:style {:height 1 :background-color :white :opacity 0.2}}]]]
|
||||
(if slippage
|
||||
[touchable-opacity {:on-press [approve {:slippage slippage-in-wei :amount-in-wei amount-in-wei
|
||||
:src-address src-address :dest-address dest-address :address address}]}
|
||||
[sign-to-confirm {:color :white}]]
|
||||
[sign-to-confirm {:color "#FFFFFF66"}])]))}
|
||||
|
||||
hooks/wallet.settings.kyber
|
||||
{:label "Exchange Assets"
|
||||
:view [kyber-panel]}}
|
|
@ -53,7 +53,7 @@
|
|||
(if dev-mode?
|
||||
{:extensions/load {:extensions extensions
|
||||
:follow-up :extensions/add-to-registry}}
|
||||
{:dispatch [:extensions/update-hooks extensions]})))
|
||||
{:dispatch [:extensions/disable-all-hooks extensions]})))
|
||||
|
||||
(fx/defn switch-dev-mode [cofx dev-mode?]
|
||||
(fx/merge cofx
|
||||
|
|
|
@ -158,6 +158,11 @@
|
|||
(fn [{:keys [db]} [_ {id :id} {:keys [key]}]]
|
||||
{:db (update-in db [:extensions/store id] dissoc key)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:store/clear-all
|
||||
(fn [{:keys [db]} [_ {id :id} _]]
|
||||
{:db (update db :extensions/store dissoc id)}))
|
||||
|
||||
(defn- json? [res]
|
||||
(when-let [type (get-in res [:headers "content-type"])]
|
||||
(string/starts-with? type "application/json")))
|
||||
|
@ -223,8 +228,7 @@
|
|||
(re-frame/reg-event-fx
|
||||
:ipfs/add
|
||||
(fn [_ [_ _ {:keys [value on-success on-failure]}]]
|
||||
(let [formdata (doto
|
||||
(js/FormData.)
|
||||
(let [formdata (doto (js/FormData.)
|
||||
(.append constants/ipfs-add-param-name value))]
|
||||
{:http-raw-post (merge {:url constants/ipfs-add-url
|
||||
:body formdata
|
||||
|
@ -316,9 +320,10 @@
|
|||
(js/clearTimeout id))
|
||||
(reset! current (js/setTimeout #(on-input-change-text on-change value) delay)))
|
||||
|
||||
(defn input [{:keys [keyboard-type style on-change change-delay placeholder placeholder-text-color]}]
|
||||
(defn input [{:keys [keyboard-type style on-change change-delay placeholder placeholder-text-color selection-color]}]
|
||||
[react/text-input (merge {:placeholder placeholder}
|
||||
(when placeholder-text-color {:placeholder-text-color placeholder-text-color})
|
||||
(when selection-color {:selection-color selection-color})
|
||||
(when style {:style style})
|
||||
(when keyboard-type {:keyboard-type keyboard-type})
|
||||
(when on-change
|
||||
|
@ -402,7 +407,7 @@
|
|||
'touchable-opacity {:value touchable-opacity :properties {:on-press :event}}
|
||||
'icon {:value icon :properties {:key :keyword :color :any}}
|
||||
'image {:value image :properties {:uri :string :source :string}}
|
||||
'input {:value input :properties {:on-change :event :placeholder :string :keyboard-type :keyword :change-delay? :number :placeholder-text-color :any}}
|
||||
'input {:value input :properties {:on-change :event :placeholder :string :keyboard-type :keyword :change-delay? :number :placeholder-text-color :any :selection-color :any}}
|
||||
'button {:value button :properties {:enabled :boolean :disabled :boolean :on-click :event}}
|
||||
'link {:value link :properties {:uri :string}}
|
||||
'list {:value list :properties {:data :vector :item-view :view :key? :keyword}}
|
||||
|
@ -495,6 +500,9 @@
|
|||
{:permissions [:read]
|
||||
:value :store/clear
|
||||
:arguments {:key :string}}
|
||||
'store/clear-all
|
||||
{:permissions [:read]
|
||||
:value :store/clear-all}
|
||||
'http/get
|
||||
{:permissions [:read]
|
||||
:value :http/get
|
||||
|
@ -519,7 +527,7 @@
|
|||
'ipfs/add
|
||||
{:permissions [:read]
|
||||
:value :ipfs/add
|
||||
:arguments {:value :string
|
||||
:arguments {:value :string
|
||||
:on-success :event
|
||||
:on-failure? :event}}
|
||||
'ethereum/transaction-receipt
|
||||
|
@ -528,6 +536,13 @@
|
|||
:arguments {:value :string
|
||||
:on-success :event
|
||||
:on-failure? :event}}
|
||||
'ethereum/await-transaction-receipt
|
||||
{:permissions [:read]
|
||||
:value :extensions/ethereum-await-transaction-receipt
|
||||
:arguments {:value :string
|
||||
:interval :number
|
||||
:on-success :event
|
||||
:on-failure? :event}}
|
||||
'ethereum/sign
|
||||
{:permissions [:read]
|
||||
:value :extensions/ethereum-sign
|
||||
|
|
|
@ -85,9 +85,9 @@
|
|||
|
||||
(defn- rpc-dispatch [error result f on-success on-failure]
|
||||
(when result
|
||||
(re-frame/dispatch (on-success {:result (f result)})))
|
||||
(re-frame/dispatch (on-success {:value (f result)})))
|
||||
(when (and error on-failure)
|
||||
(re-frame/dispatch (on-failure {:result error}))))
|
||||
(re-frame/dispatch (on-failure {:value error}))))
|
||||
|
||||
(defn- rpc-handler [o f on-success on-failure]
|
||||
(let [{:keys [error result]} (types/json->clj o)]
|
||||
|
@ -249,7 +249,7 @@
|
|||
(defn- parse-receipt [m]
|
||||
(when m
|
||||
(let [{:keys [status transactionHash transactionIndex blockHash blockNumber from to cumulativeGasUsed gasUsed contractAddress logs logsBloom]} m]
|
||||
{:status (abi-spec/hex-to-number status)
|
||||
{:status (= 1 (abi-spec/hex-to-number status))
|
||||
:transaction-hash transactionHash
|
||||
:transaction-index (abi-spec/hex-to-number transactionIndex)
|
||||
:block-hash blockHash
|
||||
|
@ -267,6 +267,15 @@
|
|||
(fn [_ [_ _ {:keys [value] :as m}]]
|
||||
(rpc-call constants/web3-transaction-receipt [value] parse-receipt m)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:extensions/ethereum-await-transaction-receipt
|
||||
(fn [_ [_ _ {:keys [value interval on-success] :as m}]]
|
||||
(let [id (atom nil)
|
||||
new-on-success (fn [o] (js/clearInterval @id) (on-success o))]
|
||||
(reset! id (js/setInterval #(rpc-call constants/web3-transaction-receipt [value] parse-receipt
|
||||
(assoc m :on-success new-on-success)) interval))
|
||||
nil)))
|
||||
|
||||
(defn- event-topic-enc [event params]
|
||||
(let [eventid (str event "(" (string/join "," params) ")")]
|
||||
(abi-spec/sha3 eventid)))
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
extension-hooks))
|
||||
hooks))))
|
||||
|
||||
(fx/defn disable-hooks
|
||||
[{:keys [db] :as cofx} extension-id]
|
||||
(update-hooks cofx hooks/unhook extension-id))
|
||||
|
||||
(fx/defn add-to-registry
|
||||
[{:keys [db] :as cofx} extension-id extension-data active?]
|
||||
(let [{:keys [hooks]} extension-data
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
(extensions.registry/add-to-registry cofx extension-key data active?)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:extensions/update-hooks
|
||||
:extensions/disable-all-hooks
|
||||
(fn [cofx [_ extensions]]
|
||||
(apply fx/merge cofx (map (fn [{:keys [url]}]
|
||||
(extensions.registry/update-hooks cofx url))
|
||||
(apply fx/merge cofx (map (fn [{:keys [id]}]
|
||||
(extensions.registry/disable-hooks cofx id))
|
||||
extensions))))
|
||||
|
|
Loading…
Reference in New Issue