feat: wallet router v2 (#20631)

* add v2 method

* rename v2 to get-suggested-route

* remove timestamp check on success

* handle async signal for suggestion

* fix stop get suggested routes

* address feedback

* rename get-suggest-route

* prefer lazy seq

* fix formatting

* update suggested routes success

* refactor get-in calls in start-get-suggested-routes

* move transformations to data store

* clean suggested routes immediately

* fix lint

* pass precision as ar

* change test name

* fix big number division error (issues 1,2)

* only trigger router fetch when there address (to/from)

* check response data for error response when routes received via signal

* update status-go

* fix: test failure

* update status go

* handle error message for generic errors
This commit is contained in:
BalogunofAfrica 2024-07-26 12:23:09 +01:00 committed by GitHub
parent 737d8c4d53
commit 2e9fa22e4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 276 additions and 176 deletions

View File

@ -38,6 +38,9 @@
"wallet"
{:fx [[:dispatch [:wallet/signal-received event-js]]]}
"wallet.suggested.routes"
{:fx [[:dispatch [:wallet/handle-suggested-routes (transforms/js->clj event-js)]]]}
"envelope.sent"
(messages.transport/update-envelopes-status
cofx

View File

@ -9,7 +9,7 @@
(defn view
[]
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/clean-routes-calculation]))
(hot-reload/use-safe-unmount #(rf/dispatch [:wallet/stop-get-suggested-routes]))
[rn/view {:style style/bridge-send-wrapper}
[input-amount/view
{:current-screen-id :screen/wallet.bridge-input-amount

View File

@ -5,6 +5,7 @@
[clojure.string :as string]
[status-im.constants :as constants]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.send.utils :as send-utils]
[utils.collection :as utils.collection]
[utils.money :as money]
[utils.number :as utils.number]
@ -188,3 +189,77 @@
:removed-account-addresses removed-account-addresses
:updated-keypairs-by-id updated-keypairs-by-id
:updated-accounts-by-address updated-accounts-by-address}))
(defn- rename-keys-to-kebab-case
[m]
(set/rename-keys m (zipmap (keys m) (map transforms/->kebab-case-keyword (keys m)))))
(defn rpc->suggested-routes
[suggested-routes]
(cond
(map? suggested-routes)
(into {}
(for [[k v] (rename-keys-to-kebab-case suggested-routes)]
[k (rpc->suggested-routes v)]))
(vector? suggested-routes)
(map rpc->suggested-routes suggested-routes)
:else suggested-routes))
(def ^:private precision 6)
(defn new->old-route-path
[new-path]
(let [bonder-fees (:tx-bonder-fees new-path)
token-fees (+ (money/wei->ether bonder-fees)
(money/wei->ether
(:tx-token-fees new-path)))]
{:from (:from-chain new-path)
:amount-in-locked (:amount-in-locked new-path)
:amount-in (:amount-in new-path)
:max-amount-in "0x0"
:gas-fees {:gas-price "0"
:base-fee (send-utils/convert-to-gwei (:tx-base-fee
new-path)
precision)
:max-priority-fee-per-gas (send-utils/convert-to-gwei (:tx-priority-fee
new-path)
precision)
:max-fee-per-gas-low (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:low])
precision)
:max-fee-per-gas-medium (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:medium])
precision)
:max-fee-per-gas-high (send-utils/convert-to-gwei
(get-in
new-path
[:suggested-levels-for-max-fees-per-gas
:high])
precision)
:l-1-gas-fee (send-utils/convert-to-gwei (:tx-l-1-fee
new-path)
precision)
:eip-1559-enabled true}
:bridge-name (:processor-name new-path)
:amount-out (:amount-out new-path)
:approval-contract-address (:approval-contract-address new-path)
:approval-required (:approval-required new-path)
:estimated-time (:estimated-time new-path)
:approval-gas-fees (* (money/wei->ether (get-in new-path
[:suggested-levels-for-max-fees-per-gas
:medium]))
(:approval-gas-amount new-path))
:to (:to-chain new-path)
:bonder-fees bonder-fees
:approval-amount-required (:approval-amount-required new-path)
;; :cost () ;; tbd not used on desktop
:token-fees token-fees
:gas-amount (:tx-gas-amount new-path)}))

View File

@ -1,19 +1,18 @@
(ns status-im.contexts.wallet.send.events
(:require
[camel-snake-kebab.extras :as cske]
[clojure.string :as string]
[native-module.core :as native-module]
[status-im.constants :as constants]
[status-im.contexts.wallet.collectible.utils :as collectible.utils]
[status-im.contexts.wallet.common.utils :as utils]
[status-im.contexts.wallet.common.utils.networks :as network-utils]
[status-im.contexts.wallet.data-store :as data-store]
[status-im.contexts.wallet.send.utils :as send-utils]
[taoensso.timbre :as log]
[utils.address :as address]
[utils.money :as money]
[utils.number]
[utils.re-frame :as rf]
[utils.transforms :as transforms]))
[utils.re-frame :as rf]))
(rf/reg-event-fx :wallet/clean-send-data
(fn [{:keys [db]}]
@ -24,40 +23,35 @@
{:db (assoc-in db [:wallet :ui :send :select-address-tab] tab)}))
(rf/reg-event-fx :wallet/suggested-routes-success
(fn [{:keys [db]} [suggested-routes timestamp]]
(when (= (get-in db [:wallet :ui :send :suggested-routes-call-timestamp]) timestamp)
(let [suggested-routes-data (cske/transform-keys transforms/->kebab-case-keyword
suggested-routes)
chosen-route (:best suggested-routes-data)
token (get-in db [:wallet :ui :send :token])
collectible (get-in db [:wallet :ui :send :collectible])
token-display-name (get-in db [:wallet :ui :send :token-display-name])
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
receiver-network-values (get-in db [:wallet :ui :send :receiver-network-values])
sender-network-values (get-in db [:wallet :ui :send :sender-network-values])
tx-type (get-in db [:wallet :ui :send :tx-type])
disabled-from-chain-ids (get-in db [:wallet :ui :send :disabled-from-chain-ids] [])
from-locked-amounts (get-in db [:wallet :ui :send :from-locked-amounts] {})
(fn [{:keys [db]} [suggested-routes-data]]
(let [chosen-route (:best suggested-routes-data)
{:keys [token collectible token-display-name
receiver-networks
receiver-network-values
sender-network-values tx-type
disabled-from-chain-ids
from-locked-amounts]} (get-in db [:wallet :ui :send])
token-decimals (if collectible 0 (:decimals token))
native-token? (and token (= token-display-name "ETH"))
routes-available? (pos? (count chosen-route))
token-networks (:networks token)
token-networks-ids (when token-networks (mapv #(:chain-id %) token-networks))
from-network-amounts-by-chain (send-utils/network-amounts-by-chain {:route chosen-route
:token-decimals
token-decimals
:native-token?
native-token?
token-networks-ids (when token-networks
(map #(:chain-id %) token-networks))
from-network-amounts-by-chain (send-utils/network-amounts-by-chain
{:route chosen-route
:token-decimals token-decimals
:native-token? native-token?
:receiver? false})
from-network-values-for-ui (send-utils/network-values-for-ui from-network-amounts-by-chain)
to-network-amounts-by-chain (send-utils/network-amounts-by-chain {:route chosen-route
:token-decimals
token-decimals
:native-token?
native-token?
from-network-values-for-ui (send-utils/network-values-for-ui
from-network-amounts-by-chain)
to-network-amounts-by-chain (send-utils/network-amounts-by-chain
{:route chosen-route
:token-decimals token-decimals
:native-token? native-token?
:receiver? true})
to-network-values-for-ui (send-utils/network-values-for-ui to-network-amounts-by-chain)
sender-possible-chain-ids (mapv :chain-id sender-network-values)
to-network-values-for-ui (send-utils/network-values-for-ui
to-network-amounts-by-chain)
sender-possible-chain-ids (map :chain-id sender-network-values)
sender-network-values (if routes-available?
(send-utils/network-amounts
{:network-values
@ -87,23 +81,24 @@
receiver-network-values)
vec
(conj {:type :edit})))
network-links (when routes-available?
(send-utils/network-links chosen-route
sender-network-values
receiver-network-values))]
{:db (-> db
(assoc-in [:wallet :ui :send :suggested-routes] suggested-routes-data)
(assoc-in [:wallet :ui :send :route] chosen-route)
(assoc-in [:wallet :ui :send :from-values-by-chain] from-network-values-for-ui)
(assoc-in [:wallet :ui :send :to-values-by-chain] to-network-values-for-ui)
(assoc-in [:wallet :ui :send :sender-network-values] sender-network-values)
(assoc-in [:wallet :ui :send :receiver-network-values] receiver-network-values)
(assoc-in [:wallet :ui :send :network-links] network-links)
(assoc-in [:wallet :ui :send :loading-suggested-routes?] false))}))))
{:db (update-in db
[:wallet :ui :send]
assoc
:suggested-routes suggested-routes-data
:route chosen-route
:from-values-by-chain from-network-values-for-ui
:to-values-by-chain to-network-values-for-ui
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values
:network-links network-links
:loading-suggested-routes? false)})))
(rf/reg-event-fx :wallet/suggested-routes-error
(fn [{:keys [db]} [error]]
(fn [{:keys [db]} [error-message]]
(let [cleaned-sender-network-values (-> (get-in db [:wallet :ui :send :sender-network-values])
(send-utils/reset-loading-network-amounts-to-zero))
cleaned-receiver-network-values (-> (get-in db [:wallet :ui :send :receiver-network-values])
@ -120,7 +115,7 @@
[:toasts/upsert
{:id :send-transaction-error
:type :negative
:text (:message error)}]]]})))
:text error-message}]]]})))
(rf/reg-event-fx :wallet/clean-suggested-routes
(fn [{:keys [db]}]
@ -135,8 +130,7 @@
:sender-network-values
:receiver-network-values
:network-links
:loading-suggested-routes?
:suggested-routes-call-timestamp)}))
:loading-suggested-routes?)}))
(rf/reg-event-fx :wallet/clean-send-address
(fn [{:keys [db]}]
@ -177,7 +171,7 @@
(assoc-in [:wallet :ui :send :receiver-preferred-networks] receiver-networks)
(assoc-in [:wallet :ui :send :receiver-networks] receiver-networks))
:fx [(when (and collectible-tx? one-collectible?)
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@ -189,7 +183,7 @@
(fn [{:keys [db]} [selected-networks]]
(let [amount (get-in db [:wallet :ui :send :amount])]
{:db (assoc-in db [:wallet :ui :send :receiver-networks] selected-networks)
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]]})))
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount amount}]]]})))
(rf/reg-event-fx
:wallet/set-token-to-send
@ -300,7 +294,7 @@
one-collectible?
(assoc-in [:wallet :ui :send :amount] 1))
:fx [(when (and one-collectible? recipient-set?)
[:dispatch [:wallet/get-suggested-routes {:amount 1}]])
[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]])
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen current-screen
@ -311,7 +305,7 @@
:wallet/set-collectible-amount-to-send
(fn [{db :db} [{:keys [stack-id amount]}]]
{:db (assoc-in db [:wallet :ui :send :amount] amount)
:fx [[:dispatch [:wallet/get-suggested-routes {:amount amount}]]
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount amount}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id
@ -347,7 +341,7 @@
(fn [{:keys [db]}]
(let [keys-to-remove [:to-values-by-chain :network-links :sender-network-values :route
:receiver-network-values :suggested-routes :from-values-by-chain
:loading-suggested-routes? :suggested-routes-call-timestamp]]
:loading-suggested-routes?]]
{:db (update-in db [:wallet :ui :send] #(apply dissoc % keys-to-remove))})))
(rf/reg-event-fx :wallet/disable-from-networks
@ -382,38 +376,33 @@
(when (empty? sender-network-values) :sender-network-values)
(when (empty? receiver-network-values) :receiver-network-values)))})))
(rf/reg-event-fx :wallet/get-suggested-routes
(fn [{:keys [db now]} [{:keys [amount updated-token]}]]
(rf/reg-event-fx :wallet/start-get-suggested-routes
(fn [{:keys [db]} [{:keys [amount amount-out updated-token] :as args :or {amount-out "0"}}]]
(let [wallet-address (get-in db [:wallet :current-viewing-account-address])
token (or updated-token (get-in db [:wallet :ui :send :token]))
transaction-type (get-in db [:wallet :ui :send :tx-type])
collectible (get-in db [:wallet :ui :send :collectible])
to-address (get-in db [:wallet :ui :send :to-address])
receiver-networks (get-in db [:wallet :ui :send :receiver-networks])
disabled-from-chain-ids (or (get-in db [:wallet :ui :send :disabled-from-chain-ids]) [])
from-locked-amounts (or (get-in db [:wallet :ui :send :from-locked-amounts]) {})
{:keys [token tx-type collectible to-address
receiver-networks disabled-from-chain-ids
from-locked-amounts bridge-to-chain-id]
:or {token updated-token}} (get-in db [:wallet :ui :send])
test-networks-enabled? (get-in db [:profile/profile :test-networks-enabled?])
networks ((if test-networks-enabled? :test :prod)
(get-in db [:wallet :networks]))
network-chain-ids (map :chain-id networks)
bridge-to-chain-id (get-in db [:wallet :ui :send :bridge-to-chain-id])
token-decimal (when token (:decimals token))
token-id (utils/format-token-id token collectible)
to-token-id ""
network-preferences (if token [] [(get-in collectible [:id :contract-id :chain-id])])
gas-rates constants/gas-rate-medium
to-hex (fn [v] (send-utils/amount-in-hex v (if token token-decimal 0)))
amount-in (to-hex amount)
amount-out (to-hex amount-out)
from-address wallet-address
disabled-from-chain-ids disabled-from-chain-ids
disabled-to-chain-ids (if (= transaction-type :tx/bridge)
disabled-to-chain-ids (if (= tx-type :tx/bridge)
(filter #(not= % bridge-to-chain-id) network-chain-ids)
(filter (fn [chain-id]
(not (some #(= chain-id %)
receiver-networks)))
network-chain-ids))
from-locked-amount (update-vals from-locked-amounts to-hex)
transaction-type-param (case transaction-type
transaction-type (case tx-type
:tx/collectible-erc-721 constants/send-type-erc-721-transfer
:tx/collectible-erc-1155 constants/send-type-erc-1155-transfer
:tx/bridge constants/send-type-bridge
@ -421,35 +410,33 @@
balances-per-chain (when token (:balances-per-chain token))
sender-token-available-networks-for-suggested-routes
(when token
(send-utils/token-available-networks-for-suggested-routes {:balances-per-chain
balances-per-chain
:disabled-chain-ids
disabled-from-chain-ids
(send-utils/token-available-networks-for-suggested-routes
{:balances-per-chain balances-per-chain
:disabled-chain-ids disabled-from-chain-ids
:only-with-balance? true}))
receiver-token-available-networks-for-suggested-routes
(when token
(send-utils/token-available-networks-for-suggested-routes {:balances-per-chain
balances-per-chain
:disabled-chain-ids
disabled-from-chain-ids
(send-utils/token-available-networks-for-suggested-routes
{:balances-per-chain balances-per-chain
:disabled-chain-ids disabled-from-chain-ids
:only-with-balance? false}))
token-networks-ids (when token (mapv #(:chain-id %) (:networks token)))
token-networks-ids (when token (map #(:chain-id %) (:networks token)))
sender-network-values (when sender-token-available-networks-for-suggested-routes
(send-utils/loading-network-amounts
{:valid-networks
(if (= transaction-type :tx/bridge)
(if (= tx-type :tx/bridge)
(remove #(= bridge-to-chain-id %)
sender-token-available-networks-for-suggested-routes)
sender-token-available-networks-for-suggested-routes)
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type transaction-type
:tx-type tx-type
:receiver? false}))
receiver-network-values (when receiver-token-available-networks-for-suggested-routes
(send-utils/loading-network-amounts
{:valid-networks
(if (= transaction-type :tx/bridge)
(if (= tx-type :tx/bridge)
(filter
#(= bridge-to-chain-id %)
receiver-token-available-networks-for-suggested-routes)
@ -457,40 +444,70 @@
:disabled-chain-ids disabled-from-chain-ids
:receiver-networks receiver-networks
:token-networks-ids token-networks-ids
:tx-type transaction-type
:tx-type tx-type
:receiver? true}))
request-params [transaction-type-param
from-address
to-address
amount-in
token-id
to-token-id
disabled-from-chain-ids
disabled-to-chain-ids
network-preferences
gas-rates
from-locked-amount]]
{:db (cond-> db
:always (assoc-in [:wallet :ui :send :amount] amount)
:always (assoc-in [:wallet :ui :send :loading-suggested-routes?] true)
:always (assoc-in [:wallet :ui :send :sender-network-values]
sender-network-values)
:always (assoc-in [:wallet :ui :send :receiver-network-values]
receiver-network-values)
:always (assoc-in [:wallet :ui :send :suggested-routes-call-timestamp] now)
:always (update-in [:wallet :ui :send] dissoc :network-links)
token (assoc-in [:wallet :ui :send :token] token))
:json-rpc/call [{:method "wallet_getSuggestedRoutes"
:params request-params
:on-success (fn [suggested-routes]
(rf/dispatch [:wallet/suggested-routes-success suggested-routes
now]))
params [{:uuid (str (random-uuid))
:sendType transaction-type
:addrFrom from-address
:addrTo to-address
:amountIn amount-in
:amountOut amount-out
:tokenID token-id
:toTokenID to-token-id
:disabledFromChainIDs disabled-from-chain-ids
:disabledToChainIDs disabled-to-chain-ids
:gasFeeMode gas-rates
:fromLockedAmount from-locked-amount
:username (:username args)
:publicKey (:publicKey args)
:packID (:packID args)}]]
(when (and to-address from-address amount-in token-id)
{:db (update-in db
[:wallet :ui :send]
#(-> %
(assoc :amount amount
:loading-suggested-routes? true
:sender-network-values sender-network-values
:receiver-network-values receiver-network-values)
(dissoc :network-links)
(cond-> token (assoc :token token))))
:json-rpc/call [{:method "wallet_getSuggestedRoutesV2Async"
:params params
:on-error (fn [error]
(rf/dispatch [:wallet/suggested-routes-error error])
(log/error "failed to get suggested routes"
{:event :wallet/get-suggested-routes
:error error
:params request-params}))}]})))
(log/error "failed to get suggested routes (async)"
{:event :wallet/start-get-suggested-routes
:error (:message error)
:params params}))}]}))))
(rf/reg-event-fx :wallet/stop-get-suggested-routes
(fn []
{:fx [[:dispatch [:wallet/clean-routes-calculation]]]
:json-rpc/call [{:method "wallet_stopSuggestedRoutesV2AsyncCalcualtion"
:params []
:on-error (fn [error]
(log/error "failed to stop suggested routes calculation"
{:event :wallet/stop-get-suggested-routes
:error error}))}]}))
(rf/reg-event-fx :wallet/handle-suggested-routes
(fn [_ data]
(if-let [error (some-> data
first
:ErrorResponse
(#(if (= (:code %) "0") "An error occurred" (:details %))))]
(do
(log/error "failed to get suggested routes (async)"
{:event :wallet/handle-suggested-routes
:error error})
{:fx [[:dispatch [:wallet/suggested-routes-error error]]]})
(let [suggested-routes-new-data (data-store/rpc->suggested-routes data)
suggested-routes (-> suggested-routes-new-data
first
(update :best #(map data-store/new->old-route-path %))
(update :candidates #(map data-store/new->old-route-path %)))]
{:fx [[:dispatch
[:wallet/suggested-routes-success suggested-routes]]]}))))
(rf/reg-event-fx :wallet/add-authorized-transaction
(fn [{:keys [db]} [transaction]]
@ -677,6 +694,7 @@
:transfer-type transaction-type-param})
transaction-paths
sha3-pwd]]
(log/info "multi transaction called")
{:json-rpc/call [{:method "wallet_createMultiTransaction"
:params request-params
:on-success (fn [result]

View File

@ -141,7 +141,7 @@
(h/deftest-event :wallet/set-collectible-amount-to-send
[event-id dispatch]
(let [initial-db {:wallet {:ui {:send nil}}}
expected-fx [[:dispatch [:wallet/get-suggested-routes {:amount 10}]]
expected-fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 10}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen nil :flow-id :wallet-send-flow}]]]
@ -284,8 +284,7 @@
:network-links [{:from-chain-id 1
:to-chain-id 10
:position-diff 1}]
:loading-suggested-routes? false
:suggested-routes-call-timestamp ["1" "2"]}}}})
:loading-suggested-routes? false}}}})
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :suggested-routes)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :route)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :amount)))
@ -296,8 +295,6 @@
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :network-links)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:loading-suggested-routes?)))
(is (not (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send])
:suggested-routes-call-timestamp)))
(is (contains? (get-in (dispatch [event-id]) [:db :wallet :ui :send]) :other-props)))
(h/deftest-event :wallet/suggested-routes-error
@ -324,7 +321,7 @@
:receiver-network-values receiver-network-amounts
:route :values
:loading-suggested-routes? true}}}})
(is (match? expected-result (dispatch [event-id {:message "error"}])))))
(is (match? expected-result (dispatch [event-id "error"])))))
(h/deftest-event :wallet/reset-network-amounts-to-zero
[event-id dispatch]
@ -438,7 +435,7 @@
:collectible collectible}}}
:profile/profile {:test-networks-enabled? false
:is-goerli-enabled? false}}
:fx [[:dispatch [:wallet/get-suggested-routes {:amount 1}]]
:fx [[:dispatch [:wallet/start-get-suggested-routes {:amount 1}]]
[:dispatch
[:wallet/wizard-navigate-forward
{:current-screen stack-id

View File

@ -129,7 +129,7 @@
[{:keys [amount bounce-duration-ms token valid-input?]}]
(if valid-input?
(debounce/debounce-and-dispatch
[:wallet/get-suggested-routes
[:wallet/start-get-suggested-routes
{:amount amount
:updated-token token}]
bounce-duration-ms)
@ -396,7 +396,7 @@
(and (not should-try-again?) confirm-disabled?))
:on-press (cond
should-try-again?
#(rf/dispatch [:wallet/get-suggested-routes
#(rf/dispatch [:wallet/start-get-suggested-routes
{:amount amount-in-crypto
:updated-token token-by-symbol}])
sending-to-unpreferred-networks?

View File

@ -242,3 +242,10 @@
(defn tx-type-collectible?
[tx-type]
(contains? collectible-tx-set tx-type))
(defn convert-to-gwei
[n precision]
(-> n
money/wei->gwei
(money/with-precision precision)
(str)))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.182.37",
"commit-sha1": "4a43b2b2bebe45df2100d1a5c5034105d93e50b8",
"src-sha256": "0f5mm7lx6s2qcy9xpa9v7piqb60yazi6p677fy105yz7hg731cw6"
"version": "v0.182.38",
"commit-sha1": "2bbdb35f6cabd1a4f7775e180e0647b70ce8d1aa",
"src-sha256": "03bksi5gn44ky76kblikpr6j3x69baid81ghfk27a4qx9hnc0qgc"
}