diff --git a/.gitignore b/.gitignore index 416fc4c..1fe4ece 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ npm-debug.log* /platforms /plugins /www +/src/extension/inject.js diff --git a/src/extension/content.ts b/src/extension/content.ts index a7703d4..d78fb1e 100644 --- a/src/extension/content.ts +++ b/src/extension/content.ts @@ -4,7 +4,14 @@ const allowedMethods = { 'eth_requestAccounts' : true, 'eth_chainId': true, 'personal_sign' : true, - 'wallet_requestPermissions': true + 'wallet_requestPermissions': true, + 'eth_gasPrice': true, + 'eth_getBlockByNumber': true, + 'eth_blockNumber': true, + 'eth_estimateGas': true, + 'eth_sign': true, + 'net_version': true, + 'eth_sendTransaction': true, } window.addEventListener("message", (event) => { @@ -13,19 +20,23 @@ window.addEventListener("message", (event) => { if (event.data.type && (event.data.type == "CLWALLET_CONTENT")) { event.data.data.resId = event.data.resId - console.log('data in', event?.data) - if(event?.data?.data?.method ?? 'x' in allowedMethods) - + if((event?.data?.data?.method ?? 'x') in allowedMethods) { chrome.runtime.sendMessage(event.data.data, (res) => { const data = { type: "CLWALLET_PAGE", data: res, resId: event.data.resId }; console.log('data back', data) window.postMessage(data, "*"); }) + } else { + const data = { type: "CLWALLET_PAGE", data: { error: true, message: 'Unknown method requested'}, resId: event.data.resId }; + window.postMessage(data, "*"); + } } }); - (function() { + chrome.runtime.connect({ + name: 'content' + }) const script = document.createElement('script') script.src = chrome.runtime.getURL('src/extension/inject.js') document.documentElement.appendChild(script) diff --git a/src/extension/inject.js b/src/extension/inject.js deleted file mode 100644 index 79fea91..0000000 --- a/src/extension/inject.js +++ /dev/null @@ -1,227 +0,0 @@ -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var _this = this; -var listners = { - accountsChanged: new Set(), - connect: new Set(), - disconnect: new Set, - chainChanged: new Set() -}; -var promResolvers = {}; -var listner = function (event) { - var _a, _b; - if (event.source != window) - return; - if (event.data.type && (event.data.type == "CLWALLET_PAGE")) { - if ((_b = (_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) { - promResolvers[event.data.resId].reject(event.data.data); - } - else { - promResolvers[event.data.resId].resolve(event.data.data); - } - promResolvers[event.data.resId] = undefined; - } -}; -window.addEventListener("message", listner); -var sendMessage = function (args) { - return new Promise(function (resolve, reject) { - var resId = crypto.randomUUID(); - promResolvers[resId] = { resolve: resolve, reject: reject }; - var data = { type: "CLWALLET_CONTENT", data: args, resId: resId }; - window.postMessage(data, "*"); - }); -}; -// chainId -// : -// "0x89" -// enable -// : -// ƒ () -// isMetaMask -// : -// true -// networkVersion -// : -// "137" -// request -// : -// ƒ () -// selectedAddress -// : -// null -// send -// : -// ƒ () -// sendAsync -// : -// ƒ () -// _events -// : -// {connect: ƒ} -// _eventsCount -// : -// 1 -// _handleAccountsChanged -// : -// ƒ () -// _handleChainChanged -// : -// ƒ () -// _handleConnect -// : -// ƒ () -// _handleDisconnect -// : -// ƒ () -// _handleStreamDisconnect -// : -// ƒ () -// _handleUnlockStateChanged -// : -// ƒ () -// _jsonRpcConnection -// : -// {events: s, stream: d, middleware: ƒ} -// _log -// : -// u {name: undefined, levels: {…}, methodFactory: ƒ, getLevel: ƒ, setLevel: ƒ, …} -// _maxListeners -// : -// 100 -// _metamask -// : -// Proxy {isUnlocked: ƒ, requestBatch: ƒ} -// _rpcEngine -// : -// o {_events: {…}, _eventsCount: 0, _maxListeners: undefined, _middleware: Array(3)} -// _rpcRequest -// : -// ƒ () -// _sendSync -// : -// ƒ () -// _sentWarnings -// : -// {enable: false, experimentalMethods: false, send: false, events: {…}} -// _state -// : -// {accounts: Array(0), isConnected: true, isUnlocked: true, initialized: true, isPermanentlyDisconnected: false} -// _warnOfDeprecation -// : -// ƒ ( -var eth = new Proxy({ - isConnected: function () { - return true; - }, - // for maximum compatibility since is cloning the same API - isMetaMask: true, - enable: function () { - return sendMessage({ method: 'eth_requestAccounts', params: Array(0) }); - }, - request: function (args) { - return sendMessage(args); - }, - on: function (eventName, callback) { - switch (eventName) { - case 'accountsChanged': - listners.accountsChanged.add(callback); - break; - case 'connect': - listners.connect.add(callback); - break; - case 'disconnect': - listners.disconnect.add(callback); - break; - case 'chainChanged': - listners.chainChanged.add(callback); - break; - default: - return; - } - }, - // Simulate Metamask - _warnOfDeprecation: function () { return null; }, - _state: {}, - _sentWarnings: function () { return null; }, - _rpcRequest: function () { return null; }, - _handleAccountsChanged: function () { return null; }, - chainId: "0x89", - networkVersion: "137", - selectedAddress: null, - send: function () { return null; }, - sendAsync: function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { - return [2 /*return*/, null]; - }); }); }, - _events: {}, - _eventsCount: 0, - _handleChainChanged: function () { return null; }, - _handleConnect: function () { return null; }, - _handleDisconnect: function () { return null; }, - _handleStreamDisconnect: function () { return null; }, - _handleUnlockStateChanged: function () { return null; }, - _jsonRpcConnection: {}, - _log: {}, - _maxListeners: 100, - _metamask: new Proxy({}, {}), - _rpcEngine: {} -}, { - set: function () { return false; }, - deleteProperty: function () { return false; } -}); -var injectWallet = function (win) { - Object.defineProperty(win, 'ethereum', { - get: function () { - return eth; - }, - set: function () { - return; - } - }); - window.tttest = 'test'; - // Object.defineProperty(window, 'ethereum', 444) - console.log('Clear wallet injected', window.ethereum, win); -}; -injectWallet(this); -// setTimeout(() => { -// console.log('Metamask clone test'); -// // (window).ethereum.request({method: 'eth_requestAccounts', params: Array(0)}).then((res: any) => { console.log(res, '111111111')}); -// // (window).ethereum.request({method: 'eth_accounts', params: Array(0)}).then((res: any) => { console.log(res, '111111111')}); -// // (window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, '111111111')}); -// // (window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, '111111111')}); -// // (window).ethereum.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, '111111111')}); -// }, 3500) -// console.log( (window as any).ethereum.request({method: 'eth_chainId'})) diff --git a/src/extension/inject.ts b/src/extension/inject.ts index f2333b3..c373446 100644 --- a/src/extension/inject.ts +++ b/src/extension/inject.ts @@ -4,10 +4,10 @@ interface RequestArguments { } const listners = { - accountsChanged: new Set<() => void>(), - connect: new Set<() => void>(), - disconnect: new Set<() => void>, - chainChanged: new Set<() => void>(), + accountsChanged: new Set<(p?: any) => void>(), + connect: new Set<(p?: any) => void>(), + disconnect: new Set<(p?: any) => void>, + chainChanged: new Set<(p?: any) => void>(), } const promResolvers = {} as any @@ -15,14 +15,23 @@ const promResolvers = {} as any const listner = function(event: any) { if (event.source != window) return; - - if (event.data.type && (event.data.type == "CLWALLET_PAGE")) { + if (event.data.type && (event.data.type === "CLWALLET_PAGE")) { if(event?.data?.data?.error){ - promResolvers[event.data.resId].reject(event.data.data) + promResolvers[event.data.resId].reject(event.data.data); + console.log('rejected') }else { promResolvers[event.data.resId].resolve(event.data.data); } promResolvers[event.data.resId] = undefined; + } else if( event.data.type && (event.data.type === "CLWALLET_PAGE_LISTENER")) { + if((event?.data?.data?.listner ?? 'x') in listners ) { + try { + const listnerName = event?.data?.data?.listner as ('accountsChanged' | 'connect' | 'disconnect' | 'chainChanged') + listners[listnerName].forEach(listner => listner(event?.data?.data?.data)); + } catch { + // ignore + } + } } } @@ -187,9 +196,7 @@ const injectWallet = (win: any) => { return } }); -(window as any).tttest = 'test' - // Object.defineProperty(window, 'ethereum', 444) - console.log('Clear wallet injected', (window as any).ethereum, win) +console.log('Clear wallet injected', (window as any).ethereum, win) } injectWallet(this) @@ -202,7 +209,7 @@ injectWallet(this) // // (window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, '111111111')}); // // (window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, '111111111')}); // // (window).ethereum.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, '111111111')}); - +// // (window).ethereum.request({method: 'wallet_switchEthereumChain', params: [{chainId: "0x99"}]}).then((res: any) => { console.log(res, '111111111')}); // }, 3500) // console.log( (window as any).ethereum.request({method: 'eth_chainId'})) \ No newline at end of file diff --git a/src/extension/manifest.json b/src/extension/manifest.json index 58133a4..0d63e8c 100644 --- a/src/extension/manifest.json +++ b/src/extension/manifest.json @@ -23,6 +23,7 @@ "scripting", "webNavigation", "tabs", + "notifications", "storage", "alarms", "unlimitedStorage", diff --git a/src/extension/serviceWorker.ts b/src/extension/serviceWorker.ts index ad413d1..051880e 100644 --- a/src/extension/serviceWorker.ts +++ b/src/extension/serviceWorker.ts @@ -1,11 +1,13 @@ -import { getAccounts, getSelectedAccount, getSelectedNetwork, smallRandomString, storageSave} from '@/utils/platform'; +import { getAccounts, getSelectedAccount, getSelectedNetwork, smallRandomString, getSettings, clearPk, openTab } from '@/utils/platform'; import { userApprove, userReject, rIdWin, rIdData } from '@/extension/userRequest' -import { signMsg, getBalance, getBlockNumber, estimateGas, sendTransaction, getGasPrice } from '@/utils/wallet' +import { signMsg, getBalance, getBlockNumber, estimateGas, sendTransaction, getGasPrice, getBlockByNumber } from '@/utils/wallet' import type { RequestArguments } from '@/extension/types' import type { Account } from '@/extension/types' import { rpcError } from '@/extension/rpcConstants' import { updatePrices } from '@/utils/gecko' +let notificationUrl: string + chrome.runtime.onInstalled.addListener(() => { console.log('Service worker installed'); chrome.runtime.connect(null as unknown as string, { @@ -13,9 +15,9 @@ chrome.runtime.onInstalled.addListener(() => { }) }) -chrome.runtime.onConnect.addListener(port => port.onDisconnect.addListener((a) => +chrome.runtime.onConnect.addListener(port => port.onDisconnect.addListener(() => { - console.log('Service worker connected', storageSave('test-d', a)); + console.log('Service worker connected'); })) @@ -40,7 +42,7 @@ chrome.alarms.onAlarm.addListener((alarm) => { } }) -chrome.windows.onRemoved.addListener((winId) => { +chrome.windows.onRemoved.addListener(async (winId) => { if (winId in (userReject ?? {})){ userReject[winId]?.() } @@ -48,13 +50,29 @@ chrome.windows.onRemoved.addListener((winId) => { userApprove[winId] = undefined rIdWin[winId] = undefined rIdData[winId] = undefined - chrome.windows.getAll().then((wins) => { + const wins = await chrome.windows.getAll() if(wins.length === 0) { - storageSave('test-p', 'browser-closed') + const s = await getSettings() + if(s.enableStorageEnctyption) { + await clearPk() + } } - }) }) +const viewTxListner = async (id: string) => { + try { + const url = new URL(notificationUrl) + openTab(url.href) + chrome.notifications.clear(id) + } catch { + // ignore + } +} + +if (!chrome.notifications.onButtonClicked.hasListener(viewTxListner)){ + chrome.notifications.onButtonClicked.addListener(viewTxListner) +} + chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendResponse) => { console.log(message); (async () => { @@ -69,6 +87,15 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes case 'eth_call': { break } + case 'eth_getBlockByNumber': { + const params = message?.params?.[0] as any + sendResponse(await getBlockByNumber(params)) + break; + } + case 'eth_gasPrice': { + sendResponse(await getGasPrice()) + break; + } case 'eth_getBalance': { sendResponse(await getBalance()) break @@ -153,11 +180,45 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes }) }) - sendResponse( - await sendTransaction({...params, ...(rIdData?.[String(gWin?.id ?? 0)] ?? {}) }, pEstimateGas, pGasPrice) - ) + try { + const tx = await sendTransaction({...params, ...(rIdData?.[String(gWin?.id ?? 0)] ?? {}) }, pEstimateGas, pGasPrice) + sendResponse(tx) + const buttons = {} as any + const network = await getSelectedNetwork() + const notificationId = crypto.randomUUID() + if(network?.explorer) { + notificationUrl = `${network.explorer}/tx/${tx.hash}`.replace('//', '/') + buttons.buttons = [{ + title: 'View Transaction', + }] + setTimeout(() => { + try { + chrome.notifications.clear(notificationId) + } catch { + // ignore + } + }, 6e4) + } + chrome.notifications.create({ + notificationId, + message: 'Transaction Confirmed', + title: 'Success', + ...(buttons) + } as any) + + } catch { + sendResponse({ + error: true, + code: rpcError.USER_REJECTED, + message: 'TX Failed' + }) + chrome.notifications.create({ + message: 'Transaction Failed', + title: 'Error', + } as any) + } } catch(err) { - console.error(err) + // console.error(err) sendResponse({ error: true, code: rpcError.USER_REJECTED, @@ -223,7 +284,7 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes chrome.windows.create({ height: 450, width: 400, - url: chrome.runtime.getURL(`index.html?route=switch-network¶m=${String(message?.params?.[0] ?? '' )}&rid=${String(message?.resId ?? '')}`), + url: chrome.runtime.getURL(`index.html?route=switch-network¶m=${String(message?.params?.[0]?.chainId ?? '' )}&rid=${String(message?.resId ?? '')}`), type: 'popup' }).then((win) => { userReject[String(win.id)] = reject @@ -232,9 +293,7 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes }) }) - sendResponse( - await signMsg(String(message?.params?.[0]) ?? '' ) - ) + sendResponse(null) } catch { sendResponse({ error: true, diff --git a/src/extension/types.ts b/src/extension/types.ts index f4612ee..26a6548 100644 --- a/src/extension/types.ts +++ b/src/extension/types.ts @@ -25,7 +25,7 @@ export interface Networks { export interface RequestArguments { method: string; - params?: unknown[]; + params?: any[]; resId?: string } @@ -49,5 +49,5 @@ export interface Settings { lockOutPeriod: number lockOutEnabled: boolean theme: 'system' | 'light' | 'dark' - MP: string + lastLock: number } \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts index a5ae1f6..308f783 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -59,6 +59,10 @@ const routes: Array = [ path: 'add-network', component: () => import('@/views/AddNetwork.vue'), }, + { + path: 'add-network/edit/:chainId', + component: () => import('@/views/AddNetwork.vue'), + }, ], }, ] diff --git a/src/utils/networks.ts b/src/utils/networks.ts index 65571d4..916833b 100644 --- a/src/utils/networks.ts +++ b/src/utils/networks.ts @@ -59,8 +59,8 @@ export const mainNets: {[key: number]: Network} = { } export const testNets = { - 1: { - name: 'TESTNET Ethereum oerli', + 5: { + name: 'TESTNET Ethereum Goerli', rpc: 'https://rpc.ankr.com/eth_goerli', chainId: 5, explorer: 'https://goerli.etherscan.io', @@ -69,8 +69,8 @@ export const testNets = { 4: { name: 'TESTNET Ethereum Rinkeby', rpc: 'https://rpc.ankr.com/eth_rinkeby', - chainId: 5, - explorer: 'https://goerli.etherscan.io', + chainId: 4, + explorer: 'https://rinkeby.etherscan.io', icon: 'eth.webp' }, 80001: { diff --git a/src/utils/platform.ts b/src/utils/platform.ts index 17e8372..fc68c22 100644 --- a/src/utils/platform.ts +++ b/src/utils/platform.ts @@ -75,7 +75,7 @@ export const setPrices = async (prices: Prices): Promise => { await storageSave('prices', prices ) } -export const getPrices = async (): Promise => { +export const getPrices = async (): Promise => { return (await storageGet('prices'))?.prices ?? {} as unknown as Prices } @@ -108,6 +108,15 @@ export const smallRandomString = () => { return (Math.random() + 1).toString(36).substring(7); } +export const clearPk = async (): Promise => { + let accounts = await getAccounts() + const accProm = accounts.map(async a => { + return a + }) + accounts = await Promise.all(accProm) + await replaceAccounts(accounts) +} + export const hexTostr = (hexStr: string) => { if(hexStr.substring(0,2) === '0x') { @@ -124,6 +133,8 @@ export const hexTostr = (hexStr: string) => return hexStr } +export const numToHexStr = (num: number) => `0x${num.toString(16)}` + export const copyAddress = async (address: string, toastRef: Ref) => { await navigator.clipboard.writeText(address) toastRef.value = true diff --git a/src/utils/wallet.ts b/src/utils/wallet.ts index 85900e4..18a0675 100644 --- a/src/utils/wallet.ts +++ b/src/utils/wallet.ts @@ -26,6 +26,12 @@ export const getBlockNumber = async () => { return await provider.getBlockNumber() } +export const getBlockByNumber = async (blockNum: number) => { + const network = await getSelectedNetwork() + const provider = new ethers.providers.JsonRpcProvider(network.rpc) + return await provider.getBlock(blockNum) +} + export const estimateGas = async ({to = '', from = '', data = '', value = '0x0' }: {to: string, from: string, data: string, value: string}) => { const network = await getSelectedNetwork() const provider = new ethers.providers.JsonRpcProvider(network.rpc) diff --git a/src/views/AddNetwork.vue b/src/views/AddNetwork.vue index d4d5f25..8c5062e 100644 --- a/src/views/AddNetwork.vue +++ b/src/views/AddNetwork.vue @@ -2,27 +2,37 @@ - Add Network + {{ isEdit ? 'Edit Network': 'Add Network' }} Add from popular chain list - Name - + Name(*) + - ChainId - + ChainId(*) + - RPC URL - + RPC URL(*) + + + + + Native Token Symbol(?) + + + + + Explorer(?) + Cancel - Add Network + {{ isEdit ? 'Edit Network': 'Add Network' }} import { defineComponent, ref } from "vue"; import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonItem, IonLabel, IonInput, IonButton, IonIcon, - IonModal, IonList, IonSegment, IonSegmentButton, IonListHeader, IonButtons, IonAvatar, modalController, IonAlert + IonModal, IonList, IonSegment, IonSegmentButton, IonListHeader, IonButtons, IonAvatar, modalController, IonAlert, onIonViewWillEnter } from "@ionic/vue"; -import { getNetworks, saveSelectedNetwork, saveNetwork, getUrl, paste } from "@/utils/platform"; +import { getNetworks, saveSelectedNetwork, getUrl, paste, replaceNetworks } from "@/utils/platform"; import router from "@/router"; import { mainNets, testNets } from "@/utils/networks" - +import { useRoute } from 'vue-router' import { clipboardOutline } from "ionicons/icons"; +import type { Networks, Network } from '@/extension/types' export default defineComponent({ components: { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonItem, IonLabel, IonInput, IonButton, IonIcon, @@ -100,10 +111,33 @@ export default defineComponent({ const name = ref('') const chainId = ref(0) const rpc = ref('') + const symbol = ref('') + const explorer = ref('') const templateModal = ref(false) const currentSegment = ref('mainnets') const alertOpen = ref(false) const alertMsg = ref('') + const route = useRoute() + const isEdit = route.path.includes('/edit') + const paramChainId = route.params.chainId ?? "" + let networksProm: Promise + + + const fillNetworkInputs = (network: Network) => { + name.value = network.name + chainId.value = network.chainId + rpc.value = network.rpc + symbol.value = network.symbol ?? '' + explorer.value = network.explorer ?? '' + } + + onIonViewWillEnter(async () => { + if(isEdit && paramChainId) { + networksProm = getNetworks() + const networks = await networksProm as Networks + fillNetworkInputs(networks[Number(paramChainId)]) + } + }) const resetFields = () => { name.value = '' @@ -133,25 +167,27 @@ export default defineComponent({ } } let p1 = Promise.resolve() - const networks = await getNetworks() - if( (Object.keys(networks).length ?? 0) < 1 ){ - p1 = saveSelectedNetwork({ + if(!networksProm) { + networksProm = getNetworks() + } + const networks = await networksProm as Networks + const network = { name: name.value, chainId: chainId.value, - rpc: rpc.value - }) + rpc: rpc.value, + ...( symbol.value ? {symbol: symbol.value}:{}), + ...( explorer.value ? {explorer: explorer.value}:{}) + } + if( (Object.keys(networks).length ?? 0) < 1 ){ + p1 = saveSelectedNetwork(network) } else { - - if(chainId.value in networks){ + if((chainId.value in networks) && !isEdit){ alertMsg.value = "Network already exists." return alertOpen.value = true } } - const p2 = saveNetwork({ - name: name.value, - chainId: chainId.value, - rpc: rpc.value - }) + networks[chainId.value] = network + const p2 = replaceNetworks(networks) await Promise.all([p1, p2]) router.push('/') resetFields() @@ -166,9 +202,7 @@ export default defineComponent({ } const fillTemplate = (network: typeof mainNets[1] ) =>{ - name.value = network.name - chainId.value = network.chainId - rpc.value = network.rpc + fillNetworkInputs(network) modalController.dismiss(null, 'cancel') } @@ -188,7 +222,10 @@ export default defineComponent({ getUrl, fillTemplate, alertOpen, - alertMsg + alertMsg, + symbol, + explorer, + isEdit } } diff --git a/src/views/NetworksTab.vue b/src/views/NetworksTab.vue index 6b78207..285bb57 100644 --- a/src/views/NetworksTab.vue +++ b/src/views/NetworksTab.vue @@ -27,8 +27,8 @@ - Edit - Delete + Edit + Delete @@ -37,7 +37,7 @@