migrate: to new version WIP

This commit is contained in:
Andrei O 2023-08-14 11:10:52 +03:00
parent 2638ea94f4
commit b52ddd02f0
No known key found for this signature in database
GPG Key ID: B961E5B68389457E
14 changed files with 1354 additions and 1621 deletions

View File

@ -14,44 +14,44 @@
"pub": "yarn build && yarn release && ts-node ./release-scripts/create-release.ts"
},
"dependencies": {
"@capacitor/app": "^4.1.1",
"@capacitor/core": "^4.7.1",
"@capacitor/haptics": "^4.1.0",
"@capacitor/keyboard": "^4.1.1",
"@capacitor/status-bar": "^4.1.1",
"@ionic/vue": "^7.0.0",
"@ionic/vue-router": "^7.0.0",
"@types/chrome": "^0.0.227",
"core-js": "^3.29.1",
"ethers": "^5.7.2",
"vue": "^3.2.47",
"vue-router": "^4.1.6"
"@capacitor/app": "^5.0.6",
"@capacitor/core": "^5.2.3",
"@capacitor/haptics": "^5.0.6",
"@capacitor/keyboard": "^5.0.6",
"@capacitor/status-bar": "^5.0.6",
"@ionic/vue": "^7.2.3",
"@ionic/vue-router": "^7.2.3",
"@types/chrome": "^0.0.243",
"core-js": "^3.32.0",
"ethers": "^6.7.0",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@capacitor/cli": "^4.7.1",
"@capacitor/cli": "^5.2.3",
"@crxjs/vite-plugin": "^1.0.14",
"@types/archiver": "^5.3.2",
"@types/jest": "^29.5.0",
"@types/node": "^18.15.11",
"@typescript-eslint/eslint-plugin": "^5.57.0",
"@typescript-eslint/parser": "^5.57.0",
"@vitejs/plugin-vue": "^4.1.0",
"@vue/eslint-config-typescript": "^11.0.2",
"@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": "^4.2.3",
"@vue/eslint-config-typescript": "^11.0.3",
"archiver": "^5.3.1",
"eslint": "^8.37.0",
"eslint-plugin-vue": "^9.10.0",
"eslint": "^8.47.0",
"eslint-plugin-vue": "^9.17.0",
"http-browserify": "^1.7.0",
"https-browserify": "^1.0.0",
"jest": "^29.5.0",
"jest": "^29.6.2",
"rollup-plugin-polyfill-node": "^0.12.0",
"sass": "^1.60.0",
"sass": "^1.65.1",
"stream-browserify": "^3.0.0",
"ts-jest": "^29.0.5",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"typescript": "^5.0.2",
"typescript": "^5.1.6",
"util": "^0.12.5",
"vite": "^4.2.1",
"vue-tsc": "^1.2.0",
"vite": "^4.4.9",
"vue-tsc": "^1.8.8",
"yarn-upgrade-all": "^0.7.2"
},
"description": "An Ionic project"

View File

@ -154,7 +154,7 @@ const mainListner = (message: RequestArguments, sender:any, sendResponse: (a: an
}
case 'eth_gasPrice': {
try {
sendResponse((await getGasPrice()).toHexString())
sendResponse(strToHex(String(await getGasPrice() ?? 0)))
} catch {
sendResponse({
error: true,
@ -217,7 +217,7 @@ const mainListner = (message: RequestArguments, sender:any, sendResponse: (a: an
data: params?.data ?? '',
value: params?.value ?? '0x0'
})
const gasHex = gas?._hex ? gas?._hex : gas
const gasHex = strToHex(String(gas ?? 0))
sendResponse(gasHex)
} catch(err) {
if(String(err).includes('UNPREDICTABLE_GAS_LIMIT')) {

View File

@ -1,10 +1,12 @@
import { getSelectedAccount, getSelectedNetwork } from '@/utils/platform';
import { BigNumber, ethers } from "ethers"
import { ethers } from "ethers"
import { strToHex } from '@/utils/platform';
export const signMsg = async (msg: string) => {
const account = await getSelectedAccount()
const wallet = new ethers.Wallet(account.pk)
return await wallet.signMessage( msg.startsWith('0x') ? ethers.utils.arrayify(msg): msg)
return await wallet.signMessage( msg.startsWith('0x') ? ethers.getBytes(msg): msg)
}
export const signTypedData = async (msg: string) => {
@ -18,73 +20,77 @@ export const signTypedData = async (msg: string) => {
}
}
}
return await wallet._signTypedData(parsedMsg.domain, parsedMsg.types, parsedMsg.message)
return await wallet.signTypedData(parsedMsg.domain, parsedMsg.types, parsedMsg.message)
}
export const getBalance = async () =>{
const account = await getSelectedAccount()
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.getBalance(account.address)
}
export const getGasPrice = async () => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
return await provider.getGasPrice()
const provider = new ethers.JsonRpcProvider(network.rpc)
const feed = await provider.getFeeData()
const gasPrice = feed.gasPrice ?? feed.maxFeePerGas
return gasPrice
}
export const getBlockNumber = async () => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.getBlockNumber()
}
export const getBlockByNumber = async (blockNum: number) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.getBlock(blockNum)
}
export const estimateGas = async ({to = '', from = '', data = '', value = '0x0' }: {to: string, from: string, data: string, value: string}) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.estimateGas({to, from, data, value})
}
export const evmCall = async ({to = '', from = '', data = '', value = '0x0' }: {to: string, from: string, data: string, value: string}) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.call({to, from, data, value})
}
export const getTxByHash = async (hash: string) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.getTransaction(hash)
}
export const getTxReceipt = async (hash: string) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.getTransactionReceipt(hash)
}
export const getCode = async (addr: string) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
return await provider.getCode(addr)
}
export const getFromMemonic = (memonic: string, index: number) => {
export const getFromMnemonic = (mnemonic: string, index: number) => {
const path = `m/44'/60'/0'/0/${index}`
const wallet = ethers.Wallet.fromMnemonic(memonic, path)
const mnemonicInst = ethers.Mnemonic.fromPhrase(mnemonic)
const wallet = ethers.HDNodeWallet.fromMnemonic(mnemonicInst, path)
return wallet.privateKey
}
export const getTxCount = async (addr: string, block: null | string = null) => {
const network = await getSelectedNetwork()
const provider = new ethers.providers.JsonRpcProvider(network.rpc)
const provider = new ethers.JsonRpcProvider(network.rpc)
if(block){
return await provider.getTransactionCount(addr, block)
} else {
@ -94,10 +100,10 @@ export const getTxCount = async (addr: string, block: null | string = null) => {
export const sendTransaction = async ({ data= '', gas='0x0', to='', from='', value='0x0', gasPrice='0x0'}:
{to: string, from: string, data: string, value: string, gas: string, gasPrice: string},
gasEstimate: Promise<BigNumber> | null = null, pGasPrice : Promise<BigNumber> | null) => {
gasEstimate: Promise<bigint> | null = null, pGasPrice : Promise<bigint | null> | null) => {
const account = await getSelectedAccount()
const network = await getSelectedNetwork()
const wallet = new ethers.Wallet(account.pk, new ethers.providers.JsonRpcProvider(network.rpc))
const wallet = new ethers.Wallet(account.pk, new ethers.JsonRpcProvider(network.rpc))
if(gas === '0x0') {
if(!gasEstimate){
throw new Error('No gas estimate available')
@ -110,9 +116,16 @@ gasEstimate: Promise<BigNumber> | null = null, pGasPrice : Promise<BigNumber> |
if(!pGasPrice){
throw new Error('No gas estimate available')
}else {
gasPrice = (await pGasPrice).toString()
gasPrice = (await pGasPrice ?? 0).toString()
}
}
console.log('gasPrice', gasPrice)
console.log('gas', gas)
if(gas === '0x0' || gasPrice === '0x0' || 1 === 1) {
throw new Error('No gas estimate available')
}
return await wallet.sendTransaction({to, from, data, value, gasLimit: gas, gasPrice})
}
@ -120,5 +133,5 @@ export const formatBalance = (balance: string) => {
Intl.NumberFormat('en-US', {
notation: 'compact',
maximumFractionDigits: 6
}).format(Number(ethers.utils.parseEther(balance)))
}).format(Number(ethers.parseEther(balance)))
}

View File

@ -31,7 +31,8 @@
</ion-label>
</ion-item>
<ion-item @click="copyAddress(account.address, getToastRef())">
<p style="font-size:0.7rem">{{ account.address }}</p><ion-icon :icon="copyOutline"></ion-icon>
<p style="font-size: 0.7rem">{{ account.address }}</p>
<ion-icon :icon="copyOutline"></ion-icon>
</ion-item>
<ion-item>
<ion-chip @click="viewPk(account.address)">View Pk</ion-chip>
@ -40,11 +41,7 @@
</ion-item>
</ion-list>
<ion-modal
:is-open="pkModal"
@didDismiss="shownPk=''"
>
<ion-modal :is-open="pkModal" @didDismiss="shownPk = ''">
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
@ -55,21 +52,27 @@
</ion-header>
<ion-content class="ion-padding">
<ion-item @click="copyAddress(shownPk, getToastRef())" button>
<ion-icon style="margin-right: 0.5rem;" :icon="copyOutline" />
<ion-icon style="margin-right: 0.5rem" :icon="copyOutline" />
<ion-label button>PK</ion-label>
<ion-input id="pastePk" v-model="shownPk" readonly></ion-input>
<ion-input label="pk" id="pastePk" v-model="shownPk" readonly></ion-input>
</ion-item>
</ion-content>
</ion-modal>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import { defineComponent, ref, Ref } from "vue";
import { getAccounts, copyAddress, replaceAccounts, getSettings, clearPk, getSelectedAccount, saveSelectedAccount } from "@/utils/platform"
import {
getAccounts,
copyAddress,
replaceAccounts,
getSettings,
clearPk,
getSelectedAccount,
saveSelectedAccount,
} from "@/utils/platform";
import {
IonContent,
IonHeader,
@ -87,14 +90,14 @@ import {
IonToast,
modalController,
IonInput,
IonModal
IonModal,
} from "@ionic/vue";
import { addCircleOutline, copyOutline } from "ionicons/icons";
import router from "@/router";
import UnlockModal from '@/views/UnlockModal.vue'
import UnlockModal from "@/views/UnlockModal.vue";
import type { Account, Settings } from '@/extension/types'
import type { Account, Settings } from "@/extension/types";
export default defineComponent({
components: {
@ -112,100 +115,99 @@ export default defineComponent({
IonButton,
IonToast,
IonInput,
IonModal
IonModal,
},
setup() {
const accounts = ref([]) as Ref<Account[]>
const loading = ref(true)
const toastState = ref(false)
const shownPk = ref('')
const pkModal = ref(false)
const settings = ref({}) as Ref<Settings>
const accounts = ref([]) as Ref<Account[]>;
const loading = ref(true);
const toastState = ref(false);
const shownPk = ref("");
const pkModal = ref(false);
const settings = ref({}) as Ref<Settings>;
const getToastRef = () => toastState
const getToastRef = () => toastState;
const loadData = () => {
const pAccounts = getAccounts()
const pGetSettings = getSettings()
const pAccounts = getAccounts();
const pGetSettings = getSettings();
Promise.all([pAccounts, pGetSettings]).then((res) => {
accounts.value = res[0]
settings.value = res[1]
loading.value = false
})
}
accounts.value = res[0];
settings.value = res[1];
loading.value = false;
});
};
const deleteAccount = async (address: string) => {
loading.value = true
loading.value = true;
if (settings.value.enableStorageEnctyption) {
const modalR = await openModal('delAcc')
const modalR = await openModal("delAcc");
if (!modalR) {
return
return;
}
}
const findIndex = accounts.value.findIndex(a => a.address === address)
const selectedAccount = await getSelectedAccount()
const pArr: Array<Promise<void>> = []
const findIndex = accounts.value.findIndex((a) => a.address === address);
const selectedAccount = await getSelectedAccount();
const pArr: Array<Promise<void>> = [];
if (findIndex !== -1) {
accounts.value.splice(findIndex, 1)
pArr.push(replaceAccounts([...accounts.value]))
accounts.value.splice(findIndex, 1);
pArr.push(replaceAccounts([...accounts.value]));
}
if (selectedAccount.address === address) {
pArr.push(saveSelectedAccount({ name: '', pk: '', encPk: '', address: ''}))
}
await Promise.all(pArr)
loading.value = false
pArr.push(saveSelectedAccount({ name: "", pk: "", encPk: "", address: "" }));
}
await Promise.all(pArr);
loading.value = false;
};
const editAccount = (address: string) => {
router.push(`add-account/edit/${address}`)
}
router.push(`add-account/edit/${address}`);
};
const goToAddAccount = () => {
router.push("/tabs/add-account");
};
onIonViewWillEnter(() => {
loadData()
})
loadData();
});
const openModal = async (type: string) => {
const modal = await modalController.create({
component: UnlockModal,
componentProps: {
unlockType: type
}
unlockType: type,
},
});
modal.present();
const { role } = await modal.onWillDismiss();
if(role === 'confirm') return true
return false
}
if (role === "confirm") return true;
return false;
};
const viewPk = async (addr: string) => {
let pk = ''
const account = accounts.value.find(a => a.address === addr)
let pk = "";
const account = accounts.value.find((a) => a.address === addr);
if (settings.value.enableStorageEnctyption) {
if (account?.encPk) {
const modalR = await openModal('viewPk')
const modalR = await openModal("viewPk");
if (modalR) {
const account = (await getAccounts()).find(a => a.address === addr)
pk = account?.pk ?? ''
const account = (await getAccounts()).find((a) => a.address === addr);
pk = account?.pk ?? "";
}
} else {
pk = account?.pk ?? ''
pk = account?.pk ?? "";
}
} else {
pk = account?.pk ?? ''
pk = account?.pk ?? "";
}
if (pk) {
shownPk.value = pk
shownPk.value = pk;
if (settings.value.encryptAfterEveryTx) {
clearPk()
}
pkModal.value = true
clearPk();
}
pkModal.value = true;
}
};
return {
accounts,
@ -220,9 +222,8 @@ export default defineComponent({
goToAddAccount,
viewPk,
pkModal,
shownPk
}
}
shownPk,
};
},
});
</script>

View File

@ -10,7 +10,7 @@
<ion-content class="ion-padding">
<ion-item>
<ion-label>Name</ion-label>
<ion-input v-model="name"></ion-input>
<ion-input label="name" v-model="name"></ion-input>
</ion-item>
<ion-item>
<ion-label>Get Random Name</ion-label>
@ -24,7 +24,7 @@
button
/>
<ion-label button>PK</ion-label>
<ion-input id="pastePk" v-model="pk"></ion-input>
<ion-input label="pk" id="pastePk" v-model="pk"></ion-input>
</ion-item>
<template v-if="!isEdit">
<ion-item>
@ -67,6 +67,7 @@
<ion-item>
<ion-textarea
style="overflow-y: scroll"
label="Enter mnemonic"
:rows="10"
:cols="10"
v-model="mnemonic"
@ -74,7 +75,7 @@
</ion-item>
<ion-item>
<ion-label>Enter Index (default: 0)</ion-label>
<ion-input v-model="mnemonicIndex"></ion-input>
<ion-input label="mnemonic index" v-model="mnemonicIndex"></ion-input>
</ion-item>
<ion-item>
<ion-button @click="extractMnemonic">Extract</ion-button>
@ -122,7 +123,7 @@ import UnlockModal from "@/views/UnlockModal.vue";
import { encrypt, getCryptoParams } from "@/utils/webCrypto";
import { clipboardOutline } from "ionicons/icons";
import { getFromMemonic } from "@/utils/wallet";
import { getFromMnemonic } from "@/utils/wallet";
export default defineComponent({
components: {
@ -294,7 +295,7 @@ export default defineComponent({
alertOpen.value = true;
return;
}
pk.value = getFromMemonic(mnemonic.value, mnemonicIndex.value);
pk.value = getFromMnemonic(mnemonic.value, mnemonicIndex.value);
mnemonicModal.value = false;
};

View File

@ -11,16 +11,22 @@
>
<ion-item>
<ion-label>Name(*)</ion-label>
<ion-input v-model="name" placeholder="ex: Polygon"></ion-input>
<ion-input label="name" v-model="name" placeholder="ex: Polygon"></ion-input>
</ion-item>
<ion-item>
<ion-label>ChainId(*)</ion-label>
<ion-input v-model="chainId" placeholder="137" type="number"></ion-input>
<ion-input
label="chainid"
v-model="chainId"
placeholder="137"
type="number"
></ion-input>
</ion-item>
<ion-item button>
<ion-icon :icon="clipboardOutline" @click="paste('pasteRpc')" />
<ion-label>RPC URL(*)</ion-label>
<ion-input
label="rpc"
id="pasteRpc"
placeholder="https://polygon-mainnet.g.alchemy.com/..."
v-model="rpc"
@ -29,12 +35,18 @@
<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-input
label="native token"
id="native-token"
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
label="explorer"
id="pasteExplorer"
placeholder="https://polygonscan.com"
v-model="explorer"

View File

@ -33,6 +33,7 @@
<ion-label>Error From Contract:</ion-label>
<ion-textarea
style="overflow-y: scroll"
label="Error"
:rows="10"
:cols="20"
:value="error"

View File

@ -22,6 +22,7 @@
<ion-item>
<ion-label>Name:</ion-label>
<ion-input
label="Name"
style="margin-left: 0.5rem"
v-model="name"
readonly
@ -31,6 +32,7 @@
<ion-item>
<ion-label>ChainId: </ion-label>
<ion-input
label="ChainId"
style="margin-left: 0.5rem"
v-model="chainId"
readonly
@ -40,6 +42,7 @@
<ion-item button>
<ion-label>RPC URL: </ion-label>
<ion-input
label="RPC URL"
style="margin-left: 0.5rem"
readonly
placeholder="https://polygon-mainnet.g.alchemy.com/..."
@ -49,6 +52,7 @@
<ion-item button>
<ion-label>Native Token Symbol: </ion-label>
<ion-input
label="Native Token Symbol"
style="margin-left: 0.5rem"
readonly
placeholder="MATIC"
@ -58,6 +62,7 @@
<ion-item button>
<ion-label>Explorer: </ion-label>
<ion-input
label="Explorer"
style="margin-left: 0.5rem"
readonly
placeholder="https://polygonscan.com"

View File

@ -228,7 +228,7 @@
<ion-label>Old Password</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="mpPass" type="password"></ion-input>
<ion-input label="password" v-model="mpPass" type="password"></ion-input>
</ion-item>
</ion-list>
<div v-else>
@ -237,7 +237,7 @@
<ion-label>New Password</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="mpPass" type="password"></ion-input>
<ion-input label="password" v-model="mpPass" type="password"></ion-input>
</ion-item>
</ion-list>
<ion-list>
@ -245,7 +245,11 @@
<ion-label>Confirm</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="mpConfirm" type="password"></ion-input>
<ion-input
label="password"
v-model="mpConfirm"
type="password"
></ion-input>
</ion-item>
</ion-list>
</div>

View File

@ -119,7 +119,7 @@
<ion-label>Limit in units</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="inGasLimit" type="number"></ion-input>
<ion-input label="gas limit" v-model="inGasLimit" type="number"></ion-input>
</ion-item>
<ion-item>
<ion-button @click="setGasLimit">Set Price</ion-button>
@ -143,7 +143,11 @@
<ion-label>Price in gwei</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="inGasPrice" type="number"></ion-input>
<ion-input
label="price in gwei"
v-model="inGasPrice"
type="number"
></ion-input>
</ion-item>
<ion-item>
<ion-button @click="setGasPrice">Set Price</ion-button>
@ -302,9 +306,9 @@ export default defineComponent({
const newGasData = () => {
gasFee.value = Number(
ethers.utils.formatUnits(String(gasLimit.value * gasPrice.value), "gwei")
ethers.formatUnits(String(gasLimit.value * gasPrice.value), "gwei")
);
txValue.value = Number(ethers.utils.formatEther(params?.value ?? "0x0"));
txValue.value = Number(ethers.formatEther(params?.value ?? "0x0"));
totalCost.value = gasFee.value + txValue.value;
};
@ -323,13 +327,15 @@ export default defineComponent({
const pGetPrices = getPrices();
selectedNetwork.value = await getSelectedNetwork();
userBalance.value = Number(
ethers.utils.formatEther((await pBalance).toString() ?? "0x0")
ethers.formatEther((await pBalance).toString() ?? "0x0")
);
gasPrice.value = parseInt(
ethers.utils.formatUnits((await pGasPrice).toString() ?? "0x0", "gwei"),
ethers.formatUnits(((await pGasPrice) || 0).toString() ?? "0x0", "gwei"),
10
);
console.log(await pGasPrice);
try {
gasLimit.value = parseInt((await pEstimateGas).toString(), 10);
} catch (err) {
@ -364,7 +370,7 @@ export default defineComponent({
timerFee.value = 20;
loading.value = true;
gasPrice.value = parseInt(
ethers.utils.formatUnits((await getGasPrice()).toString(), "gwei"),
ethers.formatUnits(((await getGasPrice()) || 0).toString(), "gwei"),
10
);
newGasData();
@ -391,7 +397,7 @@ export default defineComponent({
gasPrice.value = inGasPrice.value;
gasPriceReFetch.value = false;
walletSendData(rid, {
gasPrice: ethers.utils.parseUnits(gasPrice.value.toString(), "gwei"),
gasPrice: numToHexStr(gasPrice.value),
});
newGasData();
gasPriceModal.value = false;

View File

@ -31,7 +31,7 @@
<ion-label>Unlock Password</ion-label>
</ion-item>
<ion-item>
<ion-input v-model="mpPass" type="password"></ion-input>
<ion-input label="password" v-model="mpPass" type="password"></ion-input>
</ion-item>
</ion-list>
<ion-item>

2502
yarn.lock

File diff suppressed because it is too large Load Diff