[#9575] Make sure status supports EIP 1102 and EIP 1193

This commit is contained in:
Andrey Shovkoplyas 2019-12-10 11:55:51 +01:00
parent beed1a60ee
commit e7122dc86a
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
13 changed files with 258 additions and 510 deletions

243
resources/js/provider.js Normal file
View File

@ -0,0 +1,243 @@
if(typeof EthereumProvider === "undefined"){
var callbackId = 0;
var callbacks = {};
var currentAccountAddress;
function bridgeSend(data){
WebViewBridge.send(JSON.stringify(data));
}
function sendAPIrequest(permission, params) {
var messageId = callbackId++;
var params = params || {};
bridgeSend({
type: 'api-request',
permission: permission,
messageId: messageId,
params: params
});
return new Promise(function (resolve, reject) {
params['resolve'] = resolve;
params['reject'] = reject;
callbacks[messageId] = params;
});
}
function qrCodeResponse(data, callback){
var result = data.data;
var regex = new RegExp(callback.regex);
if (!result) {
if (callback.reject) {
callback.reject(new Error("Cancelled"));
}
}
else if (regex.test(result)) {
if (callback.resolve) {
callback.resolve(result);
}
} else {
if (callback.reject) {
callback.reject(new Error("Doesn't match"));
}
}
}
function Unauthorized() {
this.name = "Unauthorized";
this.id = 4100;
this.message = "The requested method and/or account has not been authorized by the user.";
}
Unauthorized.prototype = Object.create(Error.prototype);
function UserRejectedRequest() {
this.name = "UserRejectedRequest";
this.id = 4001;
this.message = "The user rejected the request.";
}
UserRejectedRequest.prototype = Object.create(Error.prototype);
WebViewBridge.onMessage = function (message)
{
data = JSON.parse(message);
var id = data.messageId;
var callback = callbacks[id];
if (callback) {
if (data.type === "api-response") {
if (data.permission == 'qr-code'){
qrCodeResponse(data, callback);
} else if (data.isAllowed) {
if (data.permission == 'web3') {
currentAccountAddress = data.data[0];
}
callback.resolve(data.data);
} else {
callback.reject(new UserRejectedRequest());
}
}
else if (data.type === "web3-send-async-callback")
{
if (callback.beta)
{
if (data.error)
{
if (data.error.code == 4100)
callback.reject(new Unauthorized());
else
//TODO probably if rpc returns empty result we need to call resolve with empty data?
callback.reject(data.error);
}
else{
// TODO : according to https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1193.md#examples
// TODO : we need to return data.result.result here, but for some reason some dapps (uniswap)
// TODO : expects jsonrpc
callback.resolve(data.result);
}
}
else if (callback.results)
{
callback.results.push(data.error || data.result);
if (callback.results.length == callback.num)
callback.callback(undefined, callback.results);
}
else
{
callback.callback(data.error, data.result);
}
}
}
};
function web3Response (payload, result){
return {id: payload.id,
jsonrpc: "2.0",
result: result};
}
function getSyncResponse (payload) {
if (payload.method == "eth_accounts" && currentAccountAddress){
return web3Response(payload, [currentAccountAddress])
} else if (payload.method == "eth_coinbase" && currentAccountAddress){
return web3Response(payload, currentAccountAddress)
} else if (payload.method == "net_version" || payload.method == "eth_chainId"){
return web3Response(payload, networkId)
} else if (payload.method == "eth_uninstallFilter"){
return web3Response(payload, true);
} else {
return null;
}
}
var StatusAPI = function () {};
StatusAPI.prototype.getContactCode = function () {
return sendAPIrequest('contact-code');
};
var EthereumProvider = function () {};
EthereumProvider.prototype.isStatus = true;
EthereumProvider.prototype.status = new StatusAPI();
EthereumProvider.prototype.isConnected = function () { return true; };
EthereumProvider.prototype.enable = function () {
return sendAPIrequest('web3');
};
EthereumProvider.prototype.scanQRCode = function (regex) {
return sendAPIrequest('qr-code', {regex: regex});
};
//Support for legacy send method
EthereumProvider.prototype.sendSync = function (payload)
{
if (payload.method == "eth_uninstallFilter"){
this.sendAsync(payload, function (res, err) {})
}
var syncResponse = getSyncResponse(payload);
if (syncResponse){
return syncResponse;
} else {
return web3Response(payload, null);
}
};
EthereumProvider.prototype.send = function (method, params = [])
{
if (!method) {
return new Error('Request is not valid.');
}
if (!(params instanceof Array)) {
return new Error('Params is not a valid array.');
}
//Support for legacy send method
if (typeof method !== 'string') {
return this.sendSync(method);
}
if (method == 'eth_requestAccounts'){
return sendAPIrequest('web3');
}
var syncResponse = getSyncResponse({method: method});
if (syncResponse){
return new Promise(function (resolve, reject) {
resolve(syncResponse);
});
}
var messageId = callbackId++;
var payload = {id: messageId,
jsonrpc: "2.0",
method: method,
params: params};
bridgeSend({type: 'web3-send-async-read-only',
messageId: messageId,
payload: payload});
return new Promise(function (resolve, reject) {
callbacks[messageId] = {beta: true,
resolve: resolve,
reject: reject};
});
};
//Support for legacy sendAsync method
EthereumProvider.prototype.sendAsync = function (payload, callback)
{
var syncResponse = getSyncResponse(payload);
if (syncResponse && callback) {
callback(null, syncResponse);
}
else
{
var messageId = callbackId++;
if (Array.isArray(payload))
{
callbacks[messageId] = {num: payload.length,
results: [],
callback: callback};
for (var i in payload) {
bridgeSend({type: 'web3-send-async-read-only',
messageId: messageId,
payload: payload[i]});
}
}
else
{
callbacks[messageId] = {callback: callback};
bridgeSend({type: 'web3-send-async-read-only',
messageId: messageId,
payload: payload});
}
}
};
}
ethereum = new EthereumProvider();

File diff suppressed because one or more lines are too long

View File

@ -1,170 +0,0 @@
if(typeof StatusHttpProvider === "undefined"){
var callbackId = 0;
var callbacks = {};
function bridgeSend(data){
WebViewBridge.send(JSON.stringify(data));
}
function sendAPIrequest(permission, params) {
var messageId = callbackId++;
var params = params || {};
bridgeSend({
type: 'api-request',
permission: permission,
messageId: messageId,
params: params,
host: window.location.hostname
});
return new Promise(function (resolve, reject) {
params['resolve'] = resolve;
params['reject'] = reject;
callbacks[messageId] = params;
});
}
function qrCodeResponse(data, callback){
var result = data.data;
var regex = new RegExp(callback.regex);
if (!result) {
if (callback.reject) {
callback.reject(new Error("Cancelled"));
}
}
else if (regex.test(result)) {
if (callback.resolve) {
callback.resolve(result);
}
} else {
if (callback.reject) {
callback.reject(new Error("Doesn't match"));
}
}
}
WebViewBridge.onMessage = function (message) {
data = JSON.parse(message);
var id = data.messageId;
var callback = callbacks[id];
if (callback) {
if (data.type === "api-response") {
if (data.permission == 'qr-code'){
qrCodeResponse(data, callback);
} else if (data.isAllowed) {
callback.resolve(data.data);
} else {
callback.reject(new Error("Denied"));
}
} else if (data.type === "web3-send-async-callback") {
var id = data.messageId;
var callback = callbacks[id];
if (callback) {
if (callback.results) {
callback.results.push(data.error || data.result);
if (callback.results.length == callback.num)
callback.callback(undefined, callback.results);
} else {
callback.callback(data.error, data.result);
}
}
}
}
};
var StatusAPI = function () {};
StatusAPI.prototype.getContactCode = function () {
return sendAPIrequest('contact-code');
};
var StatusHttpProvider = function () {};
StatusHttpProvider.prototype.isStatus = true;
StatusHttpProvider.prototype.status = new StatusAPI();
StatusHttpProvider.prototype.isConnected = function () { return true; };
function web3Response (payload, result){
return {id: payload.id,
jsonrpc: "2.0",
result: result};
}
function getSyncResponse (payload) {
if (payload.method == "eth_accounts"){
return web3Response(payload, [currentAccountAddress])
} else if (payload.method == "eth_coinbase"){
return web3Response(payload, currentAccountAddress)
} else if (payload.method == "net_version"){
return web3Response(payload, networkId)
} else if (payload.method == "eth_uninstallFilter"){
return web3Response(payload, true);
} else {
return null;
}
}
StatusHttpProvider.prototype.send = function (payload) {
//TODO to be compatible with MM https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#dizzy-all-async---think-of-metamask-as-a-light-client
if (payload.method == "eth_uninstallFilter"){
this.sendAsync(payload, function (res, err) {})
}
var syncResponse = getSyncResponse(payload);
if (syncResponse){
return syncResponse;
} else {
alert('You tried to send "' + payload.method + '" synchronously. Synchronous requests are not supported, sorry.');
return null;
}
};
StatusHttpProvider.prototype.sendAsync = function (payload, callback) {
var syncResponse = getSyncResponse(payload);
if (syncResponse && callback){
callback(null, syncResponse);
}
else {
var messageId = callbackId++;
if (Array.isArray(payload))
{
callbacks[messageId] = {num: payload.length,
results: [],
callback: callback};
for (var i in payload) {
bridgeSend({type: 'web3-send-async',
messageId: messageId,
payload: payload[i]});
}
}
else
{
callbacks[messageId] = {callback: callback};
bridgeSend({type: 'web3-send-async',
messageId: messageId,
payload: payload});
}
}
};
StatusHttpProvider.prototype.enable = function () {
return new Promise(function (resolve, reject) { setTimeout(resolve, 1000);});
};
StatusHttpProvider.prototype.scanQRCode = function (regex) {
return sendAPIrequest('qr-code', {regex: regex});
};
}
var protocol = window.location.protocol
if (typeof web3 === "undefined") {
//why do we need this condition?
if (protocol == "https:" || protocol == "http:") {
console.log("StatusHttpProvider");
ethereum = new StatusHttpProvider();
web3 = new Web3(ethereum);
web3.eth.defaultAccount = currentAccountAddress;
}
}

View File

@ -1,220 +0,0 @@
if(typeof ReadOnlyProvider === "undefined"){
var callbackId = 0;
var callbacks = {};
var currentAccountAddress;
function bridgeSend(data){
WebViewBridge.send(JSON.stringify(data));
}
function sendAPIrequest(permission, params) {
var messageId = callbackId++;
var params = params || {};
bridgeSend({
type: 'api-request',
permission: permission,
messageId: messageId,
params: params
});
return new Promise(function (resolve, reject) {
params['resolve'] = resolve;
params['reject'] = reject;
callbacks[messageId] = params;
});
}
function qrCodeResponse(data, callback){
var result = data.data;
var regex = new RegExp(callback.regex);
if (!result) {
if (callback.reject) {
callback.reject(new Error("Cancelled"));
}
}
else if (regex.test(result)) {
if (callback.resolve) {
callback.resolve(result);
}
} else {
if (callback.reject) {
callback.reject(new Error("Doesn't match"));
}
}
}
WebViewBridge.onMessage = function (message) {
data = JSON.parse(message);
var id = data.messageId;
var callback = callbacks[id];
if (callback) {
if (data.type === "api-response") {
if (data.permission == 'qr-code'){
qrCodeResponse(data, callback);
} else if (data.isAllowed) {
if (data.permission == 'web3') {
currentAccountAddress = data.data[0];
}
callback.resolve(data.data);
} else {
callback.reject({code: 4001, message: "User denied authorizing any accounts for the dapp."});
}
} else if (data.type === "web3-send-async-callback") {
var id = data.messageId;
var callback = callbacks[id];
if (callback) {
if (callback.beta){
if (data.error || data.result.error){
callback.reject(data.error || data.result.error);
}
else{
callback.resolve(data.result.result);
}
}
else if (callback.results) {
callback.results.push(data.error || data.result);
if (callback.results.length == callback.num)
callback.callback(undefined, callback.results);
} else {
callback.callback(data.error, data.result);
}
}
}
}
};
function web3Response (payload, result){
return {id: payload.id,
jsonrpc: "2.0",
result: result};
}
function getSyncResponse (payload) {
if (payload.method == "eth_accounts" && currentAccountAddress){
return web3Response(payload, [currentAccountAddress])
} else if (payload.method == "eth_coinbase" && currentAccountAddress){
return web3Response(payload, currentAccountAddress)
} else if (payload.method == "net_version"){
return web3Response(payload, networkId)
} else if (payload.method == "eth_uninstallFilter"){
return web3Response(payload, true);
} else {
return null;
}
}
var StatusAPI = function () {};
StatusAPI.prototype.getContactCode = function () {
return sendAPIrequest('contact-code');
};
var ReadOnlyProvider = function () {};
ReadOnlyProvider.prototype.isStatus = true;
ReadOnlyProvider.prototype.status = new StatusAPI();
ReadOnlyProvider.prototype.isConnected = function () { return true; };
ReadOnlyProvider.prototype.enable = function () {
return sendAPIrequest('web3');
};
ReadOnlyProvider.prototype.scanQRCode = function (regex) {
return sendAPIrequest('qr-code', {regex: regex});
};
ReadOnlyProvider.prototype.send = function (payload) {
if (payload.method == "eth_uninstallFilter"){
this.sendAsync(payload, function (res, err) {})
}
var syncResponse = getSyncResponse(payload);
if (syncResponse){
return syncResponse;
} else {
return web3Response(payload, null);
}
};
function sendAsync (payload, callback) {
var syncResponse = getSyncResponse(payload);
if (syncResponse && callback){
callback(null, syncResponse);
}
else {
var messageId = callbackId++;
if (Array.isArray(payload))
{
callbacks[messageId] = {num: payload.length,
results: [],
callback: callback};
for (var i in payload) {
bridgeSend({type: 'web3-send-async-read-only',
messageId: messageId,
payload: payload[i]});
}
}
else
{
callbacks[messageId] = {callback: callback};
bridgeSend({type: 'web3-send-async-read-only',
messageId: messageId,
payload: payload});
}
}
};
ReadOnlyProvider.prototype.sendAsync = sendAsync;
var ReadOnlyBetaProvider = function () {};
ReadOnlyBetaProvider.prototype.isStatus = true;
ReadOnlyBetaProvider.prototype.status = new StatusAPI();
//web3.js Backwards Compatibility
ReadOnlyBetaProvider.prototype.isConnected = function () { return true; };
ReadOnlyBetaProvider.prototype.sendAsync = sendAsync;
ReadOnlyBetaProvider.prototype.scanQRCode = function (regex) {
return sendAPIrequest('qr-code', {regex: regex});
};
ReadOnlyBetaProvider.prototype.send = function (method, params = []) {
if (!method || typeof method !== 'string') {
return new Error('Method is not a valid string.');
}
if (!(params instanceof Array)) {
return new Error('Params is not a valid array.');
}
if (method == 'eth_requestAccounts'){
return sendAPIrequest('web3');
}
var messageId = callbackId++;
var payload = {id: messageId,
jsonrpc: "2.0",
method: method,
params: params};
bridgeSend({type: 'web3-send-async-read-only',
messageId: messageId,
payload: payload});
return new Promise(function (resolve, reject) {
callbacks[messageId] = {beta: true,
resolve: resolve,
reject: reject};
});
};
}
console.log("ReadOnlyProvider");
ethereum = new ReadOnlyProvider();
console.log("ReadOnlyBetaProvider");
ethereumBeta = new ReadOnlyBetaProvider();

View File

@ -320,7 +320,7 @@
(fx/defn web3-send-async
[cofx {:keys [method params id] :as payload} message-id]
(let [message? (constants/web3-sign-message? method)
(let [message? (constants/web3-sign-message? method)
dapps-address (get-in cofx [:db :multiaccount :dapps-address])]
(if (or message? (= constants/web3-send-transaction method))
(let [[address data] (when message? (normalize-sign-message-params params))]
@ -328,8 +328,8 @@
(signing/sign cofx (merge
(if message?
{:message {:address address :data data :typed? (not= constants/web3-personal-sign method)
:from dapps-address}}
{:tx-obj (update (first params) :from #(or % dapps-address))})
:from dapps-address}}
{:tx-obj (update (first params) :from #(or % dapps-address))})
{:on-result [:browser.dapp/transaction-on-result message-id id]
:on-error [:browser.dapp/transaction-on-error message-id]}))))
(if (#{"eth_accounts" "eth_coinbase"} method)
@ -337,7 +337,7 @@
:messageId message-id
:result {:jsonrpc "2.0"
:id (int id)
:result (if (= method "eth_coinbase") dapps-address [dapps-address])}})
:result (if (= method "eth_coinbase") dapps-address [dapps-address])}})
{:browser/call-rpc [payload
#(re-frame/dispatch [:browser.callback/call-rpc
{:type constants/web3-send-async-callback
@ -354,7 +354,7 @@
(send-to-bridge cofx
{:type constants/web3-send-async-callback
:messageId message-id
:error {:code 4100 :message "The requested account has not been authorized by the user."}})
:error {:code 4100}})
(web3-send-async cofx payload message-id))))
(fx/defn handle-scanned-qr-code
@ -386,9 +386,6 @@
(update-browser-history browser url)
(resolve-url nil))
(= type constants/web3-send-async)
(web3-send-async cofx payload messageId)
(= type constants/web3-send-async-read-only)
(web3-send-async-read-only cofx dapp-name payload messageId)

View File

@ -80,8 +80,7 @@
(merge testnet-networks mainnet-networks sidechain-networks))
(def default-multiaccount-settings
{:web3-opt-in? true
:preview-privacy? false
{:preview-privacy? false
:wallet {:visible-tokens {}}})
(def currencies
@ -245,11 +244,9 @@
(def ^:const api-request "api-request")
(def ^:const history-state-changed "history-state-changed")
(def ^:const debug-metrics "debug_metrics")
(def ^:const web3-send-async "web3-send-async")
(def ^:const web3-send-async-read-only "web3-send-async-read-only")
(def ^:const web3-send-async-callback "web3-send-async-callback")
(def ^:const scan-qr-code "scan-qr-code")
(def ^:const scan-qr-code-callback "scan-qr-code-callback")
;;ipfs
(def ^:const ipfs-proto-code "e3")

View File

@ -131,11 +131,6 @@
(fn [cofx [_ enabled?]]
(multiaccounts/toggle-disable-discovery-topic cofx enabled?)))
(handlers/register-handler-fx
:multiaccounts.ui/web3-opt-in-mode-switched
(fn [cofx [_ opt-in]]
(multiaccounts/switch-web3-opt-in-mode cofx opt-in)))
(handlers/register-handler-fx
:multiaccounts.ui/preview-privacy-mode-switched
(fn [cofx [_ private?]]

View File

@ -131,13 +131,6 @@
(assoc settings :disable-discovery-topic? enabled?)
{}))))
(fx/defn switch-web3-opt-in-mode
[{:keys [db] :as cofx} opt-in]
(let [settings (get-in db [:multiaccount :settings])]
(multiaccounts.update/update-settings cofx
(assoc settings :web3-opt-in? opt-in)
{})))
(fx/defn switch-preview-privacy-mode
[{:keys [db] :as cofx} private?]
(let [settings (get-in db [:multiaccount :settings])]

View File

@ -12,9 +12,7 @@
[status-im.react-native.resources :as resources]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.radio :as radio]
[status-im.ui.components.icons.vector-icons :as icons]
[reagent.core :as reagent]
[status-im.ui.screens.browser.accounts :as accounts])
(:require-macros [status-im.utils.views :as views]))
@ -51,39 +49,8 @@
(def dapp-image-data {:image (resources/get-image :dapp-store) :width 768 :height 333})
(defn dapp-image [] [components.common/image-contain nil dapp-image-data])
(def privacy-otions-visible? (reagent/atom true))
(views/defview privacy-options []
(views/letsubs [{:keys [settings]} [:multiaccount]]
(let [privacy-enabled? (or (nil? (:web3-opt-in? settings)) (:web3-opt-in? settings))]
(when @privacy-otions-visible?
[react/view styles/privacy-container
[react/view {:style {:flex-direction :row}}
[react/view {:flex 1}
[react/text {:style {:typography :main-medium}} (i18n/label :t/dapps-can-access)]]
[react/touchable-highlight {:on-press #(reset! privacy-otions-visible? false)}
[react/view {:style {:width 40 :height 30 :align-items :center :margin-left 20}}
[react/view {:style styles/close-icon-container}
[icons/icon :main-icons/close {:color colors/white :width 19 :height 19}]]]]]
[react/touchable-highlight
{:on-press (when-not privacy-enabled?
#(re-frame/dispatch [:multiaccounts.ui/web3-opt-in-mode-switched (not privacy-enabled?)]))}
[react/view {:style {:height 56 :justify-content :center :margin-top 8}}
[react/view {:style {:flex-direction :row :align-items :center}}
[radio/radio privacy-enabled?]
[react/text {:style {:margin-left 14}} (i18n/label :t/require-my-permission)]]
[react/text {:style styles/might-break}
(i18n/label :t/might-break)]]]
[react/touchable-highlight
{:on-press (when privacy-enabled?
#(re-frame/dispatch [:multiaccounts.ui/web3-opt-in-mode-switched (not privacy-enabled?)]))}
[react/view {:style {:flex-direction :row :height 40 :align-items :center}}
[radio/radio (not privacy-enabled?)]
[react/text {:style {:margin-left 14}} (i18n/label :t/always-allow)]]]]))))
(defn list-header [empty?]
[react/view (when empty? {:flex 1})
[privacy-options]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:browser.ui/open-url "https://dap.ps"])}
[react/view styles/dapp-store-container
[dapp-image nil dapp-image-data]

View File

@ -26,14 +26,6 @@
[status-im.utils.slurp :refer [slurp]]
[status-im.utils.views :as views]))
(def browser-config-edn
(slurp "./src/status_im/utils/browser_config.edn"))
(def browser-config
(memoize
(fn []
(edn/read-string (browser-config-edn)))))
(defn toolbar-content [url url-original {:keys [secure?]} url-editing? webview]
(let [url-text (atom url)]
[react/view styles/toolbar-content
@ -79,11 +71,6 @@
[react/text {:style styles/web-view-error-text}
(str desc)]]))
(defn get-inject-js [url]
(when url
(let [domain-name (nth (re-find #"^\w+://(www\.)?([^/:]+)" url) 2)]
(get (:inject-js (browser-config)) domain-name))))
(views/defview navigation [url can-go-back? can-go-forward? dapps-account]
(views/letsubs [height [:dimensions/window-height]
accounts [:accounts-without-watch-only]]
@ -120,7 +107,7 @@
(views/defview browser-component
[{:keys [webview error? url browser browser-id unsafe? can-go-back?
can-go-forward? resolving? network-id url-original
show-permission show-tooltip opt-in? dapp? name dapps-account]}]
show-permission show-tooltip dapp? name dapps-account]}]
{:should-component-update (fn [_ _ args]
(let [[_ props] args]
(not (nil? (:url props)))))}
@ -149,11 +136,7 @@
:on-bridge-message #(re-frame/dispatch [:browser/bridge-message-received %])
:on-load #(re-frame/dispatch [:browser/loading-started])
:on-error #(re-frame/dispatch [:browser/error-occured])
:injected-on-start-loading-java-script (str (when-not opt-in? (js-res/web3))
(if opt-in?
(js-res/web3-opt-in-init (str network-id))
(js-res/web3-init (:address dapps-account) (str network-id)))
(get-inject-js url))
:injected-on-start-loading-java-script (js-res/ethereum-provider (str network-id))
:injected-java-script (js-res/webview-js)}])]
[navigation url-original can-go-back? can-go-forward? dapps-account]
[permissions.views/permissions-panel [(:dapp? browser) (:dapp browser) dapps-account] show-permission]
@ -167,15 +150,13 @@
(views/defview browser []
(views/letsubs [webview (atom nil)
window-width [:dimensions/window-width]
{:keys [settings]} [:multiaccount]
{:keys [browser-id dapp? name unsafe?] :as browser} [:get-current-browser]
{:keys [url error? loading? url-editing? show-tooltip show-permission resolving?]} [:browser/options]
dapps-account [:dapps-account]
network-id [:chain-id]]
(let [can-go-back? (browser/can-go-back? browser)
can-go-forward? (browser/can-go-forward? browser)
url-original (browser/get-current-url browser)
opt-in? (or (nil? (:web3-opt-in? settings)) (:web3-opt-in? settings))]
url-original (browser/get-current-url browser)]
[react/view {:style styles/browser}
[toolbar error? url url-original browser browser-id url-editing? webview]
[react/view
@ -195,6 +176,5 @@
:network-id network-id
:show-permission show-permission
:show-tooltip show-tooltip
:opt-in? opt-in?
:name name
:dapps-account dapps-account}]])))
:dapps-account dapps-account}]])))

View File

@ -1,6 +0,0 @@
;; Browser (webview) configuration
;; :inject-js is a map of {<domain> <js-code>}, JS code will be injected if the domain name matches (www. is stripped away)
{:inject-js {"cryptokitties.co" "; if (!window.chrome) { window.chrome = { webstore: true };
if (ethereum) ethereum.isMetaMask = true;
if (web3 && web3.currentProvider) web3.currentProvider.isMetaMask = true; }"}}

View File

@ -1,35 +1,9 @@
(ns status-im.utils.js-resources
(:require-macros [status-im.utils.slurp :refer [slurp]])
(:require [status-im.utils.types :refer [json->clj]]
[clojure.string :as s]))
(def local-protocol "local://")
(defn local-resource? [url]
(and (string? url) (s/starts-with? url local-protocol)))
(:require-macros [status-im.utils.slurp :refer [slurp]]))
(def webview-js (slurp "resources/js/webview.js"))
(def web3-file (slurp "resources/js/web3.min.js"))
(def web3
(memoize
(fn []
(str "; if (typeof Web3 == 'undefined') {"
(web3-file)
"}"))))
(def provider-file (slurp "resources/js/provider.js"))
(def web3-init-file (slurp "resources/js/web3_init.js"))
(defn web3-init [current-account-address network-id]
(str "var currentAccountAddress = \"" current-account-address "\";"
"var networkId = \"" network-id "\";"
(web3-init-file)))
(def web3-opt-in-init-file (slurp "resources/js/web3_opt_in.js"))
(defn web3-opt-in-init [network-id]
(defn ethereum-provider [network-id]
(str "var networkId = \"" network-id "\";"
(web3-opt-in-init-file)))
(defn local-storage-data [data]
(str "var localStorageData = " (or data "{}") ";"))
(defn network-id [id]
(str "status.ethereumNetworkId = " (or id "null") "; "))
(provider-file)))

View File

@ -89,8 +89,7 @@
:name "name"
:last-request nil
:desktop-notifications? false
:settings {:web3-opt-in? true
:preview-privacy? true
:settings {:preview-privacy? true
:fleet :eth.beta
:wallet {:visible-tokens {:testnet #{:STT
:HND}