diff --git a/wallets/react-wallet-v2/public/icons/arrow-down-icon.svg b/wallets/react-wallet-v2/public/icons/arrow-down-icon.svg
new file mode 100644
index 0000000..362c3cb
--- /dev/null
+++ b/wallets/react-wallet-v2/public/icons/arrow-down-icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/wallets/react-wallet-v2/public/main.css b/wallets/react-wallet-v2/public/main.css
index 530451c..290a260 100644
--- a/wallets/react-wallet-v2/public/main.css
+++ b/wallets/react-wallet-v2/public/main.css
@@ -57,4 +57,25 @@
.navLink:hover {
opacity: 0.6;
+}
+
+select {
+ background-color: rgba(139, 139, 139, 0.2);
+ background-image: url(/icons/arrow-down-icon.svg);
+ background-size: 15px 15px;
+ background-position: right 10px center;
+ background-repeat: no-repeat;
+ padding: 5px 30px 6px 10px;
+ border-radius: 10px;
+ cursor: pointer;
+ border: none;
+ appearance: none;
+ transition: .2s ease-in-out background-color;
+ font-family: var(--nextui-fonts-sans);
+ font-weight: var(--nextui-fontWeights-light);
+ border: 1px solid rgba(139, 139, 139, 0.25);
+}
+
+select:hover {
+ background-color: rgba(139, 139, 139, 0.35);
}
\ No newline at end of file
diff --git a/wallets/react-wallet-v2/src/components/AccountPicker.tsx b/wallets/react-wallet-v2/src/components/AccountPicker.tsx
new file mode 100644
index 0000000..1c0db84
--- /dev/null
+++ b/wallets/react-wallet-v2/src/components/AccountPicker.tsx
@@ -0,0 +1,18 @@
+import SettingsStore from '@/store/SettingsStore'
+import { addresses } from '@/utils/WalletUtil'
+import { useSnapshot } from 'valtio'
+
+export default function AccountPicker() {
+ const { address } = useSnapshot(SettingsStore.state)
+
+ return (
+
+ )
+}
diff --git a/wallets/react-wallet-v2/src/components/PageHeader.tsx b/wallets/react-wallet-v2/src/components/PageHeader.tsx
index f05420a..e365d76 100644
--- a/wallets/react-wallet-v2/src/components/PageHeader.tsx
+++ b/wallets/react-wallet-v2/src/components/PageHeader.tsx
@@ -1,29 +1,35 @@
-import { Divider, Text } from '@nextui-org/react'
-import { Fragment } from 'react'
+import { Col, Divider, Row, Text } from '@nextui-org/react'
+import { Fragment, ReactNode } from 'react'
/**
* Types
*/
interface Props {
- children: string
+ children?: ReactNode | ReactNode[]
+ title: string
}
/**
* Component
*/
-export default function PageHeader({ children }: Props) {
+export default function PageHeader({ title, children }: Props) {
return (
-
- {children}
-
+
+
+
+ {title}
+
+
+ {children ? {children} : null}
+
+
)
diff --git a/wallets/react-wallet-v2/src/hooks/useInitialization.ts b/wallets/react-wallet-v2/src/hooks/useInitialization.ts
index 56cf271..5b97ad6 100644
--- a/wallets/react-wallet-v2/src/hooks/useInitialization.ts
+++ b/wallets/react-wallet-v2/src/hooks/useInitialization.ts
@@ -1,3 +1,4 @@
+import SettingsStore from '@/store/SettingsStore'
import { createWalletConnectClient } from '@/utils/WalletConnectUtil'
import { createOrRestoreWallet } from '@/utils/WalletUtil'
import { useCallback, useEffect, useState } from 'react'
@@ -7,7 +8,8 @@ export default function useInitialization() {
const onInitialize = useCallback(async () => {
try {
- createOrRestoreWallet()
+ const { addresses } = createOrRestoreWallet()
+ SettingsStore.setAddress(addresses[0])
await createWalletConnectClient()
setInitialized(true)
} catch (err: unknown) {
diff --git a/wallets/react-wallet-v2/src/pages/index.tsx b/wallets/react-wallet-v2/src/pages/index.tsx
index 5946476..feae016 100644
--- a/wallets/react-wallet-v2/src/pages/index.tsx
+++ b/wallets/react-wallet-v2/src/pages/index.tsx
@@ -1,23 +1,25 @@
import AccountCard from '@/components/AccountCard'
+import AccountPicker from '@/components/AccountPicker'
import PageHeader from '@/components/PageHeader'
import { EIP155_MAINNET_CHAINS, EIP155_TEST_CHAINS } from '@/data/EIP155Data'
import SettingsStore from '@/store/SettingsStore'
-import { wallet } from '@/utils/WalletUtil'
import { Text } from '@nextui-org/react'
import { Fragment } from 'react'
import { useSnapshot } from 'valtio'
export default function HomePage() {
- const { testNets } = useSnapshot(SettingsStore.state)
+ const { testNets, address } = useSnapshot(SettingsStore.state)
return (
- Accounts
+
+
+
Mainnets
{Object.values(EIP155_MAINNET_CHAINS).map(({ name, logo, rgb }) => (
-
+
))}
{testNets ? (
@@ -26,7 +28,7 @@ export default function HomePage() {
Testnets
{Object.values(EIP155_TEST_CHAINS).map(({ name, logo, rgb }) => (
-
+
))}
) : null}
diff --git a/wallets/react-wallet-v2/src/pages/pairings.tsx b/wallets/react-wallet-v2/src/pages/pairings.tsx
index 5e2e2ad..b6439dc 100644
--- a/wallets/react-wallet-v2/src/pages/pairings.tsx
+++ b/wallets/react-wallet-v2/src/pages/pairings.tsx
@@ -19,7 +19,7 @@ export default function PairingsPage() {
return (
- Pairings
+
{pairings.length ? (
pairings.map(pairing => {
const { metadata } = pairing.state
diff --git a/wallets/react-wallet-v2/src/pages/sessions.tsx b/wallets/react-wallet-v2/src/pages/sessions.tsx
index e240884..951a107 100644
--- a/wallets/react-wallet-v2/src/pages/sessions.tsx
+++ b/wallets/react-wallet-v2/src/pages/sessions.tsx
@@ -19,7 +19,7 @@ export default function SessionsPage() {
return (
- Sessions
+
{sessions.length ? (
sessions.map(session => {
const { name, icons, url } = session.peer.metadata
diff --git a/wallets/react-wallet-v2/src/pages/settings.tsx b/wallets/react-wallet-v2/src/pages/settings.tsx
index 0c170a5..3964abe 100644
--- a/wallets/react-wallet-v2/src/pages/settings.tsx
+++ b/wallets/react-wallet-v2/src/pages/settings.tsx
@@ -1,21 +1,21 @@
import PageHeader from '@/components/PageHeader'
import SettingsStore from '@/store/SettingsStore'
-import { wallet } from '@/utils/WalletUtil'
+import { wallets } from '@/utils/WalletUtil'
import { Card, Divider, Row, Switch, Text } from '@nextui-org/react'
import { Fragment } from 'react'
import { useSnapshot } from 'valtio'
export default function SettingsPage() {
- const { testNets } = useSnapshot(SettingsStore.state)
+ const { testNets, address } = useSnapshot(SettingsStore.state)
return (
- Settings
+
Mnemonic
- {wallet.mnemonic.phrase}
+ {wallets[address].mnemonic.phrase}
diff --git a/wallets/react-wallet-v2/src/pages/walletconnect.tsx b/wallets/react-wallet-v2/src/pages/walletconnect.tsx
index 8486c3c..5585960 100644
--- a/wallets/react-wallet-v2/src/pages/walletconnect.tsx
+++ b/wallets/react-wallet-v2/src/pages/walletconnect.tsx
@@ -22,7 +22,7 @@ export default function WalletConnectPage() {
return (
- WalletConnect
+
diff --git a/wallets/react-wallet-v2/src/store/SettingsStore.ts b/wallets/react-wallet-v2/src/store/SettingsStore.ts
index 6d9d508..e50eafe 100644
--- a/wallets/react-wallet-v2/src/store/SettingsStore.ts
+++ b/wallets/react-wallet-v2/src/store/SettingsStore.ts
@@ -5,13 +5,15 @@ import { proxy } from 'valtio'
*/
interface State {
testNets: boolean
+ address: string
}
/**
* State
*/
const state = proxy({
- testNets: typeof localStorage !== 'undefined' ? Boolean(localStorage.getItem('TEST_NETS')) : true
+ testNets: typeof localStorage !== 'undefined' ? Boolean(localStorage.getItem('TEST_NETS')) : true,
+ address: ''
})
/**
@@ -20,6 +22,10 @@ const state = proxy({
const SettingsStore = {
state,
+ setAddress(address: string) {
+ state.address = address
+ },
+
toggleTestNets() {
state.testNets = !state.testNets
if (state.testNets) {
diff --git a/wallets/react-wallet-v2/src/utils/HelperUtil.ts b/wallets/react-wallet-v2/src/utils/HelperUtil.ts
index 86ea4b9..9ddf3da 100644
--- a/wallets/react-wallet-v2/src/utils/HelperUtil.ts
+++ b/wallets/react-wallet-v2/src/utils/HelperUtil.ts
@@ -52,3 +52,20 @@ export function getSignTypedDataParamsData(params: string[]) {
return data
}
+
+/**
+ * Get our address from params checking if params string contains one
+ * of our wallet addresses
+ */
+export function getWalletAddressFromParams(addresses: string[], params: any) {
+ const paramsString = JSON.stringify(params)
+ let address = ''
+
+ addresses.forEach(addr => {
+ if (paramsString.includes(addr)) {
+ address = addr
+ }
+ })
+
+ return address
+}
diff --git a/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts b/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
index e140a85..b9e9acb 100644
--- a/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
+++ b/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
@@ -1,12 +1,19 @@
-import { EIP155_SIGNING_METHODS } from '@/data/EIP155Data'
-import { getSignParamsMessage, getSignTypedDataParamsData } from '@/utils/HelperUtil'
+import { EIP155_CHAINS, EIP155_SIGNING_METHODS, TEIP155Chain } from '@/data/EIP155Data'
+import {
+ getSignParamsMessage,
+ getSignTypedDataParamsData,
+ getWalletAddressFromParams
+} from '@/utils/HelperUtil'
+import { addresses, wallets } from '@/utils/WalletUtil'
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
import { RequestEvent } from '@walletconnect/types'
import { ERROR } from '@walletconnect/utils'
-import { Wallet } from 'ethers'
+import { providers } from 'ethers'
-export async function approveEIP155Request(request: RequestEvent['request'], wallet: Wallet) {
- const { method, params, id } = request
+export async function approveEIP155Request(requestEvent: RequestEvent) {
+ const { method, params, id } = requestEvent.request
+ const { chainId } = requestEvent
+ const wallet = wallets[getWalletAddressFromParams(addresses, params)]
switch (method) {
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
@@ -25,8 +32,10 @@ export async function approveEIP155Request(request: RequestEvent['request'], wal
return formatJsonRpcResult(id, signedData)
case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION:
+ const provider = new providers.JsonRpcProvider(EIP155_CHAINS[chainId as TEIP155Chain].rpc)
const sendTransaction = params[0]
- const { hash } = await wallet.sendTransaction(sendTransaction)
+ const connectedWallet = wallet.connect(provider)
+ const { hash } = await connectedWallet.sendTransaction(sendTransaction)
return formatJsonRpcResult(id, hash)
case EIP155_SIGNING_METHODS.ETH_SIGN_TRANSACTION:
diff --git a/wallets/react-wallet-v2/src/utils/WalletUtil.ts b/wallets/react-wallet-v2/src/utils/WalletUtil.ts
index be73ad6..67e771c 100644
--- a/wallets/react-wallet-v2/src/utils/WalletUtil.ts
+++ b/wallets/react-wallet-v2/src/utils/WalletUtil.ts
@@ -1,15 +1,31 @@
import { Wallet } from 'ethers'
-export let wallet: Wallet
+export let wallets: Record
+export let addresses: string[]
+export let wallet1: Wallet
+export let wallet2: Wallet
export function createOrRestoreWallet() {
const mnemonic = localStorage.getItem('WALLET_MNEMONIC')
if (mnemonic) {
- wallet = Wallet.fromMnemonic(mnemonic)
+ wallet1 = Wallet.fromMnemonic(mnemonic, "m/44'/60'/0'/0/0")
+ wallet2 = Wallet.fromMnemonic(mnemonic, "m/44'/60'/0'/0/1")
} else {
- wallet = Wallet.createRandom()
+ wallet1 = Wallet.createRandom()
+ wallet2 = Wallet.fromMnemonic(wallet1.mnemonic.phrase, "m/44'/60'/0'/0/1")
// Don't store mnemonic in local storage in a production project!
- localStorage.setItem('WALLET_MNEMONIC', wallet.mnemonic.phrase)
+ localStorage.setItem('WALLET_MNEMONIC', wallet1.mnemonic.phrase)
+ }
+
+ wallets = {
+ [wallet1.address]: wallet1,
+ [wallet2.address]: wallet2
+ }
+ addresses = Object.keys(wallets)
+
+ return {
+ wallets,
+ addresses
}
}
diff --git a/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx b/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
index 2f9e13e..cd286e3 100644
--- a/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
+++ b/wallets/react-wallet-v2/src/views/SessionProposalModal.tsx
@@ -1,11 +1,25 @@
import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data'
import ModalStore from '@/store/ModalStore'
+import { truncate } from '@/utils/HelperUtil'
import { walletConnectClient } from '@/utils/WalletConnectUtil'
-import { wallet } from '@/utils/WalletUtil'
-import { Avatar, Button, Col, Container, Divider, Link, Modal, Row, Text } from '@nextui-org/react'
-import { Fragment } from 'react'
+import { addresses } from '@/utils/WalletUtil'
+import {
+ Avatar,
+ Button,
+ Card,
+ Col,
+ Container,
+ Divider,
+ Link,
+ Modal,
+ Row,
+ Text
+} from '@nextui-org/react'
+import { Fragment, useState } from 'react'
export default function SessionProposalModal() {
+ const [selectedAddresses, setSelectedAddresses] = useState([])
+
// Get proposal data and wallet address from store
const proposal = ModalStore.state.data?.proposal
@@ -21,12 +35,29 @@ export default function SessionProposalModal() {
const { methods } = permissions.jsonrpc
const { protocol } = relay
+ // Add / remove address from selection
+ function onSelectAddress(address: string) {
+ if (selectedAddresses.includes(address)) {
+ const newAddresses = selectedAddresses.filter(a => a !== address)
+ setSelectedAddresses(newAddresses)
+ } else {
+ setSelectedAddresses([...selectedAddresses, address])
+ }
+ }
+
// Hanlde approve action
async function onApprove() {
if (proposal) {
+ const accounts: string[] = []
+ chains.forEach(chain => {
+ selectedAddresses.forEach(address => {
+ accounts.push(`${chain}:${address}`)
+ })
+ })
+
const response = {
state: {
- accounts: chains.map(chain => `${chain}:${wallet.address}`)
+ accounts
}
}
await walletConnectClient.approve({ proposal, response })
@@ -90,6 +121,27 @@ export default function SessionProposalModal() {
{protocol}
+
+
+
+
+
+ Select Accounts to Connect
+ {addresses.map((address, index) => (
+ onSelectAddress(address)}
+ clickable
+ key={address}
+ css={{
+ marginTop: '$5',
+ backgroundColor: selectedAddresses.includes(address) ? '$green600' : '$accents2'
+ }}
+ >
+ {`Acc ${index + 1} - ${truncate(address, 19)}`}
+
+ ))}
+
+
@@ -97,7 +149,14 @@ export default function SessionProposalModal() {
-