chore: changes for 1.3.9

This commit is contained in:
Andrei O 2024-06-27 00:18:36 +03:00
parent 8b624ea8a2
commit d3aeecc7a1
No known key found for this signature in database
GPG Key ID: B961E5B68389457E
20 changed files with 862 additions and 807 deletions

View File

@ -1,5 +1,15 @@
# Changelog
## Manifest Version 1.3.9
- add an additional throttle on 'eth_chainId' to prevent websites from spamming the wallet with requests
- change inject throttle to only affect UI requests
- updated some core dependencies
- optimized performance for json rpc calls
- disabled assets fetch until new provider is found before yup.io was used
- simplified wallet switching
- added sonarCloud badge to README.md
## Manifest Version 1.3.8
- improved sign message display to better accomodate SIWE & other messages

View File

@ -12,6 +12,10 @@ For more info you can check [docs website](https://clear-wallet.flashsoft.eu)
[![Clear EVM Wallet (CLW) - Open source EVM wallet that implements meta mask API. | Product Hunt](https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=381026&theme=dark)](https://www.producthunt.com/posts/clear-evm-wallet-clw?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-clear-evm-wallet-clw)
### Badges
[![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=andrei0x309_clear-wallet)](https://sonarcloud.io/summary/new_code?id=andrei0x309_clear-wallet)
### Extended article about this repo
[Article on Mirror](https://mirror.xyz/andrei0x309.eth/9nc8UXrGIGOvz694ZY2gouS1JM9L8-Z8ITLNtirqD6Q)

View File

@ -1,13 +1,29 @@
<!DOCTYPE html>
<html>
<html lang="en" style="width:400px;height:500px">
<head>
<meta charset="utf-8" />
<title>Clear Wallet SandBox</title>
<base href="/" />
<meta name="color-scheme" content="light dark" />
<meta
name="viewport"
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Clear Wallet" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
</head>
<body>
<h1>Eval Sandbox</h1>
<script>
// console.log('sandbox loaded');
console.info('sandbox loaded');
window.addEventListener('message', function (event) {
// console.log('message received', event);
const data = event.data;
const execFunc = new Function(
'return ' + data.code

View File

@ -16,39 +16,38 @@
"pub": "yarn build && yarn release && yarn tsx ./release-scripts/create-release.ts"
},
"dependencies": {
"@ionic/vue": "^7.2.3",
"@ionic/vue-router": "^7.2.3",
"core-js": "^3.32.0",
"ethers": "^6.11.1",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
"@ionic/vue": "^7.8.6",
"@ionic/vue-router": "^7.8.6",
"core-js": "^3.37.1",
"ethers": "^6.13.1",
"vue": "^3.4.29",
"vue-router": "^4.3.3"
},
"devDependencies": {
"@capacitor/cli": "^5.2.3",
"@crxjs/vite-plugin": "^2.0.0-beta.23",
"@types/archiver": "^5.3.2",
"@types/chrome": "^0.0.243",
"@types/archiver": "^5.3.4",
"@types/chrome": "^0.0.268",
"@types/jest": "^29.5.3",
"@types/node": "^20.5.0",
"@typescript-eslint/eslint-plugin": "^6.3.0",
"@typescript-eslint/parser": "^6.3.0",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/eslint-config-typescript": "^11.0.3",
"@types/node": "^20.14.5",
"@typescript-eslint/eslint-plugin": "^7.13.0",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-vue": "^5.0.5",
"@vue/eslint-config-typescript": "^13.0.0",
"archiver": "^5.3.1",
"eslint": "^8.47.0",
"eslint-plugin-vue": "^9.17.0",
"eslint": "^8.56.0",
"eslint-plugin-vue": "^9.26.0",
"http-browserify": "^1.7.0",
"https-browserify": "^1.0.0",
"jest": "^29.6.2",
"rollup-plugin-polyfill-node": "^0.12.0",
"sass": "^1.65.1",
"sass": "^1.77.6",
"stream-browserify": "^3.0.0",
"ts-jest": "^29.1.1",
"tsx": "^4.8.0",
"typescript": "^5.1.6",
"tsx": "^4.15.6",
"typescript": "^5.4.5",
"util": "^0.12.5",
"vite": "^5.2.10",
"vue-tsc": "^1.8.8",
"vite": "^5.3.1",
"vue-tsc": "^2.0.21",
"yarn-upgrade-all": "^0.7.2"
},
"disabledNativeDependencies": {

View File

@ -14,8 +14,6 @@
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<!-- <link rel="shortcut icon" type="image/png" href="<%= BASE_URL %>assets/icon/favicon.png" /> -->
<!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Clear Wallet" />

View File

@ -47,7 +47,6 @@ async function ghRelease(changes: string[]) {
const p = cps.spawn('gh', ['release', 'create', `v${pkg.version}`, `./${outputPath}`, '-F', `./${changeLogPath}`], {
shell: true,
});
// const p = spawn('pwd');
let result = '';
p.stdout.on('data', (data) => (result += data.toString()));
p.stderr.on('data', (data) => (result += data.toString()));

View File

@ -65,8 +65,10 @@ window.addEventListener("message", (event) => {
params: event?.data?.data?.data?.params ?? [],
},
}
if(event?.data?.data?.data?.method !== 'eth_chainId') {
// console.info('data out', data)
}
window.postMessage(data, "*");
})
}

View File

@ -1,5 +1,5 @@
interface RequestArguments {
id?: string | undefined
id?: string
method: string;
params?: unknown[] | object;
}
@ -18,8 +18,6 @@ const ProviderInfo: EIP6963ProviderInfo = {
rdns: 'clear-wallet.flashsoft.eu/',
}
const THROTTLE_LEVEL = 20;
const THROTTLE_TIMEOUT = 500;
const MAX_PROMISES = 50
function loadEIP1193Provider(provider: any) {
@ -74,16 +72,18 @@ const getListnersCount = (): number => {
}
const sendMessage = (args: RequestArguments, ping = false, from = 'request'): Promise<unknown> => {
return new Promise(async (resolve, reject) => {
if(promResolvers.size < MAX_PROMISES && promResolvers.size > THROTTLE_LEVEL) {
await new Promise((res) => setTimeout(res, THROTTLE_TIMEOUT))
} else if(promResolvers.size > MAX_PROMISES) {
return new Promise((resolve, reject) => {
const p = [ "eth_signTypedData", "eth_signTypedData_v3", "eth_signTypedData_v4"]
const throttledMethods = [...p, 'eth_sign', 'personal_sign', 'eth_sendTransaction']
if(promResolvers.size > MAX_PROMISES && throttledMethods.includes(args.method)) {
reject({code: -32000, message: 'ClearWallet: Too many requests', error: true })
return
}
const resId = [...`${Math.random().toString(16) + Date.now().toString(16)}`].slice(2).join('')
promResolvers.set(resId, { resolve, reject })
const p = [ "eth_signTypedData", "eth_signTypedData_v3", "eth_signTypedData_v4"]
const method = args.method
if (p.includes(args.method)) {
args.method = undefined as any
@ -100,11 +100,13 @@ const sendMessage = (args: RequestArguments, ping = false, from = 'request'): Pr
if (ping) {
data.type = 'CLWALLET_PING'
}
if(method!== 'eth_chainId') {
// console.info('data in', data)
window.postMessage(data, "*");
}
window.postMessage(data, "*");
})
}
class MetaMaskAPI {
@ -187,30 +189,27 @@ class MetaMaskAPI {
}
if (arg2 === undefined) {
if( typeof arg1 === 'string' ) {
return resultFmt(sendMessage({
method: arg1,
params: undefined
}, false, 'send'))
} else {
return resultFmt(sendMessage(arg1 as RequestArguments, false, 'send'))
}
return resultFmt(sendMessage(arg1 as RequestArguments, false, 'send'))
} else if (typeof arg1 === 'object') {
if( typeof arg1 === 'string' ) {
return resultFmt(sendMessage(arg1 as RequestArguments, false, 'send'))
} else {
return resultFmt(sendMessage(arg1 as RequestArguments, false, 'send'))
return resultFmt(sendMessage({
method: arg1,
params: undefined
}, false, 'send'))
}
return resultFmt(sendMessage(arg1 as RequestArguments, false, 'send'))
}else if( typeof arg1 === 'string' ) {
return resultFmt( sendMessage({
method: arg1,
params: arg2 as object
}, false, 'send'))
}else if (typeof arg2 === 'function'){
return resultFmt( sendMessage(arg1 as RequestArguments, false, 'send'))
} else {
return resultFmt(sendMessage(arg1 as RequestArguments , false, 'send'))
}
return resultFmt(sendMessage(arg1 as RequestArguments, false, 'send'))
}
on (eventName: string, callback: () => void) {
this.addListener(eventName, callback)
@ -405,16 +404,16 @@ const web3Shim = {
__isMetaMaskShim__: true
}
const injectWallet = (win: any) => {
const injectWallet = () => {
const ethKey = 'ethereum'
if (win[ethKey]?.isClWallet) {
if ((window as any)[ethKey]?.isClWallet) {
return;
}
Object.defineProperty(win, ethKey, {
Object.defineProperty((window as any), ethKey, {
value: eth,
});
Object.defineProperty(win, 'web3', {
Object.defineProperty((window as any), 'web3', {
value: web3Shim
});
sendMessage({
@ -422,12 +421,52 @@ sendMessage({
}, true)
}
injectWallet(this);
injectWallet();
loadEIP1193Provider(eth)
// HELPERS TO CLONE METAMASK API
// const MMReflect = async () => {
// await new Promise((resolve) => setTimeout(resolve, 2000))
// const originalRequest = (window as any).ethereum.request
// const originalSend = (window as any).ethereum.send
// const originalSendAsync = (window as any).ethereum.sendAsync
// const methods = [originalRequest, originalSend, originalSendAsync]
// const originalMethods = ['request', 'send', 'sendAsync']
// for(const [index, method] of methods.entries()) {
// const methodName = originalMethods[index];
// (window as any).ethereum[methodName] = new Proxy(method, {
// apply(target, thisArg, argsList) {
// const isEthChainId = argsList[0]?.method === 'eth_chainId'
// const result = Reflect.apply(target, thisArg, argsList) as Promise<unknown>
// const resultCLW = Reflect.apply(sendMessage, thisArg, argsList) as Promise<unknown>
// if(!isEthChainId) {
// result?.then((res: any) => {
// resultCLW?.then((resCLW: any) => {
// console.log(`window.ethereum.${methodName} ${JSON.stringify(argsList, null, 2)} result:`, res, resCLW);
// })
// })
// }
// return result;
// }
// });
// }
// console.log('Reflecting Metamask API')
// }
// MMReflect()
// window.addEventListener("message" , (event) => {
// console.log('event', JSON.stringify(event?.data?.data, null, 2), JSON.stringify(event?.data, null, 2))
// })
@ -449,52 +488,52 @@ loadEIP1193Provider(eth)
// }, 5000)
// setTimeout(async () => {
// console.log('Metamask clone test');
// (<any>window).ethereum.request({method: 'eth_requestAccounts', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_requestAccounts')});
// (<any>window).ethereum2.request({method: 'eth_requestAccounts', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_requestAccounts')});
// console.log('Metamask clone test');
// // (<any>window).ethereum.request({method: 'eth_requestAccounts', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_requestAccounts')});
// // (<any>window).ethereum2.request({method: 'eth_requestAccounts', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_requestAccounts')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.request({method: 'eth_accounts', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_accounts')});
// (<any>window).ethereum2.request({method: 'eth_accounts', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_accounts')});
// // (<any>window).ethereum.request({method: 'eth_accounts', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_accounts')});
// // (<any>window).ethereum2.request({method: 'eth_accounts', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_accounts')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_chainId')});
// (<any>window).ethereum2.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_chainId')});
// (<any>window).ethereum.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_chainId')});
// (<any>window).ethereum2.request({method: 'eth_chainId', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_chainId')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.request({method: 'eth_blockNumber', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_chainId')});
// (<any>window).ethereum2.request({method: 'eth_blockNumber', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_chainId')});
// // (<any>window).ethereum.request({method: 'eth_blockNumber', params: Array(0)}).then((res: any) => { console.log(res, 'MT: eth_chainId')});
// // (<any>window).ethereum2.request({method: 'eth_blockNumber', params: Array(0)}).then((res: any) => { console.log(res, 'CW: eth_chainId')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, 'MT: wallet_requestPermissions')});
// (<any>window).ethereum2.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, 'CW: wallet_requestPermissions')});
// // (<any>window).ethereum.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, 'MT: wallet_requestPermissions')});
// // (<any>window).ethereum2.request({method: 'wallet_requestPermissions', params: [{eth_accounts: {}}]}).then((res: any) => { console.log(res, 'CW: wallet_requestPermissions')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, 'MT: net_version')});
// (<any>window).ethereum2.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, 'CW: net_version')});
// // (<any>window).ethereum.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, 'MT: net_version')});
// // (<any>window).ethereum2.request({method: 'net_version', params: []}).then((res: any) => { console.log(res, 'CW: net_version')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.request({method: 'wallet_switchEthereumChain', params: [{chainId: "0x89"}]}).then((res: any) => { console.log(res, 'MT: wallet_switchEthereumChain')});
// (<any>window).ethereum2.request({method: 'wallet_switchEthereumChain', params: [{chainId: "0x89"}]}).then((res: any) => { console.log(res, 'CW: wallet_switchEthereumChain')});
// // (<any>window).ethereum.request({method: 'wallet_switchEthereumChain', params: [{chainId: "0x89"}]}).then((res: any) => { console.log(res, 'MT: wallet_switchEthereumChain')});
// // (<any>window).ethereum2.request({method: 'wallet_switchEthereumChain', params: [{chainId: "0x89"}]}).then((res: any) => { console.log(res, 'CW: wallet_switchEthereumChain')});
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum.on('connect', ((a: any, b: any) => console.log('connect MT', a, b)));
// (<any>window).ethereum.on('accountsChanged', ((a: any, b: any) => console.log('accountsChanged MT', a, b)));
// (<any>window).ethereum.on('chainChanged', ((a: any) => console.log('chainChanged MT', a, typeof a)));
// // (<any>window).ethereum.on('connect', ((a: any, b: any) => console.log('connect MT', a, b)));
// // (<any>window).ethereum.on('accountsChanged', ((a: any, b: any) => console.log('accountsChanged MT', a, b)));
// // (<any>window).ethereum.on('chainChanged', ((a: any) => console.log('chainChanged MT', a, typeof a)));
// await new Promise((resolve) => setTimeout(resolve, 1000));
// // await new Promise((resolve) => setTimeout(resolve, 1000));
// (<any>window).ethereum2.on('connect', ((a: any, b: any) => console.log('connect CW', a, b)));
// (<any>window).ethereum2.on('accountsChanged', ((a: any, b: any) => console.log('accountsChanged CW', a, b)));
// (<any>window).ethereum2.on('chainChanged', ((a: any) => console.log('chainChanged CW', a, typeof a)));
// // (<any>window).ethereum2.on('connect', ((a: any, b: any) => console.log('connect CW', a, b)));
// // (<any>window).ethereum2.on('accountsChanged', ((a: any, b: any) => console.log('accountsChanged CW', a, b)));
// // (<any>window).ethereum2.on('chainChanged', ((a: any) => console.log('chainChanged CW', a, typeof a)));
// }, 3500)

View File

@ -3,8 +3,8 @@
"name": "__MSG_appName__",
"description": "__MSG_appDesc__",
"default_locale": "en",
"version": "1.3.8",
"version_name": "1.3.8",
"version": "1.3.9",
"version_name": "1.3.9",
"icons": {
"16": "assets/extension-icon/wallet_16.png",
"32": "assets/extension-icon/wallet_32.png",

View File

@ -44,6 +44,8 @@ import { allTemplateNets } from '@/utils/networks'
let notificationUrl: string
const chainIdThrottle: {[key: string]: number} = {}
chrome.runtime.onInstalled.addListener(() => {
enableRightClickVote()
console.info('Service worker installed');
@ -149,6 +151,30 @@ if (!chrome.notifications.onButtonClicked.hasListener(viewTxListner)){
chrome.notifications.onButtonClicked.addListener(viewTxListner)
}
const chainIdThrottleFn = async (website: string) => {
let urlKey
try {
const url = new URL(website)
urlKey = url.hostname
} catch {
urlKey = 'invalid'
}
if(chainIdThrottle[urlKey] === undefined) {
chainIdThrottle[urlKey] = 0
}
chainIdThrottle[urlKey] += 1
if( chainIdThrottle[urlKey] > 3) {
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(null)
}, 450)
})
// console.log('throttling', chainIdThrottle)
}
return urlKey
}
const mainListner = (message: RequestArguments, sender:any, sendResponse: (a: any) => any) => {
if (chrome.runtime.lastError) {
console.info("Error receiving message:", chrome.runtime.lastError);
@ -158,6 +184,8 @@ const mainListner = (message: RequestArguments, sender:any, sendResponse: (a: an
}
(async () => {
// console.info('Message:', message)
if (!(message?.method)) {
sendResponse({
code: 500,
@ -354,11 +382,16 @@ const mainListner = (message: RequestArguments, sender:any, sendResponse: (a: an
}
break
}
case 'eth_chainId': {
case 'eth_chainId':
case 'net_version':
{
try {
const isNetVersion = message.method === 'net_version'
const urlKey = await chainIdThrottleFn(message?.website ?? '')
const network = await getSelectedNetwork()
const chainId = network?.chainId ?? 0
sendResponse(`0x${chainId.toString(16)}`)
const chainId = network?.chainId ?? 1
sendResponse(isNetVersion ? chainId.toString() : `0x${chainId.toString(16)}`)
chainIdThrottle[urlKey] -= 1
} catch (e) {
sendResponse({
error: true,
@ -711,7 +744,7 @@ const mainListner = (message: RequestArguments, sender:any, sendResponse: (a: an
try {
chrome.windows.remove(sender.tab?.windowId ?? 0)
}catch (e) {
console.log(e)
console.info(e)
// ignore
}
break

View File

@ -48,7 +48,6 @@ export const saveNetwork = async (network: Network): Promise<void> => {
export const getSelectedNetwork = async (): Promise<Network > => {
console.info('network', (await (storageGet('selectedNetwork')))?.selectedNetwork)
return (await storageGet('selectedNetwork'))?.selectedNetwork ?? null as unknown as Network
}

View File

@ -1,6 +1,21 @@
import { getSelectedAccount, getSelectedNetwork, numToHexStr } from '@/utils/platform';
import { ethers } from "ethers"
let provider: ethers.JsonRpcProvider | null = null
export const getCurrentProvider = async () => {
const network = await getSelectedNetwork()
if (provider) {
// check if the network has changed
if (provider._getConnection().url !== network.rpc) {
provider = new ethers.JsonRpcProvider(network.rpc, ethers.Network.from(network.chainId), { staticNetwork: true, batchMaxCount: 6, polling: false })
}
return {provider, network}
}
provider = new ethers.JsonRpcProvider(network.rpc, ethers.Network.from(network.chainId), { staticNetwork: true, batchMaxCount: 6, polling: false })
return {provider, network}
}
const convertReceipt = (receipt: ethers.TransactionReceipt | null) => {
if(!receipt) return null
const newReceipt = {...receipt} as any
@ -49,34 +64,29 @@ export const signTypedData = async (msg: string) => {
export const getBalance = async () =>{
const account = await getSelectedAccount()
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
return await provider.getBalance(account.address)
}
export const getGasPrice = async () => {
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
const feed = await provider.getFeeData()
const gasPrice = feed.maxFeePerGas ?? feed.gasPrice ?? 0n
return Number(gasPrice) / 1e9
}
export const getBlockNumber = async () => {
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
return await provider.getBlockNumber()
}
export const getBlockByNumber = async (blockNum: number) => {
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
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.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
return await provider.estimateGas({to, from, data, value})
}
@ -94,23 +104,20 @@ export const evmCall = async (params: any[]) => {
tx.blockTag = 'latest'
}
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
const result = await provider.call(tx)
return result
}
export const getTxByHash = async (hash: string) => {
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
return await provider.getTransaction(hash)
}
export const getTxReceipt = async (hash: string) => {
try {
if (!hash) return null
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
const receipt = await provider.getTransactionReceipt(hash)
return convertReceipt(receipt)
@ -121,8 +128,7 @@ export const getTxReceipt = async (hash: string) => {
}
export const getCode = async (addr: string) => {
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
return await provider.getCode(addr)
}
@ -134,8 +140,7 @@ export const getFromMnemonic = (mnemonic: string, index: number) => {
}
export const getTxCount = async (addr: string, block: null | string = null) => {
const network = await getSelectedNetwork()
const provider = new ethers.JsonRpcProvider(network.rpc)
const { provider } = await getCurrentProvider()
if(block){
return await provider.getTransactionCount(addr, block)
} else {
@ -147,16 +152,11 @@ export const getRandomPk = () => {
return ethers.Wallet.createRandom().privateKey
}
export const getCurrentProvider = async () => {
const network = await getSelectedNetwork()
return new ethers.JsonRpcProvider(network.rpc)
}
export const sendTransaction = async ({ data= '', gas='0x0', to='', from='', value='', gasPrice='0x0'}:
{to: string, from: string, data: string, value: string, gas: string, gasPrice: string}) => {
const account = await getSelectedAccount()
const network = await getSelectedNetwork()
const wallet = new ethers.Wallet(account.pk, new ethers.JsonRpcProvider(network.rpc))
const { provider } = await getCurrentProvider()
const wallet = new ethers.Wallet(account.pk, provider)
const gasPriceInt = BigInt(gasPrice)
const gasInt = BigInt(gas)

View File

@ -76,7 +76,7 @@
</ion-item>
<ion-item>
<ion-textarea
style="overflow-y: scroll"
style="overflow-y: scroll; width: 100%"
aria-label="Enter mnemonic"
:rows="10"
:cols="10"
@ -263,7 +263,7 @@ export default defineComponent({
if (settings.enableStorageEnctyption) {
const pass = await openModal();
if (!pass) {
alertMsg.value = "Cannot add account with encryption password.";
alertMsg.value = "Cannot add account without encryption password.";
alertOpen.value = true;
return;
}
@ -278,7 +278,8 @@ export default defineComponent({
} else {
if (accounts.find((account) => account.address === wallet.address)) {
alertMsg.value = "Account already exists.";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
}
const p2 = saveAccount({
@ -299,7 +300,8 @@ export default defineComponent({
} else {
if (accounts.find((account) => account.address === wallet.address)) {
alertMsg.value = "Account already exists.";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
}
const p2 = saveAccount({

View File

@ -229,22 +229,26 @@ export default defineComponent({
const onAddNetwork = async () => {
if (Number(chainId.value) < 1) {
alertMsg.value = "Chain Id must be a valid decimal integer";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (name.value.length < 2) {
alertMsg.value = "Name must have at least 2 characters";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (name.value.length > 99) {
alertMsg.value = "Name must be less than 100 characters";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (name.value.length > 99) {
try {
new URL(rpc.value);
} catch {
alertMsg.value = "RPC must be a valid URL";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
}
let p1 = Promise.resolve();
@ -270,7 +274,8 @@ export default defineComponent({
} else {
if (chainId.value in networks && !isEdit) {
alertMsg.value = "Network already exists.";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
}
networks[chainId.value] = network;

View File

@ -35,10 +35,14 @@
conectivity issues.
</template>
<template v-else-if="noAssets">
<p class="padding: 1rem;">
<!-- <p class="padding: 1rem;">
No know assets found for this wallet address.
</p></template
>
</p> -->
<p class="padding: 1rem;">
Assets view temporarily disabled until finding better provider. As old
provider(yup.io) is no longer available.
</p>
</template>
<template v-else>
<template v-if="ethTokens.length || polyTokens.length">
<template v-if="ethTokens.length">

View File

@ -367,12 +367,13 @@ export default defineComponent({
const findIndex = accounts.value.findIndex((a) => a.address == address);
if (findIndex > -1) {
selectedAccount.value = accounts.value[findIndex];
await saveSelectedAccount(selectedAccount.value);
// console.log(({ [address]: accounts.value[address], ...accounts.value}))
accounts.value.splice(findIndex, 1);
accounts.value.splice(0, 0, selectedAccount.value);
accounts.value = accounts.value.filter((a) => a.address !== address);
accounts.value.unshift(selectedAccount.value);
const newAccounts = [...accounts.value];
await replaceAccounts(newAccounts);
await Promise.all([
saveSelectedAccount(selectedAccount.value),
replaceAccounts(newAccounts),
]);
triggerListner("accountsChanged", [newAccounts.map((a) => a.address)?.[0]]);
}
accountsModal.value = false;

View File

@ -121,6 +121,7 @@
></ion-alert>
<iframe
title="eval-sandbox"
@load="sandboxLoaded = true"
ref="evalFrame"
src="eval-sandbox.html"
@ -285,7 +286,8 @@ export default defineComponent({
if (!content) {
alertMsg.value =
"Abi not found in storage, be sure Abi with name " + data.abi + " exists.";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
abiContent.value = content;
@ -304,15 +306,18 @@ export default defineComponent({
const saveActionInStorage = () => {
if (!functionName.value) {
alertMsg.value = "Function Name is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!contractAddress.value) {
alertMsg.value = "Contract Address is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (abiContent.value === "") {
alertMsg.value = "Abi is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
saveActionModal.value = true;
};
@ -320,22 +325,26 @@ export default defineComponent({
const executeAction = async () => {
if (sandboxLoaded.value === false) {
alertMsg.value = "Sandbox for eval not loaded yet, please wait";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!contractAddress.value) {
alertMsg.value = "Contract Address is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!functionName.value) {
alertMsg.value = "Function Name is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!parsedAbi) {
alertMsg.value = "Abi is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
alertHeader.value = "Error";
@ -350,7 +359,8 @@ export default defineComponent({
);
} catch {
alertMsg.value = "Error parsing params, check params types";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
try {
@ -362,14 +372,16 @@ export default defineComponent({
.map((param) => param.trim());
if (paramsTypes.length !== evalParams.length) {
alertMsg.value = "Params count mismatch";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
encodeParamsTypes.push(...paramsTypes);
}
} catch {
alertMsg.value =
"Function Siganture wrong format (ex: 'functionName(uint256,string)')";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
const fnName = functionName.value.includes("(")
@ -384,17 +396,20 @@ export default defineComponent({
alertMsg.value = "Value from contract fetched check result area!";
alertHeader.value = "OK";
return (alertOpen.value = true);
alertOpen.value = true;
return;
} catch (e) {
alertMsg.value = "Function call failed, check params, contract address and ABI";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
};
const saveAction = async () => {
if (!name.value) {
alertMsg.value = "Name is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
const action = {
name: name.value,
@ -408,7 +423,8 @@ export default defineComponent({
saveActionModal.value = false;
alertMsg.value = "Action saved successfully";
alertHeader.value = "OK";
return (alertOpen.value = true);
alertOpen.value = true;
return;
};
const messageHandler = (event: any) => {

View File

@ -53,11 +53,14 @@ import {
modalController,
onIonViewWillEnter,
} from "@ionic/vue";
// import { ethers } from "ethers";
import { hexTostr } from "@/utils/platform";
import { approve, walletPing } from "@/extension/userRequest";
import { useRoute } from "vue-router";
import { getSelectedAccount, unBlockLockout, blockLockout } from "@/utils/platform";
import {
getSelectedAccount,
unBlockLockout,
blockLockout,
hexTostr,
} from "@/utils/platform";
import UnlockModal from "@/views/UnlockModal.vue";
export default defineComponent({

View File

@ -113,6 +113,7 @@
/>
<iframe
title="eval-sandbox"
@load="sandboxLoaded = true"
ref="evalFrame"
src="eval-sandbox.html"
@ -279,7 +280,8 @@ export default defineComponent({
if (!content) {
alertMsg.value =
"Abi not found in storage, be sure Abi with name " + data.abi + " exists.";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
abiContent.value = content;
@ -297,15 +299,18 @@ export default defineComponent({
const saveActionInStorage = () => {
if (!functionName.value) {
alertMsg.value = "Function Name is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!contractAddress.value) {
alertMsg.value = "Contract Address is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (abiContent.value === "") {
alertMsg.value = "Abi is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
saveActionModal.value = true;
};
@ -313,22 +318,26 @@ export default defineComponent({
const executeAction = async () => {
if (sandboxLoaded.value === false) {
alertMsg.value = "Sandbox for eval not loaded yet, please wait";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!contractAddress.value) {
alertMsg.value = "Contract Address is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!functionName.value) {
alertMsg.value = "Function Name is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
if (!parsedAbi) {
alertMsg.value = "Abi is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
alertHeader.value = "Error";
@ -348,14 +357,16 @@ export default defineComponent({
.map((param) => param.trim());
if (paramsTypes.length !== evalParams.length) {
alertMsg.value = "Params count mismatch";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
encodeParamsTypes.push(...paramsTypes);
}
} catch {
alertMsg.value =
"Function Siganture wrong format (ex: 'functionName(uint256,string)')";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
const fnName = functionName.value.includes("(")
@ -396,7 +407,8 @@ export default defineComponent({
alertMsg.value = "Function call failed, check params, contract address and ABI";
loadingSend.value = false;
loading.value = false;
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
loadingSend.value = false;
loading.value = false;
@ -405,7 +417,8 @@ export default defineComponent({
const saveAction = async () => {
if (!name.value) {
alertMsg.value = "Name is required";
return (alertOpen.value = true);
alertOpen.value = true;
return;
}
const action = {
name: name.value,
@ -419,7 +432,7 @@ export default defineComponent({
saveActionModal.value = false;
alertMsg.value = "Action saved successfully";
alertHeader.value = "OK";
return (alertOpen.value = true);
alertOpen.value = true;
};
const messageHandler = (event: any) => {

1188
yarn.lock

File diff suppressed because it is too large Load Diff