dev: 1.0.2

This commit is contained in:
Andrei O 2022-10-10 03:52:23 +03:00
parent 9932a1a522
commit 610fdc6afb
No known key found for this signature in database
GPG Key ID: B961E5B68389457E
17 changed files with 437 additions and 355 deletions

1
.gitignore vendored
View File

@ -29,3 +29,4 @@ npm-debug.log*
/platforms /platforms
/plugins /plugins
/www /www
/src/extension/inject.js

View File

@ -4,7 +4,14 @@ const allowedMethods = {
'eth_requestAccounts' : true, 'eth_requestAccounts' : true,
'eth_chainId': true, 'eth_chainId': true,
'personal_sign' : 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) => { window.addEventListener("message", (event) => {
@ -13,19 +20,23 @@ window.addEventListener("message", (event) => {
if (event.data.type && (event.data.type == "CLWALLET_CONTENT")) { if (event.data.type && (event.data.type == "CLWALLET_CONTENT")) {
event.data.data.resId = event.data.resId 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) => { chrome.runtime.sendMessage(event.data.data, (res) => {
const data = { type: "CLWALLET_PAGE", data: res, resId: event.data.resId }; const data = { type: "CLWALLET_PAGE", data: res, resId: event.data.resId };
console.log('data back', data) console.log('data back', data)
window.postMessage(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() { (function() {
chrome.runtime.connect({
name: 'content'
})
const script = document.createElement('script') const script = document.createElement('script')
script.src = chrome.runtime.getURL('src/extension/inject.js') script.src = chrome.runtime.getURL('src/extension/inject.js')
document.documentElement.appendChild(script) document.documentElement.appendChild(script)

View File

@ -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');
// // (<any>window).ethereum.request({method: 'eth_requestAccounts', params: Array(0)}).then((res: any) => { console.log(res, '111111111')});
// // (<any>window).ethereum.request({method: 'eth_accounts', params: Array(0)}).then((res: any) => { console.log(res, '111111111')});
// // (<any>window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, '111111111')});
// // (<any>window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, '111111111')});
// // (<any>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'}))

View File

@ -4,10 +4,10 @@ interface RequestArguments {
} }
const listners = { const listners = {
accountsChanged: new Set<() => void>(), accountsChanged: new Set<(p?: any) => void>(),
connect: new Set<() => void>(), connect: new Set<(p?: any) => void>(),
disconnect: new Set<() => void>, disconnect: new Set<(p?: any) => void>,
chainChanged: new Set<() => void>(), chainChanged: new Set<(p?: any) => void>(),
} }
const promResolvers = {} as any const promResolvers = {} as any
@ -15,14 +15,23 @@ const promResolvers = {} as any
const listner = function(event: any) { const listner = function(event: any) {
if (event.source != window) if (event.source != window)
return; return;
if (event.data.type && (event.data.type === "CLWALLET_PAGE")) {
if (event.data.type && (event.data.type == "CLWALLET_PAGE")) {
if(event?.data?.data?.error){ 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 { }else {
promResolvers[event.data.resId].resolve(event.data.data); promResolvers[event.data.resId].resolve(event.data.data);
} }
promResolvers[event.data.resId] = undefined; 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 return
} }
}); });
(window as any).tttest = 'test' console.log('Clear wallet injected', (window as any).ethereum, win)
// Object.defineProperty(window, 'ethereum', 444)
console.log('Clear wallet injected', (window as any).ethereum, win)
} }
injectWallet(this) injectWallet(this)
@ -202,7 +209,7 @@ injectWallet(this)
// // (<any>window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, '111111111')}); // // (<any>window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, '111111111')});
// // (<any>window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, '111111111')}); // // (<any>window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, '111111111')});
// // (<any>window).ethereum.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, '111111111')}); // // (<any>window).ethereum.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, '111111111')});
// // (<any>window).ethereum.request({method: 'wallet_switchEthereumChain', params: [{chainId: "0x99"}]}).then((res: any) => { console.log(res, '111111111')});
// }, 3500) // }, 3500)
// console.log( (window as any).ethereum.request({method: 'eth_chainId'})) // console.log( (window as any).ethereum.request({method: 'eth_chainId'}))

View File

@ -23,6 +23,7 @@
"scripting", "scripting",
"webNavigation", "webNavigation",
"tabs", "tabs",
"notifications",
"storage", "storage",
"alarms", "alarms",
"unlimitedStorage", "unlimitedStorage",

View File

@ -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 { 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 { RequestArguments } from '@/extension/types'
import type { Account } from '@/extension/types' import type { Account } from '@/extension/types'
import { rpcError } from '@/extension/rpcConstants' import { rpcError } from '@/extension/rpcConstants'
import { updatePrices } from '@/utils/gecko' import { updatePrices } from '@/utils/gecko'
let notificationUrl: string
chrome.runtime.onInstalled.addListener(() => { chrome.runtime.onInstalled.addListener(() => {
console.log('Service worker installed'); console.log('Service worker installed');
chrome.runtime.connect(null as unknown as string, { 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 ?? {})){ if (winId in (userReject ?? {})){
userReject[winId]?.() userReject[winId]?.()
} }
@ -48,13 +50,29 @@ chrome.windows.onRemoved.addListener((winId) => {
userApprove[winId] = undefined userApprove[winId] = undefined
rIdWin[winId] = undefined rIdWin[winId] = undefined
rIdData[winId] = undefined rIdData[winId] = undefined
chrome.windows.getAll().then((wins) => { const wins = await chrome.windows.getAll()
if(wins.length === 0) { 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) => { chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendResponse) => {
console.log(message); console.log(message);
(async () => { (async () => {
@ -69,6 +87,15 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes
case 'eth_call': { case 'eth_call': {
break 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': { case 'eth_getBalance': {
sendResponse(await getBalance()) sendResponse(await getBalance())
break break
@ -153,11 +180,45 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes
}) })
}) })
sendResponse( try {
await sendTransaction({...params, ...(rIdData?.[String(gWin?.id ?? 0)] ?? {}) }, pEstimateGas, pGasPrice) 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) { } catch(err) {
console.error(err) // console.error(err)
sendResponse({ sendResponse({
error: true, error: true,
code: rpcError.USER_REJECTED, code: rpcError.USER_REJECTED,
@ -223,7 +284,7 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes
chrome.windows.create({ chrome.windows.create({
height: 450, height: 450,
width: 400, width: 400,
url: chrome.runtime.getURL(`index.html?route=switch-network&param=${String(message?.params?.[0] ?? '' )}&rid=${String(message?.resId ?? '')}`), url: chrome.runtime.getURL(`index.html?route=switch-network&param=${String(message?.params?.[0]?.chainId ?? '' )}&rid=${String(message?.resId ?? '')}`),
type: 'popup' type: 'popup'
}).then((win) => { }).then((win) => {
userReject[String(win.id)] = reject userReject[String(win.id)] = reject
@ -232,9 +293,7 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes
}) })
}) })
sendResponse( sendResponse(null)
await signMsg(String(message?.params?.[0]) ?? '' )
)
} catch { } catch {
sendResponse({ sendResponse({
error: true, error: true,

View File

@ -25,7 +25,7 @@ export interface Networks {
export interface RequestArguments { export interface RequestArguments {
method: string; method: string;
params?: unknown[]; params?: any[];
resId?: string resId?: string
} }
@ -49,5 +49,5 @@ export interface Settings {
lockOutPeriod: number lockOutPeriod: number
lockOutEnabled: boolean lockOutEnabled: boolean
theme: 'system' | 'light' | 'dark' theme: 'system' | 'light' | 'dark'
MP: string lastLock: number
} }

View File

@ -59,6 +59,10 @@ const routes: Array<RouteRecordRaw> = [
path: 'add-network', path: 'add-network',
component: () => import('@/views/AddNetwork.vue'), component: () => import('@/views/AddNetwork.vue'),
}, },
{
path: 'add-network/edit/:chainId',
component: () => import('@/views/AddNetwork.vue'),
},
], ],
}, },
] ]

View File

@ -59,8 +59,8 @@ export const mainNets: {[key: number]: Network} = {
} }
export const testNets = { export const testNets = {
1: { 5: {
name: 'TESTNET Ethereum oerli', name: 'TESTNET Ethereum Goerli',
rpc: 'https://rpc.ankr.com/eth_goerli', rpc: 'https://rpc.ankr.com/eth_goerli',
chainId: 5, chainId: 5,
explorer: 'https://goerli.etherscan.io', explorer: 'https://goerli.etherscan.io',
@ -69,8 +69,8 @@ export const testNets = {
4: { 4: {
name: 'TESTNET Ethereum Rinkeby', name: 'TESTNET Ethereum Rinkeby',
rpc: 'https://rpc.ankr.com/eth_rinkeby', rpc: 'https://rpc.ankr.com/eth_rinkeby',
chainId: 5, chainId: 4,
explorer: 'https://goerli.etherscan.io', explorer: 'https://rinkeby.etherscan.io',
icon: 'eth.webp' icon: 'eth.webp'
}, },
80001: { 80001: {

View File

@ -75,7 +75,7 @@ export const setPrices = async (prices: Prices): Promise<void> => {
await storageSave('prices', prices ) await storageSave('prices', prices )
} }
export const getPrices = async (): Promise<void> => { export const getPrices = async (): Promise<Prices> => {
return (await storageGet('prices'))?.prices ?? {} as unknown as Prices return (await storageGet('prices'))?.prices ?? {} as unknown as Prices
} }
@ -108,6 +108,15 @@ export const smallRandomString = () => {
return (Math.random() + 1).toString(36).substring(7); return (Math.random() + 1).toString(36).substring(7);
} }
export const clearPk = async (): Promise<void> => {
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) => export const hexTostr = (hexStr: string) =>
{ {
if(hexStr.substring(0,2) === '0x') { if(hexStr.substring(0,2) === '0x') {
@ -124,6 +133,8 @@ export const hexTostr = (hexStr: string) =>
return hexStr return hexStr
} }
export const numToHexStr = (num: number) => `0x${num.toString(16)}`
export const copyAddress = async (address: string, toastRef: Ref<boolean>) => { export const copyAddress = async (address: string, toastRef: Ref<boolean>) => {
await navigator.clipboard.writeText(address) await navigator.clipboard.writeText(address)
toastRef.value = true toastRef.value = true

View File

@ -26,6 +26,12 @@ export const getBlockNumber = async () => {
return await provider.getBlockNumber() 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}) => { export const estimateGas = async ({to = '', from = '', data = '', value = '0x0' }: {to: string, from: string, data: string, value: string}) => {
const network = await getSelectedNetwork() const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc) const provider = new ethers.providers.JsonRpcProvider(network.rpc)

View File

@ -2,27 +2,37 @@
<ion-page> <ion-page>
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title>Add Network</ion-title> <ion-title>{{ isEdit ? 'Edit Network': 'Add Network' }}</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content class="ion-padding"> <ion-content class="ion-padding">
<ion-button @click="templateModal=true" expand="block">Add from popular chain list</ion-button> <ion-button @click="templateModal=true" expand="block">Add from popular chain list</ion-button>
<ion-item> <ion-item>
<ion-label>Name</ion-label> <ion-label>Name(*)</ion-label>
<ion-input v-model="name"></ion-input> <ion-input v-model="name" placeholder="ex: Polygon"></ion-input>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>ChainId</ion-label> <ion-label>ChainId(*)</ion-label>
<ion-input v-model="chainId" type="number"></ion-input> <ion-input v-model="chainId" placeholder="137" type="number"></ion-input>
</ion-item> </ion-item>
<ion-item button> <ion-item button>
<ion-icon :icon="clipboardOutline" @click="paste('pasteRpc')" /> <ion-icon :icon="clipboardOutline" @click="paste('pasteRpc')" />
<ion-label>RPC URL</ion-label> <ion-label>RPC URL(*)</ion-label>
<ion-input id="pasteRpc" v-model="rpc" ></ion-input> <ion-input id="pasteRpc" placeholder="https://polygon-mainnet.g.alchemy.com/..." v-model="rpc" ></ion-input>
</ion-item>
<ion-item button>
<ion-icon :icon="clipboardOutline" @click="paste('pasteRpc')" />
<ion-label>Native Token Symbol(?)</ion-label>
<ion-input id="pasteRpc" placeholder="MATIC" v-model="symbol" ></ion-input>
</ion-item>
<ion-item button>
<ion-icon :icon="clipboardOutline" @click="paste('pasteExplorer')" />
<ion-label>Explorer(?)</ion-label>
<ion-input id="pasteExplorer" placeholder="https://polygon-scan.com" v-model="explorer" ></ion-input>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-button @click="onCancel">Cancel</ion-button> <ion-button @click="onCancel">Cancel</ion-button>
<ion-button @click="onAddNetwork">Add Network</ion-button> <ion-button @click="onAddNetwork">{{ isEdit ? 'Edit Network': 'Add Network' }}</ion-button>
</ion-item> </ion-item>
<ion-alert <ion-alert
:is-open="alertOpen" :is-open="alertOpen"
@ -85,13 +95,14 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from "vue"; import { defineComponent, ref } from "vue";
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonItem, IonLabel, IonInput, IonButton, IonIcon, 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"; } 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 router from "@/router";
import { mainNets, testNets } from "@/utils/networks" import { mainNets, testNets } from "@/utils/networks"
import { useRoute } from 'vue-router'
import { clipboardOutline } from "ionicons/icons"; import { clipboardOutline } from "ionicons/icons";
import type { Networks, Network } from '@/extension/types'
export default defineComponent({ export default defineComponent({
components: { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonItem, IonLabel, IonInput, IonButton, IonIcon, components: { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonItem, IonLabel, IonInput, IonButton, IonIcon,
@ -100,10 +111,33 @@ export default defineComponent({
const name = ref('') const name = ref('')
const chainId = ref(0) const chainId = ref(0)
const rpc = ref('') const rpc = ref('')
const symbol = ref('')
const explorer = ref('')
const templateModal = ref(false) const templateModal = ref(false)
const currentSegment = ref('mainnets') const currentSegment = ref('mainnets')
const alertOpen = ref(false) const alertOpen = ref(false)
const alertMsg = ref('') const alertMsg = ref('')
const route = useRoute()
const isEdit = route.path.includes('/edit')
const paramChainId = route.params.chainId ?? ""
let networksProm: Promise<Networks | undefined>
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 = () => { const resetFields = () => {
name.value = '' name.value = ''
@ -133,25 +167,27 @@ export default defineComponent({
} }
} }
let p1 = Promise.resolve() let p1 = Promise.resolve()
const networks = await getNetworks() if(!networksProm) {
if( (Object.keys(networks).length ?? 0) < 1 ){ networksProm = getNetworks()
p1 = saveSelectedNetwork({ }
const networks = await networksProm as Networks
const network = {
name: name.value, name: name.value,
chainId: chainId.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 { } else {
if((chainId.value in networks) && !isEdit){
if(chainId.value in networks){
alertMsg.value = "Network already exists." alertMsg.value = "Network already exists."
return alertOpen.value = true return alertOpen.value = true
} }
} }
const p2 = saveNetwork({ networks[chainId.value] = network
name: name.value, const p2 = replaceNetworks(networks)
chainId: chainId.value,
rpc: rpc.value
})
await Promise.all([p1, p2]) await Promise.all([p1, p2])
router.push('/') router.push('/')
resetFields() resetFields()
@ -166,9 +202,7 @@ export default defineComponent({
} }
const fillTemplate = (network: typeof mainNets[1] ) =>{ const fillTemplate = (network: typeof mainNets[1] ) =>{
name.value = network.name fillNetworkInputs(network)
chainId.value = network.chainId
rpc.value = network.rpc
modalController.dismiss(null, 'cancel') modalController.dismiss(null, 'cancel')
} }
@ -188,7 +222,10 @@ export default defineComponent({
getUrl, getUrl,
fillTemplate, fillTemplate,
alertOpen, alertOpen,
alertMsg alertMsg,
symbol,
explorer,
isEdit
} }
} }

View File

@ -27,8 +27,8 @@
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-chip>Edit</ion-chip> <router-link :to="`/add-network/edit/${network.chainId}`" ><ion-chip>Edit</ion-chip></router-link>
<ion-chip>Delete</ion-chip> <ion-chip @click="deleteNetwork">Delete</ion-chip>
</ion-item> </ion-item>
</ion-list> </ion-list>
</ion-content> </ion-content>
@ -37,7 +37,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, Ref } from "vue"; import { defineComponent, ref, Ref } from "vue";
import { getNetworks, copyAddress, getUrl } from "@/utils/platform" import { getNetworks, copyAddress, getUrl, replaceNetworks } from "@/utils/platform"
import { import {
IonContent, IonContent,
IonHeader, IonHeader,
@ -75,7 +75,7 @@ export default defineComponent({
IonAvatar IonAvatar
}, },
setup () { setup () {
const networks = ref([]) as Ref<Networks> const networks = ref({}) as Ref<Networks>
const loading = ref(true) const loading = ref(true)
const toastState = ref(false) const toastState = ref(false)
@ -89,6 +89,13 @@ export default defineComponent({
}) })
} }
const deleteNetwork = async (chainId: number) => {
loading.value = true
delete networks.value[chainId]
await replaceNetworks(networks.value)
loading.value = false
}
onIonViewWillEnter(() => { onIonViewWillEnter(() => {
loadData() loadData()
}) })
@ -101,7 +108,8 @@ export default defineComponent({
copyAddress, copyAddress,
getToastRef, getToastRef,
getUrl, getUrl,
mainNets mainNets,
deleteNetwork
} }
} }

View File

@ -88,6 +88,21 @@
</div> </div>
</ion-accordion> </ion-accordion>
<ion-accordion value="4"> <ion-accordion value="4">
<ion-item slot="header" color="light">
<ion-label> Import / Export Accounts</ion-label>
</ion-item>
<div class="ion-padding" slot="content">
<ion-item>
<ion-label>Import Additional Accounts</ion-label>
<ion-button color="danger" @click="importAcc">Import</ion-button>
</ion-item>
<ion-item>
<ion-label>Export All Accounts</ion-label>
<ion-button color="danger" @click="exportAcc">Export</ion-button>
</ion-item>
</div>
</ion-accordion>
<ion-accordion value="5">
<ion-item slot="header" color="light"> <ion-item slot="header" color="light">
<ion-label>Danger</ion-label> <ion-label>Danger</ion-label>
</ion-item> </ion-item>
@ -240,7 +255,6 @@ export default defineComponent({
const saveSettings = async () => { const saveSettings = async () => {
loading.value = true loading.value = true
settings.s.lockOutPeriod = settings.s.lockOutPeriod * 6e4
await setSettings(settings.s) await setSettings(settings.s)
loading.value = false loading.value = false
} }
@ -278,11 +292,9 @@ export default defineComponent({
const accProm = accounts.map(async a => { const accProm = accounts.map(async a => {
a.encPk = await encrypt(mpPass.value, a.pk) a.encPk = await encrypt(mpPass.value, a.pk)
a.pk = '' a.pk = ''
console.log(a)
return a return a
}) })
accounts = await Promise.all(accProm) accounts = await Promise.all(accProm)
console.log(accounts)
await replaceAccounts(accounts) await replaceAccounts(accounts)
await saveSelectedAccount(accounts[0]) await saveSelectedAccount(accounts[0])
setEncryptToggle(true) setEncryptToggle(true)
@ -321,13 +333,20 @@ export default defineComponent({
// settings.s.enableStorageEnctyption = true; // settings.s.enableStorageEnctyption = true;
loading.value = false loading.value = false
} }
const importAcc = async () => {
//
}
const exportAcc = async () => {
//
}
onIonViewWillEnter( () => { onIonViewWillEnter( () => {
getSettings().then((storeSettings) => getSettings().then((storeSettings) =>
{ {
settings.s = storeSettings settings.s = storeSettings
settings.s.lockOutPeriod = (settings.s.lockOutPeriod / 6e4)
loading.value = false loading.value = false
}) })
@ -368,7 +387,9 @@ export default defineComponent({
modalDismiss, modalDismiss,
setTime, setTime,
toastState, toastState,
toastMsg toastMsg,
importAcc,
exportAcc
}; };
}, },
}); });

View File

@ -17,6 +17,7 @@
<ion-button @click="onCancel">Cancel</ion-button> <ion-button @click="onCancel">Cancel</ion-button>
<ion-button @click="onSign">Sign</ion-button> <ion-button @click="onSign">Sign</ion-button>
</ion-item> </ion-item>
<ion-item>Auto-reject Timer: {{ timerReject }}</ion-item>
<ion-alert <ion-alert
:is-open="alertOpen" :is-open="alertOpen"
header="Error" header="Error"
@ -49,13 +50,14 @@ import {
IonAlert, IonAlert,
IonText, IonText,
IonLoading, IonLoading,
modalController modalController,
onIonViewWillEnter
} from "@ionic/vue"; } from "@ionic/vue";
// import { ethers } from "ethers"; // import { ethers } from "ethers";
import { import {
hexTostr, hexTostr,
} from "@/utils/platform"; } from "@/utils/platform";
import { approve } from "@/extension/userRequest"; import { approve, walletPing } from "@/extension/userRequest";
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { getSelectedAccount } from '@/utils/platform' import { getSelectedAccount } from '@/utils/platform'
import UnlockModal from '@/views/UnlockModal.vue' import UnlockModal from '@/views/UnlockModal.vue'
@ -81,11 +83,33 @@ export default defineComponent({
const signMsg = ref(hexTostr(route?.params?.param as string ?? '')); const signMsg = ref(hexTostr(route?.params?.param as string ?? ''));
const alertOpen = ref(false); const alertOpen = ref(false);
const alertMsg = ref(""); const alertMsg = ref("");
const timerReject = ref(140);
let interval: any
const onCancel = () => { const onCancel = () => {
window.close() window.close();
if(interval) {
try {
clearInterval(interval)
} catch {
// ignore
}
}
}; };
onIonViewWillEnter(async () => {
interval = setInterval(async () => {
if(timerReject.value <= 0) {
onCancel()
return;
}
timerReject.value -= 1
walletPing()
}, 1000) as any
});
const openModal = async () => { const openModal = async () => {
const modal = await modalController.create({ const modal = await modalController.create({
component: UnlockModal, component: UnlockModal,
@ -123,7 +147,8 @@ export default defineComponent({
alertOpen, alertOpen,
alertMsg, alertMsg,
onSign, onSign,
loading loading,
timerReject
}; };
}, },
}); });

View File

@ -24,25 +24,25 @@
<ion-label>Transaction to Sign &amp; Send</ion-label> <ion-label>Transaction to Sign &amp; Send</ion-label>
</ion-item> </ion-item>
<ion-item> <ion-item>
Last Balance: {{ userBalance }} Last Balance: {{ userBalance }} <span style="opacity:0.7" v-if="dollarPrice > 0">${{ dollarPrice*userBalance }}</span>
</ion-item> </ion-item>
<ion-item> <ion-item>
Contract: {{ contract }} Contract: {{ contract }}
</ion-item> </ion-item>
<ion-item> <ion-item>
Tx Total Cost: {{ totalCost }} Tx Total Cost: {{ totalCost }} <span style="opacity:0.7" v-if="dollarPrice > 0">${{ dollarPrice*totalCost }}</span>
</ion-item> </ion-item>
<ion-item> <ion-item>
Gas Fee: {{ gasFee }} Gas Fee: {{ gasFee }} <span style="opacity:0.7" v-if="dollarPrice > 0">${{ dollarPrice*gasFee }}</span>
</ion-item> </ion-item>
<ion-item> <ion-item>
Tx value: {{ txValue }} Tx value: {{ txValue }}
</ion-item> </ion-item>
<ion-item> <ion-item>
Gas Limit: {{ gasLimit }} <ion-button @click="setGasLimit">Set manually</ion-button> Gas Limit: {{ gasLimit }} <ion-button style="margin-left: 1rem" @click="gasLimitModal=true">Set manually</ion-button>
</ion-item> </ion-item>
<ion-item> <ion-item>
Gas Price: {{ gasPrice}} <ion-button @click="setGasPrice">Set manually</ion-button> Gas Price: {{ gasPrice }} <ion-button style="margin-left: 1rem" @click="gasPriceModal=true">Set manually</ion-button>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Raw TX:</ion-label> <ion-label>Raw TX:</ion-label>
@ -75,6 +75,59 @@
@didDismiss="loading = false" @didDismiss="loading = false"
> >
</ion-loading> </ion-loading>
<ion-modal
:is-open="gasLimitModal"
>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="gasLimitModal=false">Close</ion-button>
</ion-buttons>
<ion-title>Set Gas Limit</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-list>
<ion-item>
<ion-label>Limit in units</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="inGasLimit" type="number"></ion-input>
</ion-item>
<ion-item>
<ion-button @click="setGasLimit">Set Price</ion-button>
</ion-item>
</ion-list>
</ion-content>
</ion-modal>
<ion-modal
:is-open="gasPriceModal"
>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="gasPriceModal=false">Close</ion-button>
</ion-buttons>
<ion-title>Set Gas Price</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-list>
<ion-item>
<ion-label>Price in gwei</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="inGasPrice" type="number"></ion-input>
</ion-item>
<ion-item>
<ion-button @click="setGasPrice">Set Price</ion-button>
</ion-item>
</ion-list>
</ion-content>
</ion-modal>
</ion-content> </ion-content>
</ion-page> </ion-page>
@ -95,12 +148,15 @@ import {
IonTextarea, IonTextarea,
onIonViewWillEnter, onIonViewWillEnter,
IonList, IonList,
IonLoading IonLoading,
IonModal,
IonButtons,
IonInput
} from "@ionic/vue"; } from "@ionic/vue";
import { ethers } from "ethers"; import { ethers } from "ethers";
import { approve, walletPing, walletSendData } from "@/extension/userRequest"; import { approve, walletPing, walletSendData } from "@/extension/userRequest";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getSelectedNetwork, getUrl } from '@/utils/platform' import { getSelectedNetwork, getUrl, getPrices, numToHexStr } from '@/utils/platform'
import { getBalance, getGasPrice, estimateGas } from '@/utils/wallet' import { getBalance, getGasPrice, estimateGas } from '@/utils/wallet'
import type { Network } from '@/extension/types' import type { Network } from '@/extension/types'
import { mainNets } from "@/utils/networks"; import { mainNets } from "@/utils/networks";
@ -118,7 +174,10 @@ export default defineComponent({
IonAlert, IonAlert,
IonTextarea, IonTextarea,
IonList, IonList,
IonLoading IonLoading,
IonModal,
IonButtons,
IonInput
}, },
setup: () => { setup: () => {
const route = useRoute(); const route = useRoute();
@ -142,6 +201,12 @@ export default defineComponent({
const insuficientBalance = ref(false) const insuficientBalance = ref(false)
const gasPriceReFetch = ref(true) const gasPriceReFetch = ref(true)
const selectedNetwork = (ref(null) as unknown) as Ref<Network>; const selectedNetwork = (ref(null) as unknown) as Ref<Network>;
const dollarPrice = ref(0)
const gasLimitModal = ref(false)
const gasPriceModal = ref(false)
const inGasPrice = ref(0)
const inGasLimit = ref(0)
let interval = 0 let interval = 0
const bars = ref(0) const bars = ref(0)
@ -170,6 +235,12 @@ export default defineComponent({
} }
}; };
const newGasData = () => {
gasFee.value = Number(ethers.utils.formatUnits(String(gasLimit.value * gasPrice.value), "gwei"))
txValue.value = Number(ethers.utils.formatEther(params?.value ?? '0x0'))
totalCost.value = gasFee.value + txValue.value
}
onIonViewWillEnter(async () => { onIonViewWillEnter(async () => {
console.log(params.value); console.log(params.value);
(window as any)?.resizeTo?.(600, 800) (window as any)?.resizeTo?.(600, 800)
@ -181,19 +252,26 @@ export default defineComponent({
}) })
const pGasPrice = getGasPrice() const pGasPrice = getGasPrice()
const pBalance = getBalance() const pBalance = getBalance()
const pGetPrices = getPrices()
selectedNetwork.value = await getSelectedNetwork() selectedNetwork.value = await getSelectedNetwork()
userBalance.value = Number(ethers.utils.formatEther((await pBalance).toString())) userBalance.value = Number(ethers.utils.formatEther((await pBalance).toString()))
console.log(userBalance.value)
gasPrice.value = parseInt(ethers.utils.formatUnits((await pGasPrice).toString(), "gwei"), 10) gasPrice.value = parseInt(ethers.utils.formatUnits((await pGasPrice).toString(), "gwei"), 10)
console.log(gasPrice.value)
gasLimit.value = parseInt((await pEstimateGas).toString(), 10) gasLimit.value = parseInt((await pEstimateGas).toString(), 10)
gasFee.value = Number(ethers.utils.formatUnits(String(gasLimit.value * gasPrice.value), "gwei"))
txValue.value = Number(ethers.utils.formatEther(params?.value ?? '0x0')) console.log( 'test', ethers.utils.formatUnits((await pGasPrice).toString(), "gwei"), ethers.utils.formatUnits(ethers.utils.parseUnits(gasPrice.value.toString(), "gwei"), "gwei") )
totalCost.value = gasFee.value + txValue.value
newGasData()
if(userBalance.value < totalCost.value){ if(userBalance.value < totalCost.value){
insuficientBalance.value = true insuficientBalance.value = true
} }
const prices = await pGetPrices
console.log('dd', prices, selectedNetwork.value?.priceId)
if ( (selectedNetwork.value?.priceId ?? 'x') in prices ){
dollarPrice.value = prices[(selectedNetwork.value?.priceId ?? 'x')]?.usd ?? 0
}
loading.value=false loading.value=false
interval = setInterval(async () => { interval = setInterval(async () => {
@ -207,8 +285,7 @@ export default defineComponent({
timerFee.value = 20 timerFee.value = 20
loading.value=true loading.value=true
gasPrice.value = parseInt(ethers.utils.formatUnits((await getGasPrice()).toString(), "gwei"), 10) gasPrice.value = parseInt(ethers.utils.formatUnits((await getGasPrice()).toString(), "gwei"), 10)
gasFee.value = Number(ethers.utils.formatUnits(String(gasLimit.value * gasPrice.value), "gwei")) newGasData()
txValue.value = Number(ethers.utils.formatEther(params?.value ?? '0x0'))
loading.value=false loading.value=false
} }
} }
@ -218,13 +295,25 @@ export default defineComponent({
walletPing() walletPing()
}, 1000) as any }, 1000) as any
}) })
const setGasLimit = () => { const setGasLimit = () => {
// TODO gasLimit.value = inGasLimit.value
walletSendData(rid, {
gas: numToHexStr(gasLimit.value)
})
newGasData()
gasLimitModal.value = false
} }
const setGasPrice = () => { const setGasPrice = () => {
// TODO gasPrice.value = inGasPrice.value
gasPriceReFetch.value = false
walletSendData(rid, {
gasPrice: ethers.utils.parseUnits(gasPrice.value.toString(), "gwei")
})
newGasData()
gasPriceModal.value = false
} }
@ -252,7 +341,12 @@ export default defineComponent({
mainNets, mainNets,
getUrl, getUrl,
setGasLimit, setGasLimit,
setGasPrice setGasPrice,
dollarPrice,
gasLimitModal,
gasPriceModal,
inGasPrice,
inGasLimit
}; };
}, },
}); });

View File

@ -35,18 +35,18 @@
<ion-item>To</ion-item> <ion-item>To</ion-item>
<ion-item> <ion-item>
<ion-list> <ion-list>
<ion-item>Network Name: {{ (templateNetworks as any)[selectedNetwork?.chainId]?.name }}</ion-item> <ion-item>Network Name: {{ (templateNetworks as any)[networkId]?.name }}</ion-item>
<ion-item> <ion-item>
<ion-avatar <ion-avatar
v-if="(templateNetworks as any)[selectedNetwork?.chainId]?.icon" v-if="(templateNetworks as any)[networkId]?.icon"
style="margin-right: 1rem; width: 1.8rem; height: 1.8rem" style="margin-right: 1rem; width: 1.8rem; height: 1.8rem"
> >
<img <img
:alt="selectedNetwork?.name" :alt="selectedNetwork?.name"
:src="getUrl('assets/chain-icons/' + (templateNetworks as any)[selectedNetwork?.chainId]?.icon)" :src="getUrl('assets/chain-icons/' + (templateNetworks as any)[networkId]?.icon)"
/> />
</ion-avatar> </ion-avatar>
<ion-label>Network ID: {{ (templateNetworks as any)[selectedNetwork?.chainId]?.chainId }}</ion-label> <ion-label>Network ID: {{ (templateNetworks as any)[networkId]?.chainId }}</ion-label>
</ion-item> </ion-item>
</ion-list> </ion-list>
</ion-item> </ion-item>
@ -59,15 +59,16 @@
</ion-item> </ion-item>
<ion-item v-else> <ion-item v-else>
<ion-list> <ion-list>
<ion-item>Request to change to unknown network ID: {{ }}</ion-item> <ion-item>Request to change to unknown network ID: {{ networkId }}</ion-item>
<ion-item>Do you want to go to {{ }}</ion-item> <ion-item>Do you want to go to {{ addChainUrl }}</ion-item>
<ion-item>To add it manually.</ion-item> <ion-item>To add it manually.</ion-item>
<ion-item> <ion-item>
<ion-button @click="onCancel">No</ion-button> <ion-button @click="onCancel">No</ion-button>
<ion-button @click="onSwitchTemplates">Yes</ion-button> <ion-button @click="onSwitchNotExisting">Yes</ion-button>
</ion-item> </ion-item>
</ion-list> </ion-list>
</ion-item> </ion-item>
<ion-item>Auto-reject Timer: {{ timerReject }}</ion-item>
</ion-list> </ion-list>
<ion-alert <ion-alert
@ -108,11 +109,11 @@ import {
IonList, IonList,
} from "@ionic/vue"; } from "@ionic/vue";
// import { ethers } from "ethers"; // import { ethers } from "ethers";
import { hexTostr } from "@/utils/platform";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getSelectedNetwork, getNetworks, getUrl } from "@/utils/platform"; import { getSelectedNetwork, getNetworks, getUrl, saveSelectedNetwork, saveNetwork, openTab} from "@/utils/platform";
import type { Network } from "@/extension/types"; import type { Network, Networks } from "@/extension/types";
import { mainNets, testNets } from "@/utils/networks"; import { mainNets, testNets } from "@/utils/networks";
import { approve, walletPing } from '@/extension/userRequest'
export default defineComponent({ export default defineComponent({
components: { components: {
@ -133,55 +134,76 @@ export default defineComponent({
const route = useRoute(); const route = useRoute();
const loading = ref(true); const loading = ref(true);
const rid = (route?.params?.rid as string) ?? ""; const rid = (route?.params?.rid as string) ?? "";
const networkId = ref(hexTostr((route?.params?.param as string) ?? "")); const networkId = ref(String(Number(route?.params?.param as string ?? "")));
const alertOpen = ref(false); const alertOpen = ref(false);
const selectedNetwork = (ref(null) as unknown) as Ref<Network>; const selectedNetwork = (ref(null) as unknown) as Ref<Network>;
const alertMsg = ref(""); const alertMsg = ref("");
const networkCase = ref(""); const networkCase = ref("");
let pnetworks; let pnetworks: Promise<Networks>;
const templateNetworks = Object.assign({}, mainNets, testNets) ?? {}; const templateNetworks = Object.assign({}, mainNets, testNets) ?? {};
const addChainUrl = `${chainListPage}${networkId.value}`
const timerReject = ref(140);
let interval: any
const onCancel = () => { const onCancel = () => {
window.close(); window.close();
if(interval) {
try {
clearInterval(interval)
} catch {
// ignore
}
}
}; };
onIonViewWillEnter(async () => { onIonViewWillEnter(async () => {
(window as any)?.resizeTo?.(600, 600)
pnetworks = getNetworks(); pnetworks = getNetworks();
selectedNetwork.value = await getSelectedNetwork(); selectedNetwork.value = await getSelectedNetwork();
const chainId = parseInt(networkId.value, 16); console.log(networkId.value)
const existingNetworks = await pnetworks; const existingNetworks = await pnetworks;
if ((chainId ?? "0") in existingNetworks ?? {}) { if ((networkId.value ?? "0") in existingNetworks ?? {}) {
networkCase.value = "exists"; networkCase.value = "exists";
} else if ((chainId ?? "0") in templateNetworks) { } else if ((networkId.value ?? "0") in templateNetworks) {
networkCase.value = "inTemplates"; networkCase.value = "inTemplates";
} else { } else {
networkCase.value = "doesNotExist"; networkCase.value = "doesNotExist";
} }
loading.value = false; loading.value = false;
interval = setInterval(async () => {
if(timerReject.value <= 0) {
onCancel()
return;
}
timerReject.value -= 1
walletPing()
}, 1000) as any
}); });
const onSwitchExists = async () => { const onSwitchExists = async () => {
loading.value = true; loading.value = true;
const existingNetworks = await pnetworks;
// const selectedAccount = await getSelectedAccount(); selectedNetwork.value = existingNetworks[Number(networkId.value)]
// if ((selectedAccount.pk ?? "").length !== 66) { await saveSelectedNetwork(selectedNetwork.value)
// const modalResult = await openModal(); approve(rid);
// if (modalResult) { loading.value = false;
// approve(rid);
// } else {
// onCancel();
// }
// } else {
// approve(rid);
// }
// loading.value = false;
}; };
const onSwitchTemplates = async () => { const onSwitchTemplates = async () => {
loading.value = true; loading.value = true;
selectedNetwork.value = templateNetworks[Number(networkId.value)]
saveNetwork(templateNetworks[Number(networkId.value)])
saveSelectedNetwork(templateNetworks[Number(networkId.value)])
approve(rid);
loading.value = true;
}; };
const onSwitchNotExisting = async () => { const onSwitchNotExisting = async () => {
loading.value = true; loading.value = true;
openTab(addChainUrl)
onCancel()
}; };
return { return {
@ -196,7 +218,9 @@ export default defineComponent({
templateNetworks, templateNetworks,
getUrl, getUrl,
onSwitchTemplates, onSwitchTemplates,
onSwitchNotExisting onSwitchNotExisting,
addChainUrl,
timerReject
}; };
}, },
}); });