feat (wallet): add ability to create new account (#17496)
This commit is contained in:
parent
ab2ad0ec12
commit
56492949f1
|
@ -765,7 +765,7 @@ SPEC CHECKSUMS:
|
||||||
RNLanguages: 962e562af0d34ab1958d89bcfdb64fafc37c513e
|
RNLanguages: 962e562af0d34ab1958d89bcfdb64fafc37c513e
|
||||||
RNPermissions: ad71dd4f767ec254f2cd57592fbee02afee75467
|
RNPermissions: ad71dd4f767ec254f2cd57592fbee02afee75467
|
||||||
RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071
|
RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071
|
||||||
RNReanimated: b2dc21e263319892469d656dc58fc26fb03eadab
|
RNReanimated: 62e43ee6baafb9ba3d3af1857d7fd23a1d41bff0
|
||||||
RNShare: d82e10f6b7677f4b0048c23709bd04098d5aee6c
|
RNShare: d82e10f6b7677f4b0048c23709bd04098d5aee6c
|
||||||
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
|
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
|
||||||
RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9
|
RNSVG: 80584470ff1ffc7994923ea135a3e5ad825546b9
|
||||||
|
@ -777,6 +777,6 @@ SPEC CHECKSUMS:
|
||||||
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
|
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
|
||||||
Yoga: d24d6184b6b85f742536bd93bd07d69d7b9bb4c1
|
Yoga: d24d6184b6b85f742536bd93bd07d69d7b9bb4c1
|
||||||
|
|
||||||
PODFILE CHECKSUM: 6a5f0e6776ce4ef6193032d077947117ace77a87
|
PODFILE CHECKSUM: 84b749023e1c988c133d7a6ec09d125536e4a4fd
|
||||||
|
|
||||||
COCOAPODS: 1.12.0
|
COCOAPODS: 1.12.0
|
||||||
|
|
|
@ -9,10 +9,8 @@
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn view
|
(defn view
|
||||||
[{:keys [on-enter-password button-label]}]
|
[{:keys [on-enter-password button-label button-icon-left customization-color]}]
|
||||||
(let [{:keys [key-uid display-name
|
(let [{:keys [key-uid display-name] :as account} (rf/sub [:profile/multiaccount])
|
||||||
customization-color]
|
|
||||||
:as account} (rf/sub [:profile/multiaccount])
|
|
||||||
{:keys [error processing password]} (rf/sub [:profile/login])
|
{:keys [error processing password]} (rf/sub [:profile/login])
|
||||||
sign-in-enabled? (rf/sub [:sign-in-enabled?])
|
sign-in-enabled? (rf/sub [:sign-in-enabled?])
|
||||||
profile-picture (multiaccounts/displayed-photo account)]
|
profile-picture (multiaccounts/displayed-photo account)]
|
||||||
|
@ -45,7 +43,7 @@
|
||||||
:type :primary
|
:type :primary
|
||||||
:customization-color (or customization-color :primary)
|
:customization-color (or customization-color :primary)
|
||||||
:accessibility-label :login-button
|
:accessibility-label :login-button
|
||||||
:icon-left :i/reveal
|
:icon-left button-icon-left
|
||||||
:disabled? (or (not sign-in-enabled?) processing)
|
:disabled? (or (not sign-in-enabled?) processing)
|
||||||
:on-press (fn []
|
:on-press (fn []
|
||||||
(rf/dispatch [:set-in [:profile/login :key-uid] key-uid])
|
(rf/dispatch [:set-in [:profile/login :key-uid] key-uid])
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
(defn authorize
|
(defn authorize
|
||||||
[{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close
|
[{:keys [on-enter-password biometric-auth? on-auth-success on-auth-fail on-close
|
||||||
fallback-button-label theme blur?]}]
|
auth-button-label theme blur? customization-color auth-button-icon-left]}]
|
||||||
(biometric/get-supported-type
|
(biometric/get-supported-type
|
||||||
(fn [biometric-type]
|
(fn [biometric-type]
|
||||||
(if (and biometric-auth? biometric-type)
|
(if (and biometric-auth? biometric-type)
|
||||||
|
@ -43,8 +43,10 @@
|
||||||
:shell? blur?
|
:shell? blur?
|
||||||
:content (fn []
|
:content (fn []
|
||||||
[enter-password/view
|
[enter-password/view
|
||||||
{:on-enter-password on-enter-password
|
{:customization-color customization-color
|
||||||
:button-label fallback-button-label}])}]))))))
|
:on-enter-password on-enter-password
|
||||||
|
:button-icon-left auth-button-icon-left
|
||||||
|
:button-label auth-button-label}])}]))))))
|
||||||
|
|
||||||
(defn- view-internal
|
(defn- view-internal
|
||||||
[_]
|
[_]
|
||||||
|
@ -53,26 +55,31 @@
|
||||||
(fn [{:keys [biometric-auth?
|
(fn [{:keys [biometric-auth?
|
||||||
track-text
|
track-text
|
||||||
customization-color
|
customization-color
|
||||||
fallback-button-label
|
auth-button-label
|
||||||
on-enter-password
|
on-enter-password
|
||||||
on-auth-success
|
on-auth-success
|
||||||
on-auth-fail
|
on-auth-fail
|
||||||
|
auth-button-icon-left
|
||||||
size
|
size
|
||||||
theme
|
theme
|
||||||
blur?]}]
|
blur?
|
||||||
|
container-style]}]
|
||||||
[rn/view {:style {:flex 1}}
|
[rn/view {:style {:flex 1}}
|
||||||
[quo/slide-button
|
[quo/slide-button
|
||||||
{:size size
|
{:size size
|
||||||
|
:container-style container-style
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-reset (when @reset-slider? #(reset! reset-slider? false))
|
:on-reset (when @reset-slider? #(reset! reset-slider? false))
|
||||||
:on-complete #(authorize {:on-close on-close
|
:on-complete #(authorize {:on-close on-close
|
||||||
|
:auth-button-icon-left auth-button-icon-left
|
||||||
:theme theme
|
:theme theme
|
||||||
:blur? blur?
|
:blur? blur?
|
||||||
|
:customization-color customization-color
|
||||||
:on-enter-password on-enter-password
|
:on-enter-password on-enter-password
|
||||||
:biometric-auth? biometric-auth?
|
:biometric-auth? biometric-auth?
|
||||||
:on-auth-success on-auth-success
|
:on-auth-success on-auth-success
|
||||||
:on-auth-fail on-auth-fail
|
:on-auth-fail on-auth-fail
|
||||||
:fallback-button-label fallback-button-label})
|
:auth-button-label auth-button-label})
|
||||||
:track-icon (if biometric-auth? :i/face-id :password)
|
:track-icon (if biometric-auth? :i/face-id :password)
|
||||||
:track-text track-text}]])))
|
:track-text track-text}]])))
|
||||||
|
|
||||||
|
|
|
@ -188,14 +188,16 @@
|
||||||
native-module/sha3)]
|
native-module/sha3)]
|
||||||
{:json-rpc/call [{:method "accounts_verifyPassword"
|
{:json-rpc/call [{:method "accounts_verifyPassword"
|
||||||
:params [hashed-password]
|
:params [hashed-password]
|
||||||
:on-success #(do (rf/dispatch [:profile.login/verified-database-password %]) (cb))
|
:on-success #(rf/dispatch [:profile.login/verified-database-password % cb])
|
||||||
:on-error #(log/error "accounts_verifyPassword error" %)}]}))
|
:on-error #(log/error "accounts_verifyPassword error" %)}]}))
|
||||||
|
|
||||||
(rf/defn verify-database-password-success
|
(rf/defn verify-database-password-success
|
||||||
{:events [:profile.login/verified-database-password]}
|
{:events [:profile.login/verified-database-password]}
|
||||||
[{:keys [db] :as cofx} valid?]
|
[{:keys [db] :as cofx} valid? callback]
|
||||||
(if valid?
|
(if valid?
|
||||||
(do
|
(do
|
||||||
|
(when (fn? callback)
|
||||||
|
(callback))
|
||||||
{:db (update db
|
{:db (update db
|
||||||
:profile/login
|
:profile/login
|
||||||
dissoc
|
dissoc
|
||||||
|
|
|
@ -126,7 +126,8 @@
|
||||||
:customization-color customization-color
|
:customization-color customization-color
|
||||||
:on-enter-password on-enter-password
|
:on-enter-password on-enter-password
|
||||||
:biometric-auth? false
|
:biometric-auth? false
|
||||||
:fallback-button-label (i18n/label :t/reveal-sync-code)}]])]]
|
:auth-button-label (i18n/label :t/reveal-sync-code)
|
||||||
|
:auth-button-icon-left :i/reveal}]])]]
|
||||||
[rn/view {:style style/sync-code}
|
[rn/view {:style style/sync-code}
|
||||||
[quo/divider-label {:tight? false} (i18n/label :t/have-a-sync-code?)]
|
[quo/divider-label {:tight? false} (i18n/label :t/have-a-sync-code?)]
|
||||||
[quo/action-drawer
|
[quo/action-drawer
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im2.common.resources :as status.resources]
|
[status-im2.common.resources :as status.resources]
|
||||||
[status-im2.constants :as constants]
|
[status-im2.constants :as constants]
|
||||||
[status-im2.contexts.wallet.common.utils :as utils]
|
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
@ -112,35 +111,6 @@
|
||||||
:account :default
|
:account :default
|
||||||
:customization-color :blue})
|
:customization-color :blue})
|
||||||
|
|
||||||
(defn keypair-string
|
|
||||||
[full-name]
|
|
||||||
(let [first-name (utils/get-first-name full-name)]
|
|
||||||
(i18n/label :t/keypair-title {:name first-name})))
|
|
||||||
|
|
||||||
(defn create-account-state
|
|
||||||
[name]
|
|
||||||
[{:title (keypair-string name)
|
|
||||||
:image :avatar
|
|
||||||
:image-props {:full-name "A Y"
|
|
||||||
:size :xxs
|
|
||||||
:customization-color :blue}
|
|
||||||
:action :button
|
|
||||||
:action-props {:on-press #(js/alert "Button pressed!")
|
|
||||||
:button-text (i18n/label :t/edit)
|
|
||||||
:alignment :flex-start}
|
|
||||||
:description :text
|
|
||||||
:description-props {:text (i18n/label :t/on-device)}}
|
|
||||||
{:title (i18n/label :t/derivation-path)
|
|
||||||
:image :icon
|
|
||||||
:image-props :i/derivated-path
|
|
||||||
:action :button
|
|
||||||
:action-props {:on-press #(js/alert "Button pressed!")
|
|
||||||
:button-text (i18n/label :t/edit)
|
|
||||||
:icon-left :i/placeholder
|
|
||||||
:alignment :flex-start}
|
|
||||||
:description :text
|
|
||||||
:description-props {:text (string/replace constants/path-default-wallet #"/" " / ")}}])
|
|
||||||
|
|
||||||
(def network-names [:ethereum :optimism :arbitrum])
|
(def network-names [:ethereum :optimism :arbitrum])
|
||||||
|
|
||||||
(def address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd4")
|
(def address "0x39cf6E0Ba4C4530735616e1Ee7ff5FbCB726fBd4")
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
(ns status-im2.contexts.wallet.common.utils
|
(ns status-im2.contexts.wallet.common.utils
|
||||||
(:require
|
(:require [clojure.string :as string]
|
||||||
[clojure.string :as string]))
|
[status-im2.constants :as constants]))
|
||||||
|
|
||||||
(defn get-first-name
|
(defn get-first-name
|
||||||
[full-name]
|
[full-name]
|
||||||
(first (string/split full-name #" ")))
|
(first (string/split full-name #" ")))
|
||||||
|
|
||||||
|
(defn get-derivation-path
|
||||||
|
[number-of-accounts]
|
||||||
|
(str constants/path-wallet-root "/" number-of-accounts))
|
||||||
|
|
|
@ -5,20 +5,44 @@
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im2.contexts.wallet.common.temp :as temp]
|
[status-im2.common.standard-authentication.standard-auth.view :as standard-auth]
|
||||||
|
[status-im2.contexts.wallet.common.utils :as utils]
|
||||||
[status-im2.contexts.wallet.create-account.style :as style]
|
[status-im2.contexts.wallet.create-account.style :as style]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(def diamond-emoji "\uD83D\uDC8E")
|
(def diamond-emoji "\uD83D\uDC8E")
|
||||||
|
|
||||||
|
(defn keypair-string
|
||||||
|
[full-name]
|
||||||
|
(let [first-name (utils/get-first-name full-name)]
|
||||||
|
(i18n/label :t/keypair-title {:name first-name})))
|
||||||
|
|
||||||
|
(defn get-keypair-data
|
||||||
|
[name derivation-path]
|
||||||
|
[{:title (keypair-string name)
|
||||||
|
:button-props {:title (i18n/label :t/edit)}
|
||||||
|
:left-icon :i/placeholder
|
||||||
|
:description :text
|
||||||
|
:description-props {:text (i18n/label :t/on-device)}}
|
||||||
|
{:title (i18n/label :t/derivation-path)
|
||||||
|
:button-props {:title (i18n/label :t/edit)}
|
||||||
|
:left-icon :i/derivated-path
|
||||||
|
:description :text
|
||||||
|
:description-props {:text derivation-path}}])
|
||||||
|
|
||||||
(defn- view-internal
|
(defn- view-internal
|
||||||
[]
|
[]
|
||||||
(let [top (safe-area/get-top)
|
(let [top (safe-area/get-top)
|
||||||
bottom (safe-area/get-bottom)
|
bottom (safe-area/get-bottom)
|
||||||
account-color (reagent/atom :blue)
|
account-color (reagent/atom :blue)
|
||||||
emoji (reagent/atom diamond-emoji)
|
emoji (reagent/atom diamond-emoji)
|
||||||
|
number-of-accounts (count (rf/sub [:profile/wallet-accounts]))
|
||||||
|
account-name (reagent/atom (i18n/label :t/default-account-name
|
||||||
|
{:number (inc number-of-accounts)}))
|
||||||
|
derivation-path (reagent/atom (utils/get-derivation-path number-of-accounts))
|
||||||
{:keys [public-key]} (rf/sub [:profile/profile])
|
{:keys [public-key]} (rf/sub [:profile/profile])
|
||||||
|
on-change-text #(reset! account-name %)
|
||||||
display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))]
|
display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))]
|
||||||
(fn [{:keys [theme]}]
|
(fn [{:keys [theme]}]
|
||||||
[rn/view
|
[rn/view
|
||||||
|
@ -50,12 +74,13 @@
|
||||||
(reset! emoji selected-emoji))}])
|
(reset! emoji selected-emoji))}])
|
||||||
:container-style style/reaction-button-container} :i/reaction]]
|
:container-style style/reaction-button-container} :i/reaction]]
|
||||||
[quo/title-input
|
[quo/title-input
|
||||||
{:color :red
|
{:customization-color @account-color
|
||||||
:placeholder "Type something here"
|
:placeholder "Type something here"
|
||||||
|
:on-change-text on-change-text
|
||||||
:max-length 24
|
:max-length 24
|
||||||
:blur? true
|
:blur? true
|
||||||
:disabled? false
|
:disabled? false
|
||||||
:default-value "Account 2"
|
:default-value @account-name
|
||||||
:container-style style/title-input-container}]
|
:container-style style/title-input-container}]
|
||||||
[quo/divider-line]
|
[quo/divider-line]
|
||||||
[rn/view
|
[rn/view
|
||||||
|
@ -74,13 +99,20 @@
|
||||||
[quo/category
|
[quo/category
|
||||||
{:list-type :settings
|
{:list-type :settings
|
||||||
:label (i18n/label :t/origin)
|
:label (i18n/label :t/origin)
|
||||||
:data (temp/create-account-state display-name)}]
|
:data (get-keypair-data display-name @derivation-path)}]
|
||||||
[quo/slide-button
|
[standard-auth/view
|
||||||
{:track-text (i18n/label :t/slide-to-sign)
|
{:size :size-48
|
||||||
:track-icon :face-id
|
:track-text (i18n/label :t/slide-to-create-account)
|
||||||
:customization-color @account-color
|
:customization-color @account-color
|
||||||
:on-complete (fn []
|
:on-enter-password (fn [entered-password]
|
||||||
(js/alert "Functionality not implemented"))
|
(rf/dispatch [:wallet/derive-address-and-add-account
|
||||||
|
entered-password
|
||||||
|
{:emoji @emoji
|
||||||
|
:color @account-color
|
||||||
|
:path @derivation-path
|
||||||
|
:account-name @account-name}]))
|
||||||
|
:biometric-auth? false
|
||||||
|
:auth-button-label (i18n/label :t/confirm)
|
||||||
:container-style (style/slide-button-container bottom)}]])))
|
:container-style (style/slide-button-container bottom)}]])))
|
||||||
|
|
||||||
(def view (quo.theme/with-theme view-internal))
|
(def view (quo.theme/with-theme view-internal))
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
(ns status-im2.contexts.wallet.events
|
(ns status-im2.contexts.wallet.events
|
||||||
(:require [utils.re-frame :as rf]))
|
(:require
|
||||||
|
[native-module.core :as native-module]
|
||||||
|
[taoensso.timbre :as log]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[utils.security.core :as security]))
|
||||||
|
|
||||||
(rf/defn scan-address-success
|
(rf/defn scan-address-success
|
||||||
{:events [:wallet/scan-address-success]}
|
{:events [:wallet/scan-address-success]}
|
||||||
|
@ -10,3 +14,40 @@
|
||||||
{:events [:wallet/clean-scanned-address]}
|
{:events [:wallet/clean-scanned-address]}
|
||||||
[{:keys [db]}]
|
[{:keys [db]}]
|
||||||
{:db (dissoc db :wallet/scanned-address)})
|
{:db (dissoc db :wallet/scanned-address)})
|
||||||
|
|
||||||
|
(rf/reg-event-fx :wallet/create-derived-addresses
|
||||||
|
(fn [{:keys [db]} [password {:keys [path]} on-success]]
|
||||||
|
(let [{:keys [wallet-root-address]} (:profile/profile db)
|
||||||
|
sha3-pwd (native-module/sha3 (str (security/safe-unmask-data password)))]
|
||||||
|
{:fx [[:json-rpc/call
|
||||||
|
[{:method "wallet_getDerivedAddresses"
|
||||||
|
:params [sha3-pwd wallet-root-address [path]]
|
||||||
|
:on-success on-success
|
||||||
|
:on-error #(log/info "failed to derive address " %)}]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :wallet/add-account
|
||||||
|
(fn [{:keys [db]} [password {:keys [emoji account-name color]} {:keys [public-key address path]}]]
|
||||||
|
(let [key-uid (get-in db [:profile/profile :key-uid])
|
||||||
|
sha3-pwd (native-module/sha3 (security/safe-unmask-data password))
|
||||||
|
account-config {:key-uid key-uid
|
||||||
|
:wallet false
|
||||||
|
:chat false
|
||||||
|
:type :generated
|
||||||
|
:name account-name
|
||||||
|
:emoji emoji
|
||||||
|
:path path
|
||||||
|
:address address
|
||||||
|
:public-key public-key
|
||||||
|
:colorID color}]
|
||||||
|
{:fx [[:json-rpc/call
|
||||||
|
[{:method "accounts_addAccount"
|
||||||
|
:params [sha3-pwd account-config]
|
||||||
|
:on-success #(rf/dispatch [:navigate-to :wallet-accounts])
|
||||||
|
:on-error #(log/info "failed to create account " %)}]]]})))
|
||||||
|
|
||||||
|
(rf/reg-event-fx :wallet/derive-address-and-add-account
|
||||||
|
(fn [_ [password account-details]]
|
||||||
|
(let [on-success (fn [derived-adress-details]
|
||||||
|
(rf/dispatch [:wallet/add-account password account-details
|
||||||
|
(first derived-adress-details)]))]
|
||||||
|
{:fx [[:dispatch [:wallet/create-derived-addresses password account-details on-success]]]})))
|
||||||
|
|
|
@ -146,3 +146,4 @@
|
||||||
|
|
||||||
;;wallet
|
;;wallet
|
||||||
(reg-root-key-sub :wallet/scanned-address :wallet/scanned-address)
|
(reg-root-key-sub :wallet/scanned-address :wallet/scanned-address)
|
||||||
|
(reg-root-key-sub :wallet/create-account :wallet/create-account)
|
||||||
|
|
|
@ -83,3 +83,5 @@
|
||||||
(def reg-fx re-frame/reg-fx)
|
(def reg-fx re-frame/reg-fx)
|
||||||
|
|
||||||
(def dispatch-sync re-frame/dispatch-sync)
|
(def dispatch-sync re-frame/dispatch-sync)
|
||||||
|
|
||||||
|
(def reg-event-fx re-frame/reg-event-fx)
|
||||||
|
|
|
@ -433,6 +433,7 @@
|
||||||
"decline": "Decline",
|
"decline": "Decline",
|
||||||
"decryption-failed-content": "An error occured decrypting your data. You might need to erase your old data and generate a new account. Tap “Apply” to erase or “Cancel” to try again",
|
"decryption-failed-content": "An error occured decrypting your data. You might need to erase your old data and generate a new account. Tap “Apply” to erase or “Cancel” to try again",
|
||||||
"default": "Default",
|
"default": "Default",
|
||||||
|
"default-account-name": "Account {{number}}",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"delete-and-leave-group": "Delete and leave group",
|
"delete-and-leave-group": "Delete and leave group",
|
||||||
"delete-bootnode": "Delete bootnode",
|
"delete-bootnode": "Delete bootnode",
|
||||||
|
@ -1893,6 +1894,7 @@
|
||||||
"select-token-to-swap": "Select token to Swap",
|
"select-token-to-swap": "Select token to Swap",
|
||||||
"select-token-to-receive": "Select token to receive",
|
"select-token-to-receive": "Select token to receive",
|
||||||
"slide-to-reveal-code": "Slide to reveal code",
|
"slide-to-reveal-code": "Slide to reveal code",
|
||||||
|
"slide-to-create-account": "Slide to create account",
|
||||||
"minimum-received": "Minimum received",
|
"minimum-received": "Minimum received",
|
||||||
"powered-by-paraswap": "Powered by Paraswap",
|
"powered-by-paraswap": "Powered by Paraswap",
|
||||||
"priority": "Priority",
|
"priority": "Priority",
|
||||||
|
@ -2360,5 +2362,6 @@
|
||||||
"network-preferences": "Network preferences",
|
"network-preferences": "Network preferences",
|
||||||
"network-preferences-desc": "Select which network this address is happy to receive funds on",
|
"network-preferences-desc": "Select which network this address is happy to receive funds on",
|
||||||
"layer-2": "Layer 2",
|
"layer-2": "Layer 2",
|
||||||
"manage-tokens": "Manage tokens"
|
"manage-tokens": "Manage tokens",
|
||||||
|
"sign transactions": "sign transactions"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue