365 lines
10 KiB
Vue
365 lines
10 KiB
Vue
<template>
|
|
<ion-page>
|
|
<ion-header>
|
|
<ion-toolbar>
|
|
<ion-title>
|
|
<ion-avatar
|
|
style="margin: 0.3rem; width: 1.8rem; height: 1.8rem; display: inline-flex"
|
|
>
|
|
<img alt="clw" :src="getUrl('assets/extension-icon/wallet_32.png')" />
|
|
</ion-avatar>
|
|
<span style="position: absolute; top: 0.45rem; margin-left: 0.3rem"
|
|
>CL Wallet</span
|
|
>
|
|
</ion-title>
|
|
</ion-toolbar>
|
|
</ion-header>
|
|
<ion-content class="ion-padding">
|
|
<ion-item v-if="loading || accounts.length < 1">
|
|
<ion-label>No EVM accounts found</ion-label>
|
|
<ion-button @click="goToAddAccount">Add Account</ion-button>
|
|
</ion-item>
|
|
<ion-list v-else>
|
|
<ion-item>
|
|
<ion-label>Selected Account: {{ selectedAccount?.name }}</ion-label>
|
|
<ion-button
|
|
@click="
|
|
() => {
|
|
accountsModal = true;
|
|
toastState = false;
|
|
}
|
|
"
|
|
>Select</ion-button
|
|
>
|
|
</ion-item>
|
|
<ion-item button @click="copyAddress(selectedAccount?.address, getToastRef())">
|
|
<p style="font-size: 0.7rem; color: coral">{{ selectedAccount?.address }}</p>
|
|
<ion-icon style="margin-left: 0.5rem" :icon="copyOutline"></ion-icon>
|
|
</ion-item>
|
|
<ion-item
|
|
v-if="!loading && selectedNetwork?.explorer && selectedAccount?.address"
|
|
>
|
|
<ion-button
|
|
@click="
|
|
openTab(
|
|
`${selectedNetwork.explorer}/address/${selectedAccount?.address}`.replace(
|
|
'//',
|
|
'/'
|
|
)
|
|
)
|
|
"
|
|
expand="block"
|
|
>View Address on
|
|
{{
|
|
`${selectedNetwork.explorer}`.replace("https://", "").replace("http://", "")
|
|
}}
|
|
</ion-button>
|
|
</ion-item>
|
|
</ion-list>
|
|
<ion-item v-if="loading || Object.keys(networks).length < 1">
|
|
<ion-label>No EVM Networks found</ion-label>
|
|
<ion-button @click="goToAddNetwork">Add Network</ion-button>
|
|
</ion-item>
|
|
<ion-item v-else>
|
|
<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
|
|
>Selected Network ID:
|
|
<span style="color: coral; font-weight: bold">{{
|
|
selectedNetwork?.chainId
|
|
}}</span></ion-label
|
|
>
|
|
<ion-button
|
|
@click="
|
|
() => {
|
|
networksModal = true;
|
|
toastState = false;
|
|
}
|
|
"
|
|
>Select</ion-button
|
|
>
|
|
</ion-item>
|
|
|
|
<ion-loading
|
|
:is-open="loading"
|
|
cssClass="my-custom-class"
|
|
message="Please wait..."
|
|
:duration="4000"
|
|
:key="`k${loading}`"
|
|
@didDismiss="loading = false"
|
|
>
|
|
</ion-loading>
|
|
<ion-toast
|
|
position="top"
|
|
:is-open="toastState"
|
|
@didDismiss="toastState = false"
|
|
message="Copied to clipboard"
|
|
:duration="1500"
|
|
></ion-toast>
|
|
</ion-content>
|
|
|
|
<ion-modal :is-open="accountsModal">
|
|
<ion-header>
|
|
<ion-toolbar>
|
|
<ion-buttons slot="start">
|
|
<ion-button @click="accountsModal = false">Close</ion-button>
|
|
</ion-buttons>
|
|
<ion-title>Select</ion-title>
|
|
</ion-toolbar>
|
|
</ion-header>
|
|
<ion-content class="ion-padding">
|
|
<ion-list style="margin-bottom: 4rem">
|
|
<ion-radio-group :value="selectedAccount?.address ?? ''">
|
|
<ion-list-header>
|
|
<ion-label>Accounts</ion-label>
|
|
</ion-list-header>
|
|
|
|
<ion-list
|
|
@click="changeSelectedAccount(account.address)"
|
|
class="ion-padding"
|
|
v-for="account of accounts"
|
|
:key="account.address"
|
|
button
|
|
>
|
|
<ion-item>
|
|
<ion-radio
|
|
:aria-label="account.name"
|
|
slot="start"
|
|
:value="account.address"
|
|
>{{ account.name }}</ion-radio
|
|
>
|
|
</ion-item>
|
|
<ion-item>
|
|
<ion-text style="font-size: 0.7rem; color: coral">{{
|
|
account.address
|
|
}}</ion-text>
|
|
</ion-item>
|
|
</ion-list>
|
|
</ion-radio-group>
|
|
</ion-list>
|
|
</ion-content>
|
|
</ion-modal>
|
|
<ion-modal :is-open="networksModal">
|
|
<ion-header>
|
|
<ion-toolbar>
|
|
<ion-buttons slot="start">
|
|
<ion-button @click="networksModal = false">Close</ion-button>
|
|
</ion-buttons>
|
|
<ion-title>Select</ion-title>
|
|
</ion-toolbar>
|
|
</ion-header>
|
|
<ion-content class="ion-padding">
|
|
<ion-list style="margin-bottom: 4rem">
|
|
<ion-radio-group :value="selectedNetwork.chainId">
|
|
<ion-list-header>
|
|
<ion-label>Networks</ion-label>
|
|
</ion-list-header>
|
|
|
|
<ion-list
|
|
class="ion-padding"
|
|
v-for="network of networks"
|
|
:key="network.chainId"
|
|
>
|
|
<ion-item>
|
|
<ion-radio
|
|
@click="changeSelectedNetwork(network.chainId)"
|
|
slot="start"
|
|
:value="network.chainId"
|
|
:aria-label="network.name"
|
|
>
|
|
<span style="opacity: 0.7; font-size: 0.8rem">
|
|
ID: {{ network.chainId }} ->
|
|
</span>
|
|
{{ network.name }}
|
|
</ion-radio>
|
|
</ion-item>
|
|
<ion-item>
|
|
<ion-text style="opacity: 0.8; font-size: 0.85rem">{{
|
|
network.rpc
|
|
}}</ion-text>
|
|
</ion-item>
|
|
</ion-list>
|
|
</ion-radio-group>
|
|
</ion-list>
|
|
</ion-content>
|
|
</ion-modal>
|
|
</ion-page>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, ref, onMounted, Ref } from "vue";
|
|
import {
|
|
IonContent,
|
|
IonHeader,
|
|
IonPage,
|
|
IonTitle,
|
|
IonToolbar,
|
|
IonLoading,
|
|
IonItem,
|
|
IonLabel,
|
|
IonButton,
|
|
onIonViewWillEnter,
|
|
IonModal,
|
|
IonRadioGroup,
|
|
IonRadio,
|
|
IonButtons,
|
|
IonList,
|
|
IonListHeader,
|
|
IonText,
|
|
IonToast,
|
|
IonIcon,
|
|
IonAvatar,
|
|
} from "@ionic/vue";
|
|
import {
|
|
getAccounts,
|
|
getNetworks,
|
|
getSelectedAccount,
|
|
saveSelectedAccount,
|
|
replaceAccounts,
|
|
getSelectedNetwork,
|
|
copyAddress,
|
|
replaceNetworks,
|
|
getUrl,
|
|
saveSelectedNetwork,
|
|
numToHexStr,
|
|
openTab,
|
|
} from "@/utils/platform";
|
|
import type { Network, Account, Networks } from "@/extension/types";
|
|
import { mainNets } from "@/utils/networks";
|
|
import router from "@/router";
|
|
import { triggerListner } from "@/extension/listners";
|
|
|
|
import { copyOutline } from "ionicons/icons";
|
|
|
|
export default defineComponent({
|
|
components: {
|
|
IonContent,
|
|
IonHeader,
|
|
IonPage,
|
|
IonTitle,
|
|
IonToolbar,
|
|
IonLoading,
|
|
IonItem,
|
|
IonLabel,
|
|
IonButton,
|
|
IonModal,
|
|
IonRadioGroup,
|
|
IonRadio,
|
|
IonButtons,
|
|
IonList,
|
|
IonListHeader,
|
|
IonText,
|
|
IonToast,
|
|
IonIcon,
|
|
IonAvatar,
|
|
},
|
|
setup: () => {
|
|
const loading = ref(false);
|
|
const accounts = ref([]) as Ref<Account[]>;
|
|
const networks = ref({}) as Ref<Networks>;
|
|
const accountsModal = ref(false) as Ref<boolean>;
|
|
const networksModal = ref(false) as Ref<boolean>;
|
|
const selectedAccount = (ref(null) as unknown) as Ref<Account>;
|
|
const selectedNetwork = (ref(null) as unknown) as Ref<Network>;
|
|
const toastState = ref(false);
|
|
|
|
const getToastRef = () => toastState;
|
|
|
|
const loadData = () => {
|
|
loading.value = true;
|
|
const pAccounts = getAccounts();
|
|
const pNetworks = getNetworks();
|
|
const pSelectedAccount = getSelectedAccount();
|
|
const pSelectedNetwork = getSelectedNetwork();
|
|
Promise.all([pAccounts, pNetworks, pSelectedAccount, pSelectedNetwork]).then(
|
|
(res) => {
|
|
accounts.value = res[0];
|
|
networks.value = res[1];
|
|
selectedAccount.value = res[2];
|
|
selectedNetwork.value = res[3];
|
|
loading.value = false;
|
|
}
|
|
);
|
|
};
|
|
|
|
onIonViewWillEnter(() => {
|
|
loadData();
|
|
});
|
|
|
|
onMounted(() => {
|
|
// nothing
|
|
});
|
|
|
|
const goToAddAccount = () => {
|
|
router.push("/tabs/add-account");
|
|
};
|
|
|
|
const goToAddNetwork = () => {
|
|
router.push("/tabs/add-network");
|
|
};
|
|
|
|
const changeSelectedAccount = async (address: string) => {
|
|
loading.value = true;
|
|
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);
|
|
const newAccounts = [...accounts.value];
|
|
await replaceAccounts(newAccounts);
|
|
triggerListner(
|
|
"accountsChanged",
|
|
newAccounts.map((a) => a.address)
|
|
);
|
|
}
|
|
accountsModal.value = false;
|
|
loading.value = false;
|
|
};
|
|
|
|
const changeSelectedNetwork = async (chainId: number) => {
|
|
loading.value = true;
|
|
if (chainId in networks.value) {
|
|
await saveSelectedNetwork(networks.value[chainId]);
|
|
await replaceNetworks(
|
|
Object.assign({ [chainId]: networks.value[chainId] }, networks.value)
|
|
);
|
|
selectedNetwork.value = networks.value[chainId];
|
|
triggerListner("chainChanged", numToHexStr(chainId));
|
|
}
|
|
networksModal.value = false;
|
|
loading.value = false;
|
|
};
|
|
|
|
return {
|
|
loading,
|
|
accounts,
|
|
networks,
|
|
accountsModal,
|
|
goToAddAccount,
|
|
goToAddNetwork,
|
|
selectedAccount,
|
|
selectedNetwork,
|
|
changeSelectedAccount,
|
|
changeSelectedNetwork,
|
|
copyAddress,
|
|
copyOutline,
|
|
toastState,
|
|
getToastRef,
|
|
networksModal,
|
|
mainNets,
|
|
getUrl,
|
|
openTab,
|
|
};
|
|
},
|
|
});
|
|
</script>
|