diff --git a/.gitignore b/.gitignore index 1fe4ece..9743756 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ npm-debug.log* /plugins /www /src/extension/inject.js +readme.md \ No newline at end of file diff --git a/src/extension/content.ts b/src/extension/content.ts index d78fb1e..74b551e 100644 --- a/src/extension/content.ts +++ b/src/extension/content.ts @@ -12,6 +12,7 @@ const allowedMethods = { 'eth_sign': true, 'net_version': true, 'eth_sendTransaction': true, + 'wallet_switchEthereumChain': true } window.addEventListener("message", (event) => { diff --git a/src/extension/inject.ts b/src/extension/inject.ts index c373446..282d717 100644 --- a/src/extension/inject.ts +++ b/src/extension/inject.ts @@ -42,6 +42,7 @@ return new Promise((resolve, reject) => { const resId = crypto.randomUUID() promResolvers[resId] = { resolve, reject } const data = { type: "CLWALLET_CONTENT", data: args, resId}; + console.log('data in', data) window.postMessage(data, "*"); }) } diff --git a/src/extension/serviceWorker.ts b/src/extension/serviceWorker.ts index 051880e..792d1d4 100644 --- a/src/extension/serviceWorker.ts +++ b/src/extension/serviceWorker.ts @@ -1,4 +1,4 @@ -import { getAccounts, getSelectedAccount, getSelectedNetwork, smallRandomString, getSettings, clearPk, openTab } from '@/utils/platform'; +import { getAccounts, getSelectedAccount, getSelectedNetwork, smallRandomString, getSettings, clearPk, openTab, getUrl } from '@/utils/platform'; import { userApprove, userReject, rIdWin, rIdData } from '@/extension/userRequest' import { signMsg, getBalance, getBlockNumber, estimateGas, sendTransaction, getGasPrice, getBlockByNumber } from '@/utils/wallet' import type { RequestArguments } from '@/extension/types' @@ -40,6 +40,12 @@ chrome.alarms.onAlarm.addListener((alarm) => { console.log('Prices updated') }) } + getSettings().then((settings) => { + if( ((settings.lastLock + settings.lockOutPeriod * 6e4) < Date.now()) && settings.lockOutEnabled && !settings.lockOutBlocked ) { + settings.lastLock = Date.now() + clearPk() + } + }) }) chrome.windows.onRemoved.addListener(async (winId) => { @@ -89,11 +95,16 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes } case 'eth_getBlockByNumber': { const params = message?.params?.[0] as any - sendResponse(await getBlockByNumber(params)) + const block = await getBlockByNumber(params) as any + block.gasLimit = block.gasLimit.toHexString() + block.gasUsed = block.gasUsed.toHexString() + block.baseFeePerGas = block.baseFeePerGas.toHexString() + block._difficulty = block._difficulty.toHexString() + sendResponse(block) break; } case 'eth_gasPrice': { - sendResponse(await getGasPrice()) + sendResponse((await getGasPrice()).toHexString()) break; } case 'eth_getBalance': { @@ -156,6 +167,7 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes if(!account || !network) { return } + params.from = account.address const serializeParams = encodeURIComponent(JSON.stringify(params)) ?? '' const pEstimateGas = estimateGas({ to: params?.to ?? '', @@ -178,7 +190,7 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes rIdWin[String(win.id)] = String(message.resId) rIdData[String(win.id)] = {} }) - + }) try { const tx = await sendTransaction({...params, ...(rIdData?.[String(gWin?.id ?? 0)] ?? {}) }, pEstimateGas, pGasPrice) @@ -199,14 +211,16 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes } }, 6e4) } - chrome.notifications.create({ - notificationId, + chrome.notifications.create(notificationId,{ message: 'Transaction Confirmed', title: 'Success', + iconUrl: getUrl('assets/extension-icon/wallet_128.png'), + type: 'basic', ...(buttons) } as any) - } catch { + } catch (err) { + console.log(err) sendResponse({ error: true, code: rpcError.USER_REJECTED, @@ -215,10 +229,12 @@ chrome.runtime.onMessage.addListener((message: RequestArguments, sender, sendRes chrome.notifications.create({ message: 'Transaction Failed', title: 'Error', + iconUrl: getUrl('assets/extension-icon/wallet_128.png'), + type: 'basic' } as any) } } catch(err) { - // console.error(err) + // console.log(err) sendResponse({ error: true, code: rpcError.USER_REJECTED, diff --git a/src/extension/types.ts b/src/extension/types.ts index 26a6548..ac62ce0 100644 --- a/src/extension/types.ts +++ b/src/extension/types.ts @@ -50,4 +50,5 @@ export interface Settings { lockOutEnabled: boolean theme: 'system' | 'light' | 'dark' lastLock: number + lockOutBlocked: boolean } \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts index 308f783..314c72c 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -19,6 +19,10 @@ const routes: Array = [ path: '/switch-network/:rid/:param', component: () => import('@/views/SwitchNetwork.vue'), }, + { + path: '/contract-error/:rid/:param/:contract', + component: () => import('@/views/ContractError.vue'), + }, { path: '/tabs/', component: AppTabs, diff --git a/src/utils/networks.ts b/src/utils/networks.ts index 916833b..d9ad9bb 100644 --- a/src/utils/networks.ts +++ b/src/utils/networks.ts @@ -6,16 +6,16 @@ export const mainNets: {[key: number]: Network} = { name: 'Ethereum Main', rpc: 'https://eth-mainnet.public.blastapi.io', chainId: 1, - explorer: '', + explorer: 'https://etherscan.io', icon: 'eth.webp', symbol: 'ETH', - priceId: 'ethereum' + priceId: 'ethereum', }, 137: { name: 'Polygon Mainnet', rpc: 'https://polygon-rpc.com', chainId: 137, - explorer: '', + explorer: 'https://polygonscan.com', icon:'polygon.webp', symbol: 'MATIC', priceId: 'matic-network' @@ -24,7 +24,7 @@ export const mainNets: {[key: number]: Network} = { name: 'Gnosis', rpc: 'https://rpc.gnosischain.com/', chainId: 100, - explorer: '', + explorer: 'https://gnosisscan.io', icon:'xdai.webp', symbol: 'xDAI', priceId: 'xdai' @@ -33,7 +33,7 @@ export const mainNets: {[key: number]: Network} = { name: 'Optimism', rpc: 'https://mainnet.optimism.io', chainId: 10, - explorer: '', + explorer: 'https://optimistic.etherscan.io', icon: 'optimism.webp', symbol: 'ETH', priceId: 'ethereum' @@ -42,7 +42,7 @@ export const mainNets: {[key: number]: Network} = { name: 'BSC Main', rpc: 'https://bsc-dataseed2.binance.org', chainId: 56, - explorer: '', + explorer: 'https://bscscan.com', icon: 'binance.webp', symbol: 'BNB', priceId: 'binancecoin' @@ -51,7 +51,7 @@ export const mainNets: {[key: number]: Network} = { name: 'Arbitrum One', rpc: 'https://rpc.ankr.com/arbitrum', chainId: 42161, - explorer: '', + explorer: 'https://explorer.offchainlabs.com', icon: 'arbitrum.webp', symbol: 'ETH', priceId: 'ethereum' @@ -77,7 +77,7 @@ export const testNets = { name: 'TESTNET Polygon', rpc: 'https://rpc.ankr.com/polygon_mumbai', chainId: 80001, - explorer: '', + explorer: 'https://mumbai.polygonscan.com/', icon:'polygon.webp' }, 100100: { @@ -91,21 +91,21 @@ export const testNets = { name: 'TESTNET Optimism Goreli', rpc: 'https://goerli.optimism.io/', chainId: 420, - explorer: '', + explorer: 'https://goerli.etherscan.io/', icon: 'optimism.webp' }, 97: { - name: 'TESTNET BSC Main', + name: 'TESTNET BSC', rpc: 'https://bsctestapi.terminet.io/rpc', chainId: 97, - explorer: '', + explorer: 'https://testnet.bscscan.com/', icon: 'binance.webp' }, 421613: { name: 'TESTNET Arbitrum One', rpc: 'https://goerli-rollup.arbitrum.io/rpc/', chainId: 421613, - explorer: '', + explorer: 'https://testnet.arbiscan.io/', icon: 'arbitrum.webp' }, } diff --git a/src/utils/platform.ts b/src/utils/platform.ts index fc68c22..434e690 100644 --- a/src/utils/platform.ts +++ b/src/utils/platform.ts @@ -5,10 +5,10 @@ const defaultSettings = { enableStorageEnctyption: false, encryptAfterEveryTx: false, lockOutEnabled: false, - lockOutPeriod: 12e4, + lockOutPeriod: 2, lockOutBlocked: false, theme: 'system', - MP: '' + lastLock: Date.now() } export const storageSave = async (key: string, value: any): Promise =>{ @@ -87,6 +87,20 @@ export const setSettings = async (settings: Settings): Promise => { await storageSave('settings', settings ) } +export const blockLockout = async (): Promise => { + const settings = await getSettings() + settings.lockOutBlocked = true + await setSettings(settings) + return settings +} + +export const unBlockLockout = async (): Promise => { + const settings = await getSettings() + settings.lockOutBlocked = false + await setSettings(settings) + return settings +} + export const getBalanceCache = async (): Promise => { return (await storageGet('balance'))?.balance ?? '0x0' } @@ -125,20 +139,21 @@ export const hexTostr = (hexStr: string) => for (let i = 0, charsLength = hexCodes.length; i < charsLength; i += 2) { chunks.push(hexCodes.substring(i, i + 2)); } - return chunks.reduce( - (pv, cv) => `${pv}${String.fromCharCode(parseInt(cv, 16))}`, - '' - ).substring(0, 66) + return chunks.reduce( + (pv, cv) => `${pv}${String.fromCharCode(parseInt(cv, 16))}`, + '') } return hexStr } +export const strToHex = (str: string) => `0x${str.split('').map( s => s.charCodeAt(0).toString(16) ).join('')}` + export const numToHexStr = (num: number) => `0x${num.toString(16)}` - export const copyAddress = async (address: string, toastRef: Ref) => { +export const copyAddress = async (address: string, toastRef: Ref) => { await navigator.clipboard.writeText(address) toastRef.value = true - } +} export const getUrl = (url: string) => chrome.runtime.getURL(url) diff --git a/src/utils/webCrypto.ts b/src/utils/webCrypto.ts index 9448794..48bd52c 100644 --- a/src/utils/webCrypto.ts +++ b/src/utils/webCrypto.ts @@ -51,19 +51,9 @@ async function getKey(passwordBytes: Uint8Array) { export const encrypt = async (password: string, data:string) => { const enc = new TextEncoder() const encData = enc.encode(data) - console.log(encData) const encKey = enc.encode(password) - console.log(encKey) const key = await getKey(encKey) - console.log(key) const iv = await getIv() - console.log(iv) - console.log({ - name: "AES-GCM", - iv, - }, - key, - encData) const encResult = await crypto.subtle.encrypt( { name: "AES-GCM", @@ -72,7 +62,6 @@ export const encrypt = async (password: string, data:string) => { key, encData, ) - console.log(JSON.stringify(new Uint8Array(encResult))) return JSON.stringify(new Uint8Array(encResult)) } @@ -82,7 +71,6 @@ export const decrypt = async (encryptedData: string, password: string) => { const key = await getKey(encKey) const iv = await getIv() const encryptedUint= new Uint8Array(Object.values(JSON.parse(encryptedData))); - console.log(encryptedUint) const contentBytes = new Uint8Array( await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, encryptedUint) ); diff --git a/src/views/AddNetwork.vue b/src/views/AddNetwork.vue index 8c5062e..267ff41 100644 --- a/src/views/AddNetwork.vue +++ b/src/views/AddNetwork.vue @@ -28,7 +28,7 @@ Explorer(?) - + Cancel diff --git a/src/views/ContractError.vue b/src/views/ContractError.vue new file mode 100644 index 0000000..8129fcd --- /dev/null +++ b/src/views/ContractError.vue @@ -0,0 +1,113 @@ + + + diff --git a/src/views/NetworksTab.vue b/src/views/NetworksTab.vue index 285bb57..0a7ed0e 100644 --- a/src/views/NetworksTab.vue +++ b/src/views/NetworksTab.vue @@ -16,7 +16,7 @@ - + @@ -27,8 +27,8 @@ - Edit - Delete + Edit + Delete @@ -56,6 +56,7 @@ import { } from "@ionic/vue"; import { mainNets } from "@/utils/networks" import { addCircleOutline, copyOutline } from "ionicons/icons"; +import router from '@/router/index' import type { Networks } from '@/extension/types' export default defineComponent({ @@ -96,6 +97,10 @@ export default defineComponent({ loading.value = false } + const editNetwork = (chainId: number) => { + router.push(`add-network/edit/${chainId}`) + } + onIonViewWillEnter(() => { loadData() }) @@ -109,7 +114,8 @@ export default defineComponent({ getToastRef, getUrl, mainNets, - deleteNetwork + deleteNetwork, + editNetwork } } diff --git a/src/views/SettingsTab.vue b/src/views/SettingsTab.vue index 15a6d34..676cbd7 100644 --- a/src/views/SettingsTab.vue +++ b/src/views/SettingsTab.vue @@ -94,11 +94,12 @@
Import Additional Accounts - Import + + Import Export All Accounts - Export + Export
@@ -181,7 +182,7 @@