diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a378f8..d5a9b45 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,21 @@
# Changelog
+## Manifest Version 1.3.0
+
+- refactored the wallet to use etheres V6
+- implemented EIP6963Provider
+- updated all dependencies
+- added ability to send native tokens
+- added ability to manage ABIs
+- added ability to perfrom arbitrary read calls to contracts
+- added ability to perfrom arbitrary write calls to contracts
+- added ability to save read or write calls for later use
+- added sandbox to be able to evaluate JS code in order to pass complex parameters to read or write calls
+- added base Network to templates class
+- added Icon for base network
+- added ability to add contacts and load them in Read contract and Write and Send token pages
+- added ability to paste current selected address to both webpages and insde wallet itself
+
## Manifest Version 1.2.8
- better support for estimate gas
diff --git a/eval-sandbox.html b/eval-sandbox.html
new file mode 100644
index 0000000..57c0550
--- /dev/null
+++ b/eval-sandbox.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Eval Sandbox
+
+
+
\ No newline at end of file
diff --git a/index.html b/index.html
index 2f26e1f..8f589b8 100644
--- a/index.html
+++ b/index.html
@@ -1,5 +1,5 @@
-
+
Clear Wallet
diff --git a/package.json b/package.json
index 2c03b86..c8ccdbb 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,11 @@
{
"name": "clear-wallet",
- "version": "1.2.8",
+ "version": "1.2.9",
"private": true,
+ "description": "Clear Wallet (CLW) is a wallet that helps you manage your Ethereum assets and interact with Ethereum dApps and contracts with the main focus on absolute privacy.",
"scripts": {
"dev": "vite",
- "inject": "tsc --outFile src/extension/inject.js src/extension/inject.ts",
+ "inject": "tsc --downlevelIteration --outFile src/extension/inject.js src/extension/inject.ts",
"content": "tsc --outFile src/extension/content.js src/extension/content.ts",
"post-build": "ts-node ./release-scripts/post-build.ts",
"build": "yarn inject && yarn content && vue-tsc --noEmit && vite build && yarn post-build",
@@ -53,6 +54,5 @@
"vite": "^4.4.9",
"vue-tsc": "^1.8.8",
"yarn-upgrade-all": "^0.7.2"
- },
- "description": "An Ionic project"
+ }
}
diff --git a/public/assets/chain-icons/base.webp b/public/assets/chain-icons/base.webp
new file mode 100644
index 0000000..e901973
Binary files /dev/null and b/public/assets/chain-icons/base.webp differ
diff --git a/public/index.html b/public/index.html
index 3d6e6c9..2f98757 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,5 +1,5 @@
-
+
Clear Wallet
diff --git a/release-scripts/post-build.ts b/release-scripts/post-build.ts
index f095a0f..a09f117 100644
--- a/release-scripts/post-build.ts
+++ b/release-scripts/post-build.ts
@@ -1,16 +1,15 @@
(async () => {
const CONTENT_BUILD_PATH = 'src/extension/content.js'
- const METAMASK_STUB_PATH = 'src/extension/metamask-stub.js'
+ const METAMASK_INJECT_PATH = 'src/extension/inject.js'
const fs = (await import('fs')).default
const path = (await import('path')).default
const pkg = JSON.parse(fs.readFileSync('dist/manifest.json').toString());
pkg.content_scripts[0].js[0] = CONTENT_BUILD_PATH
- pkg.content_scripts[1].js[0] = METAMASK_STUB_PATH
+ pkg.content_scripts[1].js[0] = METAMASK_INJECT_PATH
fs.writeFileSync('dist/manifest.json', JSON.stringify(pkg, null, 2))
- // fs.writeFileSync('dist/rules.js', fs.readFileSync('rules.json').toString())
fs.writeFileSync('dist/'+ CONTENT_BUILD_PATH, fs.readFileSync('src/extension/content.js').toString())
- fs.writeFileSync('dist/'+ METAMASK_STUB_PATH, fs.readFileSync('src/extension/metamask-stub.js').toString())
+ fs.writeFileSync('dist/'+ METAMASK_INJECT_PATH, fs.readFileSync('src/extension/inject.js').toString())
const directory = 'dist/assets/';
fs.readdir(directory, (err, files) => {
files.forEach(file => {
diff --git a/src/App.vue b/src/App.vue
index 2a8f6c2..11893d0 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -6,9 +6,11 @@
diff --git a/src/views/AbiList.vue b/src/views/AbiList.vue
new file mode 100644
index 0000000..d13c93b
--- /dev/null
+++ b/src/views/AbiList.vue
@@ -0,0 +1,146 @@
+
+
+
+
+
+ Close
+
+ Select Abi
+
+
+
+ Add New ABI
+
+
+
+ Saved ABIs
+
+
+
+
+
+ {{ item }}
+
+ Edit
+ Delete
+
+
+
+
+
+
+ No Abis found, please add at least one
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/AbiSelectFunction.vue b/src/views/AbiSelectFunction.vue
new file mode 100644
index 0000000..8beacdf
--- /dev/null
+++ b/src/views/AbiSelectFunction.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+ Close
+
+ Select Function
+
+
+
+
+
+
+
+
+
+ Functions
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/AccountsTab.vue b/src/views/AccountsTab.vue
index 4b7ac67..caa1c1f 100644
--- a/src/views/AccountsTab.vue
+++ b/src/views/AccountsTab.vue
@@ -15,6 +15,7 @@
PK
-
+
diff --git a/src/views/AddAccount.vue b/src/views/AddAccount.vue
index cf5cbaa..76c12ac 100644
--- a/src/views/AddAccount.vue
+++ b/src/views/AddAccount.vue
@@ -9,8 +9,7 @@
- Name
-
+
Get Random Name
@@ -23,8 +22,12 @@
:icon="clipboardOutline"
button
/>
- PK
-
+
@@ -33,7 +36,7 @@
Extarct From A MnemonicExtract From A Mnemonic
@@ -67,7 +70,7 @@
Enter Index (default: 0)
-
+
+
+
+ Close
Extract
@@ -111,7 +117,6 @@ import {
saveSelectedAccount,
getAccounts,
saveAccount,
- getRandomPk,
smallRandomString,
paste,
getSettings,
@@ -123,7 +128,7 @@ import UnlockModal from "@/views/UnlockModal.vue";
import { encrypt, getCryptoParams } from "@/utils/webCrypto";
import { clipboardOutline } from "ionicons/icons";
-import { getFromMnemonic } from "@/utils/wallet";
+import { getFromMnemonic, getRandomPk } from "@/utils/wallet";
export default defineComponent({
components: {
diff --git a/src/views/AddContact.vue b/src/views/AddContact.vue
new file mode 100644
index 0000000..e7782a5
--- /dev/null
+++ b/src/views/AddContact.vue
@@ -0,0 +1,153 @@
+
+
+
+
+ Add Contact
+ Edit Contact
+
+
+
+
+
+
+
+
+
+
+
+
+ Cancel
+ {{
+ isEdit ? "Edit Contact" : "Add Contact"
+ }}
+
+
+
+
+
+
+
diff --git a/src/views/AddNetwork.vue b/src/views/AddNetwork.vue
index afdd33b..4c3d044 100644
--- a/src/views/AddNetwork.vue
+++ b/src/views/AddNetwork.vue
@@ -10,13 +10,17 @@
>Add from popular chain list
- Name(*)
-
+
- ChainId(*)
- RPC URL(*)
-
- Native Token Symbol(?)
- Explorer(?)
Settings
+
+
+
+
+ Send Tokens
+
+
+
+
+ Read Contract
+
+
+
+
+ Write Contracts
+
+
@@ -50,9 +67,19 @@ import {
IonTabBar,
IonTabButton,
IonLabel,
- IonIcon
+ IonIcon,
} from "@ionic/vue";
-import { personCircle, walletOutline, diamondOutline, cogOutline, receiptOutline, gitNetworkOutline } from "ionicons/icons";
+import {
+ personCircle,
+ walletOutline,
+ diamondOutline,
+ cogOutline,
+ receiptOutline,
+ gitNetworkOutline,
+ sendOutline,
+ glassesOutline,
+ pushOutline,
+} from "ionicons/icons";
export default defineComponent({
components: {
@@ -63,7 +90,7 @@ export default defineComponent({
IonTabBar,
IonTabButton,
IonLabel,
- IonIcon
+ IonIcon,
},
name: "AppTabs",
setup() {
@@ -81,8 +108,11 @@ export default defineComponent({
cogOutline,
receiptOutline,
gitNetworkOutline,
+ sendOutline,
beforeTabChange,
afterTabChange,
+ glassesOutline,
+ pushOutline,
};
},
});
diff --git a/src/views/AssetsTab.vue b/src/views/AssetsTab.vue
index 8b91ee5..c848117 100644
--- a/src/views/AssetsTab.vue
+++ b/src/views/AssetsTab.vue
@@ -16,6 +16,7 @@
>
- No assets found for this wallet address.
+
+
+ No know assets found for this wallet address.
+
@@ -274,7 +279,7 @@ export default defineComponent({
return null;
}
} catch (error) {
- console.error("Failed to fetch web3 profiles", error);
+ console.info("ERROR: Failed to fetch web3 profiles", error);
return null;
}
};
diff --git a/src/views/ContactsSelect.vue b/src/views/ContactsSelect.vue
new file mode 100644
index 0000000..202f310
--- /dev/null
+++ b/src/views/ContactsSelect.vue
@@ -0,0 +1,173 @@
+
+
+
+
+
+ Close
+
+ Select Contact
+
+
+
+
+ Add contact
+
+
+
+
+
+
+
+
+ Contacts
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+ {{ item.address }}
+
+
+
+
+
+ Edit contact
+ Delete contact
+
+
+
+
+ No contacts found, please add at least one
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/ContractError.vue b/src/views/ContractError.vue
index 9e2b55a..69e3981 100644
--- a/src/views/ContractError.vue
+++ b/src/views/ContractError.vue
@@ -33,7 +33,7 @@
Error From Contract:
- Wallet
+
+
+
+
+ CL Wallet
+
@@ -13,10 +22,18 @@
Selected Account: {{ selectedAccount?.name }}
- Select
+ {
+ accountsModal = true;
+ toastState = false;
+ }
+ "
+ >Select
- {{ selectedAccount?.address }}
+ {{ selectedAccount?.address }}
- Selected Network ID: {{ selectedNetwork?.chainId }}
- Select
+ Selected Network ID:
+ {{
+ selectedNetwork?.chainId
+ }}
+ {
+ networksModal = true;
+ toastState = false;
+ }
+ "
+ >Select
-
- {{ account.name }}
+ {{ account.name }}
- {{ account.address }}
+ {{
+ account.address
+ }}
@@ -135,11 +172,18 @@
@click="changeSelectedNetwork(network.chainId)"
slot="start"
:value="network.chainId"
- />
- {{ network.name }}
+ :aria-label="network.name"
+ >
+
+ ID: {{ network.chainId }} ->
+
+ {{ network.name }}
+
- {{ network.rpc }}
+ {{
+ network.rpc
+ }}
diff --git a/src/views/ReadContract.vue b/src/views/ReadContract.vue
new file mode 100644
index 0000000..7b1a2c5
--- /dev/null
+++ b/src/views/ReadContract.vue
@@ -0,0 +1,637 @@
+
+
+
+
+ Read From Contract
+
+
+
+ Load saved read action
+
+
+ Selected Abi: {{ selectedAbi }}
+
+
+ No Abi selected
+
+
+ Load Abi
+
+
+
+
+
+
+
+ Load address from contacts
+
+
+
+
+ Select Abi with functions to enable function selection
+
+
+
+ Selected Function: {{ functionName }}
+ Change
+
+
+ No Function selected
+ Select
+
+
+
+
+
+
+ PARAMS NOTES:
+
+
+ Will be evaluated in sandbox using js eval in order to pass complex types
+ like [1,2 [1,0x...]]
+ Strings must be passed using qoutes example '0x3...1A2', or ['param1',
+ 'param2'] for multiple params.
+ Params are sent exactly as they are, numbers are not parsed to UINT256
+ format.
+
+ SET PARAMS:
+
+
+ P:{{ Number(index) + 1 }} name: {{ param.name }} type: ({{
+ param.type
+ }})
+
+
+
+
+
+
+ Function has no params
+
+
+
+
+
+
+
+
+ Save Action
+ Execute Action
+
+
+
+
+
+
+
+
+
+
+ Close
+
+ Select
+
+
+
+
+
+
+
+
+ Cancel
+ Save
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/RequestNetwork.vue b/src/views/RequestNetwork.vue
index e41ace1..c084f17 100644
--- a/src/views/RequestNetwork.vue
+++ b/src/views/RequestNetwork.vue
@@ -22,7 +22,7 @@
Name:
ChainId:
RPC URL:
Native Token Symbol:
Explorer:
+
+
+
+
+ Close
+
+ Select Action
+
+
+
+
+
+
+
+
+
+ Actions
+
+
+
+
+
+ {{ key }} on ABI {{ actions[key].abi }}
+
+
+
+ Delete
+
+
+
+
+
+
+ No Actions found, please save at least one
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/SendToken.vue b/src/views/SendToken.vue
new file mode 100644
index 0000000..64d58d8
--- /dev/null
+++ b/src/views/SendToken.vue
@@ -0,0 +1,302 @@
+
+
+
+
+ Send Native Token
+
+
+
+
+
+ Current Network
+
+
+
+ Name: {{ selectedNetwork.name }}
+
+
+ ID: {{ selectedNetwork.chainId }}
+
+
+
+
+ Current Address
+
+
+ {{ selectedAccount?.address }}
+
+
+
+ Current Balance
+
+
+ {{ currentBalance.toFixed(8) }}
+
+
+
+
+ Send To Address:
+
+
+
+
+
+
+
+
+
+ Load address from contacts
+
+
+
+
+ Amount (e.g. 1.2):
+
+
+
+
+
+
+
+ Prompt Transaction
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/SettingsTab.vue b/src/views/SettingsTab.vue
index e4d45e6..c5ae249 100644
--- a/src/views/SettingsTab.vue
+++ b/src/views/SettingsTab.vue
@@ -20,6 +20,7 @@
Enable Storage Encryption
Enable Auto Lock
Permanent Lock
Old Password
-
+
@@ -237,7 +245,11 @@
New Password
-
+
@@ -246,7 +258,7 @@
diff --git a/src/views/SignTx.vue b/src/views/SignTx.vue
index ed5cd31..e9bb28e 100644
--- a/src/views/SignTx.vue
+++ b/src/views/SignTx.vue
@@ -66,6 +66,7 @@
Raw TX:
Limit in units
-
+
Set Price
@@ -144,7 +149,7 @@
@@ -256,7 +261,12 @@ export default defineComponent({
if (!decodedParam) {
isError = true;
} else {
- signTxData.value = JSON.stringify(params, null, 2);
+ const paramsWithoutZeros = Object.fromEntries(
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ Object.entries(params).filter(([_, v]) => v !== "0x0")
+ );
+
+ signTxData.value = JSON.stringify(paramsWithoutZeros, null, 2);
}
const openModal = async () => {
@@ -304,16 +314,22 @@ export default defineComponent({
}
};
- const newGasData = () => {
+ const newGasData = async () => {
+ await walletSendData(rid, {
+ gas: numToHexStr(gasLimit.value),
+ });
+
+ await walletSendData(rid, {
+ gasPrice: numToHexStr(BigInt(Math.trunc(gasPrice.value * 1e9))),
+ });
gasFee.value = Number(
- ethers.formatUnits(String(gasLimit.value * gasPrice.value), "gwei")
+ ethers.formatUnits(Math.trunc(gasLimit.value * gasPrice.value), "gwei")
);
txValue.value = Number(ethers.formatEther(params?.value ?? "0x0"));
totalCost.value = gasFee.value + txValue.value;
};
onIonViewWillEnter(async () => {
- console.log(params.value);
(window as any)?.resizeTo?.(600, 800);
const pEstimateGas = estimateGas({
to: params?.to ?? "",
@@ -330,11 +346,7 @@ export default defineComponent({
ethers.formatEther((await pBalance).toString() ?? "0x0")
);
- gasPrice.value = parseInt(
- ethers.formatUnits(((await pGasPrice) || 0).toString() ?? "0x0", "gwei"),
- 10
- );
- console.log(await pGasPrice);
+ gasPrice.value = parseFloat((await pGasPrice).toString() ?? 0.1);
try {
gasLimit.value = parseInt((await pEstimateGas).toString(), 10);
@@ -347,16 +359,13 @@ export default defineComponent({
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") )
-
- newGasData();
if (userBalance.value < totalCost.value) {
insuficientBalance.value = true;
}
const prices = await pGetPrices;
dollarPrice.value =
prices[chainIdToPriceId(selectedNetwork.value?.chainId ?? 0)]?.usd ?? 0;
-
+ await newGasData();
loading.value = false;
interval = setInterval(async () => {
@@ -369,11 +378,8 @@ export default defineComponent({
if (timerFee.value <= 0) {
timerFee.value = 20;
loading.value = true;
- gasPrice.value = parseInt(
- ethers.formatUnits(((await getGasPrice()) || 0).toString(), "gwei"),
- 10
- );
- newGasData();
+ gasPrice.value = parseFloat((await getGasPrice()).toString() ?? 0.1);
+ await newGasData();
loading.value = false;
}
}
@@ -386,9 +392,6 @@ export default defineComponent({
const setGasLimit = () => {
gasLimit.value = inGasLimit.value;
- walletSendData(rid, {
- gas: numToHexStr(gasLimit.value),
- });
newGasData();
gasLimitModal.value = false;
};
@@ -396,9 +399,6 @@ export default defineComponent({
const setGasPrice = () => {
gasPrice.value = inGasPrice.value;
gasPriceReFetch.value = false;
- walletSendData(rid, {
- gasPrice: numToHexStr(gasPrice.value),
- });
newGasData();
gasPriceModal.value = false;
};
diff --git a/src/views/SwitchNetwork.vue b/src/views/SwitchNetwork.vue
index 5a678d7..b53b145 100644
--- a/src/views/SwitchNetwork.vue
+++ b/src/views/SwitchNetwork.vue
@@ -183,7 +183,6 @@ export default defineComponent({
(window as any)?.resizeTo?.(600, 600);
pnetworks = getNetworks();
selectedNetwork.value = await getSelectedNetwork();
- console.log(networkId.value);
existingNetworks.value = await pnetworks;
if ((networkId.value ?? "0") in existingNetworks.value ?? {}) {
networkCase.value = "exists";
diff --git a/src/views/UnitConvertor.vue b/src/views/UnitConvertor.vue
new file mode 100644
index 0000000..e69de29
diff --git a/src/views/UnlockModal.vue b/src/views/UnlockModal.vue
index 29f3741..62b18b0 100644
--- a/src/views/UnlockModal.vue
+++ b/src/views/UnlockModal.vue
@@ -31,7 +31,7 @@
Unlock Password
-
+
diff --git a/src/views/WalletError.vue b/src/views/WalletError.vue
index 43f96b7..b1d201c 100644
--- a/src/views/WalletError.vue
+++ b/src/views/WalletError.vue
@@ -11,8 +11,9 @@
Operation Aborted
- Error:
+
+
+
+ Contract Write Action
+
+
+
+ Load saved wite action
+
+
+ Selected Abi: {{ selectedAbi }}
+
+
+ No Abi selected
+
+
+ Load Abi
+
+
+
+
+
+
+
+ Load address from contacts
+
+
+
+
+ Select Abi with functions to enable function selection
+
+
+
+ Selected Function: {{ functionName }}
+ Change
+
+
+ No Function selected
+ Select
+
+
+
+
+
+ PARAMS NOTES:
+
+
+ Will be evaluated in sandbox using js eval in order to pass complex types
+ like [1,2 [1,0x...]]
+ Strings must be passed using qoutes example '0x3...1A2', or ['param1',
+ 'param2'] for multiple params.
+ Params are sent exactly as they are, numbers are not parsed to UINT256
+ format.
+
+ SET PARAMS:
+
+
+ P:{{ Number(index) + 1 }} name: {{ param.name }} type: ({{
+ param.type
+ }})
+
+
+
+
+
+
+ Function has no params
+
+
+
+
+ Save Action
+ Execute Action
+
+
+
+
+
+
+
+
+
+
+
+
+ Close
+
+ Select
+
+
+
+
+
+
+
+
+ Cancel
+ Save
+
+
+
+
+
+
+
+
diff --git a/vite.config.ts b/vite.config.ts
index a1aba60..13bee50 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -25,9 +25,12 @@ export default defineConfig({
},
build: {
rollupOptions: {
- plugins: [nodePolyfills()]
+ plugins: [nodePolyfills()],
+ input: {
+ ['eval-sandbox']: 'eval-sandbox.html',
+ },
},
- sourcemap: false,
+ sourcemap: true,
chunkSizeWarningLimit: 1000,
commonjsOptions: {
transformMixedEsModules: true