mirror of
https://github.com/andrei0x309/clear-wallet.git
synced 2024-12-19 00:00:45 +00:00
dev: 1.0.2
This commit is contained in:
parent
610fdc6afb
commit
1a4b531ae2
1
.gitignore
vendored
1
.gitignore
vendored
@ -30,3 +30,4 @@ npm-debug.log*
|
||||
/plugins
|
||||
/www
|
||||
/src/extension/inject.js
|
||||
readme.md
|
@ -12,6 +12,7 @@ const allowedMethods = {
|
||||
'eth_sign': true,
|
||||
'net_version': true,
|
||||
'eth_sendTransaction': true,
|
||||
'wallet_switchEthereumChain': true
|
||||
}
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
|
@ -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, "*");
|
||||
})
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -50,4 +50,5 @@ export interface Settings {
|
||||
lockOutEnabled: boolean
|
||||
theme: 'system' | 'light' | 'dark'
|
||||
lastLock: number
|
||||
lockOutBlocked: boolean
|
||||
}
|
@ -19,6 +19,10 @@ const routes: Array<RouteRecordRaw> = [
|
||||
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,
|
||||
|
@ -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'
|
||||
},
|
||||
}
|
||||
|
@ -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<void> =>{
|
||||
@ -87,6 +87,20 @@ export const setSettings = async (settings: Settings): Promise<void> => {
|
||||
await storageSave('settings', settings )
|
||||
}
|
||||
|
||||
export const blockLockout = async (): Promise<Settings> => {
|
||||
const settings = await getSettings()
|
||||
settings.lockOutBlocked = true
|
||||
await setSettings(settings)
|
||||
return settings
|
||||
}
|
||||
|
||||
export const unBlockLockout = async (): Promise<Settings> => {
|
||||
const settings = await getSettings()
|
||||
settings.lockOutBlocked = false
|
||||
await setSettings(settings)
|
||||
return settings
|
||||
}
|
||||
|
||||
export const getBalanceCache = async (): Promise<string> => {
|
||||
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<boolean>) => {
|
||||
export const copyAddress = async (address: string, toastRef: Ref<boolean>) => {
|
||||
await navigator.clipboard.writeText(address)
|
||||
toastRef.value = true
|
||||
}
|
||||
}
|
||||
|
||||
export const getUrl = (url: string) => chrome.runtime.getURL(url)
|
||||
|
||||
|
@ -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)
|
||||
);
|
||||
|
@ -28,7 +28,7 @@
|
||||
<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-input id="pasteExplorer" placeholder="https://polygonscan.com" v-model="explorer" ></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-button @click="onCancel">Cancel</ion-button>
|
||||
|
113
src/views/ContractError.vue
Normal file
113
src/views/ContractError.vue
Normal file
@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Contract Error</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
<ion-item
|
||||
><ion-label>Network Name: {{ selectedNetwork?.name }}</ion-label></ion-item
|
||||
>
|
||||
<ion-item>
|
||||
<ion-avatar
|
||||
v-if="(mainNets as any)[selectedNetwork?.chainId]?.icon"
|
||||
style="margin-right: 1rem; width: 1.8rem; height: 1.8rem"
|
||||
>
|
||||
<img
|
||||
:alt="selectedNetwork?.name"
|
||||
:src="getUrl('assets/chain-icons/' + (mainNets as any)[selectedNetwork?.chainId]?.icon)"
|
||||
/>
|
||||
</ion-avatar>
|
||||
<ion-label>Network ID: {{ selectedNetwork?.chainId }}</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Transaction was aboreted before being sent</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Gas Estimation Error due to Contract Error</ion-label>
|
||||
</ion-item>
|
||||
<ion-item> Contract: {{ contract }} </ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Error From Contract:</ion-label>
|
||||
<ion-textarea style="overflow-y: scroll;" :rows="10" :cols="20" :value="error" readonly></ion-textarea>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-button @click="onCancel">Exit</ion-button>
|
||||
</ion-item>
|
||||
|
||||
<ion-loading
|
||||
:is-open="loading"
|
||||
cssClass="my-custom-class"
|
||||
message="Please wait..."
|
||||
:duration="4000"
|
||||
@didDismiss="loading = false"
|
||||
>
|
||||
</ion-loading>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, Ref } from "vue";
|
||||
import {
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonButton,
|
||||
IonTextarea,
|
||||
onIonViewWillEnter,
|
||||
IonLoading,
|
||||
} from "@ionic/vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { getSelectedNetwork, getUrl, hexTostr, } from "@/utils/platform";
|
||||
import type { Network } from "@/extension/types";
|
||||
import { mainNets } from "@/utils/networks";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonPage,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonButton,
|
||||
IonTextarea,
|
||||
IonLoading,
|
||||
},
|
||||
setup: () => {
|
||||
const route = useRoute();
|
||||
const error = hexTostr((route.params?.param as string) ?? "");
|
||||
const loading = ref(true);
|
||||
const contract = (route.params?.contract as string) ?? ""
|
||||
const selectedNetwork = (ref(null) as unknown) as Ref<Network>;
|
||||
|
||||
const onCancel = () => {
|
||||
window.close();
|
||||
};
|
||||
|
||||
onIonViewWillEnter(async () => {
|
||||
(window as any)?.resizeTo?.(700, 600)
|
||||
selectedNetwork.value = await getSelectedNetwork()
|
||||
loading.value = false
|
||||
});
|
||||
|
||||
return {
|
||||
onCancel,
|
||||
contract,
|
||||
loading,
|
||||
selectedNetwork,
|
||||
mainNets,
|
||||
getUrl,
|
||||
error
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
@ -16,7 +16,7 @@
|
||||
<ion-content class="ion-padding">
|
||||
<ion-list v-for="network of networks" :key="network.chainId">
|
||||
<ion-item>
|
||||
<ion-avatar v-if="(mainNets as any)[network.chainId].icon" style="margin-right: 1rem; width: 1.8rem; height:1.8rem;">
|
||||
<ion-avatar v-if="(mainNets as any)[network.chainId]?.icon" style="margin-right: 1rem; width: 1.8rem; height:1.8rem;">
|
||||
<img :alt="network.name" :src="getUrl('assets/chain-icons/' + (mainNets as any)[network.chainId].icon)" />
|
||||
</ion-avatar>
|
||||
<ion-label>
|
||||
@ -27,8 +27,8 @@
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<router-link :to="`/add-network/edit/${network.chainId}`" ><ion-chip>Edit</ion-chip></router-link>
|
||||
<ion-chip @click="deleteNetwork">Delete</ion-chip>
|
||||
<ion-chip @click="editNetwork(network.chainId)" button>Edit</ion-chip>
|
||||
<ion-chip @click="deleteNetwork(network.chainId)" button>Delete</ion-chip>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -94,11 +94,12 @@
|
||||
<div class="ion-padding" slot="content">
|
||||
<ion-item>
|
||||
<ion-label>Import Additional Accounts</ion-label>
|
||||
<ion-button color="danger" @click="importAcc">Import</ion-button>
|
||||
<input ref="importFile" type="file" accept=".json" />
|
||||
<ion-button color="warning" @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-button color="warning" @click="exportAcc">Export</ion-button>
|
||||
</ion-item>
|
||||
</div>
|
||||
</ion-accordion>
|
||||
@ -181,7 +182,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, reactive } from "vue";
|
||||
import { defineComponent, ref, reactive, Ref } from "vue";
|
||||
import { storageWipe, getSettings, setSettings, getAccounts, saveSelectedAccount, replaceAccounts } from "@/utils/platform";
|
||||
import { decrypt, encrypt } from "@/utils/webCrypto"
|
||||
// import { Account } from '@/extension/type'
|
||||
@ -243,6 +244,7 @@ export default defineComponent({
|
||||
const alertMsg = ref('');
|
||||
const toastState = ref(false);
|
||||
const toastMsg = ref('');
|
||||
const importFile = ref(null) as unknown as Ref<HTMLInputElement>
|
||||
|
||||
const wipeStorage = async () => {
|
||||
loading.value = true;
|
||||
@ -333,9 +335,45 @@ export default defineComponent({
|
||||
// settings.s.enableStorageEnctyption = true;
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const validateFile = () => {
|
||||
return new Promise((resolve) => {
|
||||
try {
|
||||
if (!importFile.value?.value?.length) {
|
||||
return resolve({
|
||||
error: 'Import json file is missing'
|
||||
})
|
||||
}
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event) => {
|
||||
const json = JSON.parse(event?.target?.result as string)
|
||||
if(!json.length){
|
||||
return resolve({ error: 'JSON format is wrong. Corrrect JSON format is: [{ "name": "Account Name", "pk": "Private Key" },{...}]' })
|
||||
}
|
||||
const test = json.some((e:any) => ( !('pk' in e ) || !('name' in e) || !(e.pk.length !== 66 && e.pk.length !== 64)))
|
||||
if(test) {
|
||||
return resolve({ error: 'JSON format is wrong. Corrrect JSON format is: [{ "name": "Account Name", "pk": "Private Key" },{...}], Also PK must be valid' })
|
||||
}
|
||||
return resolve({ error: false })
|
||||
}
|
||||
reader.readAsText(importFile.value?.files?.[0] as File);
|
||||
|
||||
}catch {
|
||||
return resolve(
|
||||
{
|
||||
error: 'Parsing JSON file'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const importAcc = async () => {
|
||||
//
|
||||
const validation = await validateFile() as { error: any }
|
||||
if (validation.error) {
|
||||
alertMsg.value = validation.error
|
||||
alertOpen.value = true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const exportAcc = async () => {
|
||||
@ -389,7 +427,8 @@ export default defineComponent({
|
||||
toastState,
|
||||
toastMsg,
|
||||
importAcc,
|
||||
exportAcc
|
||||
exportAcc,
|
||||
importFile
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -51,16 +51,14 @@ import {
|
||||
IonText,
|
||||
IonLoading,
|
||||
modalController,
|
||||
onIonViewWillEnter
|
||||
onIonViewWillEnter,
|
||||
} from "@ionic/vue";
|
||||
// import { ethers } from "ethers";
|
||||
import {
|
||||
hexTostr,
|
||||
} from "@/utils/platform";
|
||||
import { hexTostr } from "@/utils/platform";
|
||||
import { approve, walletPing } from "@/extension/userRequest";
|
||||
import { useRoute } from 'vue-router';
|
||||
import { getSelectedAccount } from '@/utils/platform'
|
||||
import UnlockModal from '@/views/UnlockModal.vue'
|
||||
import { useRoute } from "vue-router";
|
||||
import { getSelectedAccount, unBlockLockout, blockLockout } from "@/utils/platform";
|
||||
import UnlockModal from "@/views/UnlockModal.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -74,23 +72,24 @@ export default defineComponent({
|
||||
IonButton,
|
||||
IonAlert,
|
||||
IonText,
|
||||
IonLoading
|
||||
IonLoading,
|
||||
},
|
||||
setup: () => {
|
||||
const route = useRoute()
|
||||
const loading = ref(false)
|
||||
const rid = route?.params?.rid as string ?? '';
|
||||
const signMsg = ref(hexTostr(route?.params?.param as string ?? ''));
|
||||
const route = useRoute();
|
||||
const loading = ref(false);
|
||||
const rid = (route?.params?.rid as string) ?? "";
|
||||
const signMsg = ref(hexTostr((route?.params?.param as string) ?? ""));
|
||||
const alertOpen = ref(false);
|
||||
const alertMsg = ref("");
|
||||
const timerReject = ref(140);
|
||||
let interval: any
|
||||
let interval: any;
|
||||
|
||||
const onCancel = () => {
|
||||
window.close();
|
||||
if(interval) {
|
||||
if (interval) {
|
||||
try {
|
||||
clearInterval(interval)
|
||||
unBlockLockout();
|
||||
clearInterval(interval);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
@ -98,48 +97,48 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
onIonViewWillEnter(async () => {
|
||||
blockLockout();
|
||||
interval = setInterval(async () => {
|
||||
if(timerReject.value <= 0) {
|
||||
onCancel()
|
||||
if (timerReject.value <= 0) {
|
||||
onCancel();
|
||||
return;
|
||||
}
|
||||
|
||||
timerReject.value -= 1
|
||||
walletPing()
|
||||
}, 1000) as any
|
||||
|
||||
timerReject.value -= 1;
|
||||
walletPing();
|
||||
}, 1000) as any;
|
||||
});
|
||||
|
||||
const openModal = async () => {
|
||||
const modal = await modalController.create({
|
||||
component: UnlockModal,
|
||||
componentProps: {
|
||||
unlockType: 'message'
|
||||
}
|
||||
|
||||
});
|
||||
modal.present();
|
||||
const { role } = await modal.onWillDismiss();
|
||||
if(role === 'confirm') return true
|
||||
return false
|
||||
|
||||
}
|
||||
const modal = await modalController.create({
|
||||
component: UnlockModal,
|
||||
componentProps: {
|
||||
unlockType: "message",
|
||||
},
|
||||
});
|
||||
modal.present();
|
||||
const { role } = await modal.onWillDismiss();
|
||||
if (role === "confirm") return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
const onSign = async () => {
|
||||
loading.value = true;
|
||||
const selectedAccount = await getSelectedAccount()
|
||||
if ((selectedAccount.pk ?? '').length !== 66) {
|
||||
const modalResult = await openModal()
|
||||
if(modalResult) {
|
||||
approve(rid)
|
||||
}else {
|
||||
onCancel()
|
||||
}
|
||||
}else {
|
||||
approve(rid)
|
||||
loading.value = true;
|
||||
const selectedAccount = await getSelectedAccount();
|
||||
if ((selectedAccount.pk ?? "").length !== 66) {
|
||||
const modalResult = await openModal();
|
||||
if (modalResult) {
|
||||
unBlockLockout();
|
||||
approve(rid);
|
||||
} else {
|
||||
onCancel();
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
} else {
|
||||
unBlockLockout();
|
||||
approve(rid);
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
return {
|
||||
signMsg,
|
||||
@ -148,7 +147,7 @@ export default defineComponent({
|
||||
alertMsg,
|
||||
onSign,
|
||||
loading,
|
||||
timerReject
|
||||
timerReject,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@ -46,7 +46,7 @@
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>Raw TX:</ion-label>
|
||||
<ion-textarea :rows="10" :cols="20" :value="signTxData" readonly></ion-textarea>
|
||||
<ion-textarea style="overflow-y: scroll;" :rows="10" :cols="20" :value="signTxData" readonly></ion-textarea>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-button @click="onCancel">Cancel</ion-button>
|
||||
@ -151,15 +151,18 @@ import {
|
||||
IonLoading,
|
||||
IonModal,
|
||||
IonButtons,
|
||||
IonInput
|
||||
IonInput,
|
||||
modalController
|
||||
} from "@ionic/vue";
|
||||
import { ethers } from "ethers";
|
||||
import { approve, walletPing, walletSendData } from "@/extension/userRequest";
|
||||
import { useRoute } from "vue-router";
|
||||
import { getSelectedNetwork, getUrl, getPrices, numToHexStr } from '@/utils/platform'
|
||||
import { getSelectedNetwork, getUrl, getPrices, numToHexStr, blockLockout, unBlockLockout, getSelectedAccount, strToHex} from '@/utils/platform'
|
||||
import { getBalance, getGasPrice, estimateGas } from '@/utils/wallet'
|
||||
import type { Network } from '@/extension/types'
|
||||
import { mainNets } from "@/utils/networks";
|
||||
import UnlockModal from '@/views/UnlockModal.vue'
|
||||
import router from "@/router";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -220,14 +223,43 @@ export default defineComponent({
|
||||
signTxData.value = JSON.stringify( params, null, 2)
|
||||
}
|
||||
|
||||
const onSign = () => {
|
||||
approve(rid);
|
||||
};
|
||||
const openModal = async () => {
|
||||
const modal = await modalController.create({
|
||||
component: UnlockModal,
|
||||
componentProps: {
|
||||
unlockType: 'message'
|
||||
}
|
||||
|
||||
});
|
||||
modal.present();
|
||||
const { role } = await modal.onWillDismiss();
|
||||
if(role === 'confirm') return true
|
||||
return false
|
||||
}
|
||||
|
||||
const onSign = async () => {
|
||||
loading.value = true;
|
||||
const selectedAccount = await getSelectedAccount()
|
||||
if ((selectedAccount.pk ?? '').length !== 66) {
|
||||
const modalResult = await openModal()
|
||||
if(modalResult) {
|
||||
unBlockLockout()
|
||||
approve(rid)
|
||||
}else {
|
||||
onCancel()
|
||||
}
|
||||
}else {
|
||||
unBlockLockout()
|
||||
approve(rid)
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const onCancel = () => {
|
||||
window.close();
|
||||
if(interval) {
|
||||
try {
|
||||
unBlockLockout()
|
||||
clearInterval(interval)
|
||||
} catch {
|
||||
// ignore
|
||||
@ -250,6 +282,7 @@ export default defineComponent({
|
||||
data: params?.data ?? '',
|
||||
value: params?.value ?? '0x0'
|
||||
})
|
||||
blockLockout()
|
||||
const pGasPrice = getGasPrice()
|
||||
const pBalance = getBalance()
|
||||
const pGetPrices = getPrices()
|
||||
@ -257,19 +290,26 @@ export default defineComponent({
|
||||
userBalance.value = Number(ethers.utils.formatEther((await pBalance).toString()))
|
||||
|
||||
gasPrice.value = parseInt(ethers.utils.formatUnits((await pGasPrice).toString(), "gwei"), 10)
|
||||
try {
|
||||
gasLimit.value = parseInt((await pEstimateGas).toString(), 10)
|
||||
} catch (err) {
|
||||
const errorToHex = strToHex(String(err))
|
||||
router.push(`/contract-error/${rid}/${errorToHex}/${contract}`)
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
inGasPrice.value = gasPrice.value
|
||||
inGasLimit.value = gasLimit.value
|
||||
|
||||
console.log( 'test', ethers.utils.formatUnits((await pGasPrice).toString(), "gwei"), ethers.utils.formatUnits(ethers.utils.parseUnits(gasPrice.value.toString(), "gwei"), "gwei") )
|
||||
// console.log( 'test', ethers.utils.formatUnits((await pGasPrice).toString(), "gwei"), ethers.utils.formatUnits(ethers.utils.parseUnits(gasPrice.value.toString(), "gwei"), "gwei") )
|
||||
|
||||
newGasData()
|
||||
if(userBalance.value < totalCost.value){
|
||||
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
|
||||
|
@ -27,7 +27,7 @@ export default defineConfig({
|
||||
rollupOptions: {
|
||||
plugins: [nodePolyfills()]
|
||||
},
|
||||
sourcemap: false,
|
||||
sourcemap: true,
|
||||
chunkSizeWarningLimit: 1000,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true
|
||||
|
Loading…
Reference in New Issue
Block a user