Skip to content

Commit

Permalink
Merge pull request #1 from ledanghuy1811/feat/support-owallet
Browse files Browse the repository at this point in the history
Feat/support-owallet
  • Loading branch information
quangdz1704 authored Jul 31, 2024
2 parents 7e26258 + b2867bb commit 5cd2788
Show file tree
Hide file tree
Showing 3 changed files with 293 additions and 82 deletions.
128 changes: 94 additions & 34 deletions lib/components/ConnectWallet/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ const sending = ref(false);
const open = ref(false);
const error = ref('');
const name = ref(WalletName.Keplr);
const name = ref(WalletName.Owallet);
const list = [
{
wallet: WalletName.Owallet,
logo: 'https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/6d/cf/9c/6dcf9c8f-45d9-37a4-d5c3-0da8d4af0650/AppIcon-0-0-1x_U007emarketing-0-6-0-85-220.png/460x0w.webp',
},
{
wallet: WalletName.Keplr,
logo: 'https://ping.pub/logos/keplr-logo.svg',
Expand All @@ -40,21 +44,22 @@ const list = [
{
wallet: WalletName.Metamask,
logo: 'https://ping.pub/logos/metamask.png',
}
},
];
async function initData() { }
async function initData() {}
const walletList = computed(() => {
// const l = list
return list
})
return list;
});
const connected = ref(readWallet(props.hdPath) as ConnectedWallet);
function selectWallet(wallet: WalletName) {
name.value = wallet;
}
async function connect() {
sending.value = true;
error.value = '';
Expand Down Expand Up @@ -91,15 +96,16 @@ async function connect() {
}
sending.value = false;
}
function disconnect() {
removeWallet(props.hdPath);
emit('disconnect', { value: connected.value });
connected.value = {} as ConnectedWallet;
}
function keplr() {
emit('keplr-config', {})
open.value = false
emit('keplr-config', {});
open.value = false;
}
let showCopyToast = ref(0);
Expand All @@ -124,29 +130,43 @@ const tipMsg = computed(() => {
: { class: 'success', msg: 'Copy Success!' };
});
const customKeplr = computed(() => {
return `${location.protocol}//${location.host}/wallet/keplr?chain=${props.chainId}`
})
return `${location.protocol}//${location.host}/wallet/keplr?chain=${props.chainId}`;
});
</script>

<template>
<div class="mb-4">
<!-- modal btn -->
<div v-if="connected.cosmosAddress" class="dropdown dropdown-hover ping-connect-dropdown">
<label tabindex="0" class="btn btn-sm m-1 lowercase">{{ connected.wallet }}-{{
connected.cosmosAddress?.substring(
connected.cosmosAddress?.length - 4
)
}}</label>
<div tabindex="0" class="dropdown-content menu shadow p-2 bg-base-100 rounded w-64 overflow-auto">
<div class="px-2 mb-1 text-gray-500 dark:text-gray-400 font-semibold flex justify-between">
<div
v-if="connected.cosmosAddress"
class="dropdown dropdown-hover ping-connect-dropdown"
>
<label tabindex="0" class="btn btn-sm m-1 lowercase"
>{{ connected.wallet }}-{{
connected.cosmosAddress?.substring(
connected.cosmosAddress?.length - 4
)
}}</label
>
<div
tabindex="0"
class="dropdown-content menu shadow p-2 bg-base-100 rounded w-64 overflow-auto"
>
<div
class="px-2 mb-1 text-gray-500 dark:text-gray-400 font-semibold flex justify-between"
>
<span class="text-lg"> {{ connected.wallet }} </span>
<span class="ml-2 text-xs mt-2">
{{ connected.hdPath }}
</span>
</div>
<div class="">
<div class="divider mt-1 mb-1"></div>
<a class="block py-2 px-2 hover:bg-gray-100 dark:hover:bg-[#353f5a] rounded cursor-pointer"
style="overflow-wrap: anywhere" @click="copyAdress(connected.cosmosAddress)">
<a
class="block py-2 px-2 hover:bg-gray-100 dark:hover:bg-[#353f5a] rounded cursor-pointer"
style="overflow-wrap: anywhere"
@click="copyAdress(connected.cosmosAddress)"
>
{{ connected.cosmosAddress }}
</a>
<!-- <div class="divider mt-1 mb-1"></div>
Expand All @@ -160,8 +180,11 @@ const customKeplr = computed(() => {
to="/wallet/portfolio"
>Portfolio</RouterLink
> -->
<a class="block py-2 px-2 hover:bg-gray-100 dark:hover:bg-[#353f5a] rounded cursor-pointer"
@click="disconnect()">Disconnect</a>
<a
class="block py-2 px-2 hover:bg-gray-100 dark:hover:bg-[#353f5a] rounded cursor-pointer"
@click="disconnect()"
>Disconnect</a
>
</div>
</div>
<div class="toast" v-show="showCopyToast === 1">
Expand All @@ -179,41 +202,78 @@ const customKeplr = computed(() => {
</div>
</div>
</div>
<label v-if="!connected.cosmosAddress" for="PingConnectWallet"
class="btn btn-sm ping-connect-btn capitalize">Connect Wallet</label>
<label
v-if="!connected.cosmosAddress"
for="PingConnectWallet"
class="btn btn-sm ping-connect-btn capitalize"
>Connect Wallet</label
>

<!-- modal content -->
<input v-model="open" type="checkbox" id="PingConnectWallet" class="modal-toggle" @change="initData()" />
<input
v-model="open"
type="checkbox"
id="PingConnectWallet"
class="modal-toggle"
@change="initData()"
/>

<label for="PingConnectWallet" class="modal cursor-pointer z-[999999]">
<label class="modal-box rounded-lg" for="">
<h3 class="text-xl font-semibold">Connect Wallet</h3>
<ul role="list" class="bg-gray-100 dark:bg-gray-900 rounded-lg mt-4 px-3 py-3">
<li class="flex items-center px-2 py-3 hover:bg-gray-200 dark:hover:bg-gray-800 rounded-lg cursor-pointer"
v-for="(i, k) of walletList" :key="k" @click="selectWallet(i.wallet)">
<img class="h-10 w-10 bg-gray-50 rounded-full mr-4" :src="i.logo" alt="" />
<p class="text-base font-semibold flex-1 dark:text-gray-300">
<ul
role="list"
class="bg-gray-100 dark:bg-gray-900 rounded-lg mt-4 px-3 py-3"
>
<li
class="flex items-center px-2 py-3 hover:bg-gray-200 dark:hover:bg-gray-800 rounded-lg cursor-pointer"
v-for="(i, k) of walletList"
:key="k"
@click="selectWallet(i.wallet)"
>
<img
class="h-10 w-10 bg-gray-50 rounded-full mr-4"
:src="i.logo"
alt=""
/>
<p
class="text-base font-semibold flex-1 dark:text-gray-300"
>
{{ i.wallet }}
</p>
<div>
<div v-if="i.wallet === name" class="mr-4 rounded-full bg-green-200">
<Icon icon="mdi:check" class="font-bold text-green-600" />
<div
v-if="i.wallet === name"
class="mr-4 rounded-full bg-green-200"
>
<Icon
icon="mdi:check"
class="font-bold text-green-600"
/>
</div>
</div>
</li>
</ul>
<div v-show="error" class="text-error mt-3">
<span>{{ error }}.</span>
<div v-show="String(error).search('no chain info') > -1">
<a :href="customKeplr" class="btn btn-link">Suggest a chain to Keplr</a>
<a :href="customKeplr" class="btn btn-link"
>Suggest a chain to Keplr</a
>
</div>
</div>
<div class="mt-8 text-right flex">
<label class="btn mr-1" @click="keplr">
<Icon icon="mdi:cog-outline" />
</label>
<label class="btn btn-primary ping-connect-confirm grow" @click="connect()">
<span v-if="sending" class="loading loading-spinner"></span>
<label
class="btn btn-primary ping-connect-confirm grow"
@click="connect()"
>
<span
v-if="sending"
class="loading loading-spinner"
></span>
Connect
</label>
</div>
Expand Down
106 changes: 58 additions & 48 deletions lib/wallet/Wallet.ts
Original file line number Diff line number Diff line change
@@ -1,105 +1,115 @@
import { Registry } from '@cosmjs/proto-signing'
import { defaultRegistryTypes } from "@cosmjs/stargate";
import { Transaction } from "../utils/type";
import { Registry } from '@cosmjs/proto-signing';
import { defaultRegistryTypes } from '@cosmjs/stargate';
import { Transaction } from '../utils/type';
import { KeplerWallet } from './wallets/KeplerWallet';
import { LedgerWallet } from './wallets/LedgerWallet';
import { MetamaskWallet } from './wallets/MetamaskWallet';
import { MetamaskSnapWallet } from './wallets/MetamaskSnapWallet';
import { LeapWallet } from './wallets/LeapWallet';
import { Owallet } from './wallets/Owallet';

export enum WalletName {
Keplr = "Keplr",
Ledger = "LedgerUSB",
LedgerBLE = "LedgerBLE",
Metamask = "Metamask",
MetamaskSnap = "MetamaskSnap",
Leap = "Leap",
Owallet = 'Owallet',
Keplr = 'Keplr',
Ledger = 'LedgerUSB',
LedgerBLE = 'LedgerBLE',
Metamask = 'Metamask',
MetamaskSnap = 'MetamaskSnap',
Leap = 'Leap',
// None Signning
Address = "Address",
NameService = "Nameservice",
Address = 'Address',
NameService = 'Nameservice',
}

export interface ConnectedWallet {
wallet: WalletName,
cosmosAddress: string
hdPath?: string
wallet: WalletName;
cosmosAddress: string;
hdPath?: string;
}

export interface Account {
address: string,
algo: string,
pubkey: Uint8Array,
address: string;
algo: string;
pubkey: Uint8Array;
}

export interface WalletArgument {
chainId?: string,
hdPath?: string,
address?: string,
name?: string,
transport?: string
prefix?: string,
chainId?: string;
hdPath?: string;
address?: string;
name?: string;
transport?: string;
prefix?: string;
}

export interface AbstractWallet {
name: WalletName
name: WalletName;
/**
* The the accounts from the wallet (addresses)
*/
getAccounts(): Promise<Account[]>
supportCoinType(coinType?: string): Promise<boolean>
sign(transaction: Transaction): Promise<any>
getAccounts(): Promise<Account[]>;
supportCoinType(coinType?: string): Promise<boolean>;
sign(transaction: Transaction): Promise<any>;
}

export const DEFAULT_HDPATH = "m/44'/118/0'/0/0";

export function keyType(chainId: string) {
switch (true) {
case chainId.search(/\w+_\d+-\d+/g) > -1: // ethermint like chain: evmos_9002-1
return "/ethermint.crypto.v1.ethsecp256k1.PubKey"
case chainId.startsWith("injective"):
return "/injective.crypto.v1beta1.ethsecp256k1.PubKey";
case chainId.search(/\w+_\d+-\d+/g) > -1: // ethermint like chain: evmos_9002-1
return '/ethermint.crypto.v1.ethsecp256k1.PubKey';
case chainId.startsWith('injective'):
return '/injective.crypto.v1beta1.ethsecp256k1.PubKey';
default:
return "/cosmos.crypto.secp256k1.PubKey"
return '/cosmos.crypto.secp256k1.PubKey';
}
}

export function readWallet(hdPath?: string) {
return JSON.parse(
localStorage.getItem(hdPath || DEFAULT_HDPATH) || '{}'
) as ConnectedWallet
) as ConnectedWallet;
}
export function writeWallet(connected: ConnectedWallet, hdPath?: string) {
localStorage.setItem(hdPath || DEFAULT_HDPATH, JSON.stringify(connected))
localStorage.setItem(hdPath || DEFAULT_HDPATH, JSON.stringify(connected));
}

export function removeWallet(hdPath?: string) {
localStorage.removeItem(hdPath || DEFAULT_HDPATH);
}

export function extractChainId(chainId: string) {
const start = chainId.indexOf('_')
const end = chainId.indexOf('-')
const start = chainId.indexOf('_');
const end = chainId.indexOf('-');
if (end > start && start > 0) {
return Number(chainId.substring(start + 1, end))
return Number(chainId.substring(start + 1, end));
}
return 0
return 0;
}

export function createWallet(name: WalletName, arg: WalletArgument, registry?: Registry): AbstractWallet {
const reg = registry || new Registry(defaultRegistryTypes)
export function createWallet(
name: WalletName,
arg: WalletArgument,
registry?: Registry
): AbstractWallet {
const reg = registry || new Registry(defaultRegistryTypes);
switch (name) {
case WalletName.Owallet:
return new Owallet(arg, reg);
case WalletName.Keplr:
return new KeplerWallet(arg, reg)
return new KeplerWallet(arg, reg);
case WalletName.Ledger:
return new LedgerWallet(arg, reg)
return new LedgerWallet(arg, reg);
case WalletName.Leap:
return new LeapWallet(arg, reg)
return new LeapWallet(arg, reg);
case WalletName.MetamaskSnap:
return new MetamaskSnapWallet(arg, reg)
return new MetamaskSnapWallet(arg, reg);
case WalletName.Metamask:
return arg.hdPath &&
(arg.hdPath.startsWith('m/44/60') || arg.hdPath.startsWith("m/44'/60"))
? new MetamaskWallet(arg, reg) : new MetamaskSnapWallet(arg, reg)
return arg.hdPath &&
(arg.hdPath.startsWith('m/44/60') ||
arg.hdPath.startsWith("m/44'/60"))
? new MetamaskWallet(arg, reg)
: new MetamaskSnapWallet(arg, reg);
}
throw new Error("No wallet connected")
throw new Error('No wallet connected');
}
Loading

0 comments on commit 5cd2788

Please sign in to comment.