diff --git a/wallets/react-wallet-v2/package.json b/wallets/react-wallet-v2/package.json
index 796627c..2ed88a1 100644
--- a/wallets/react-wallet-v2/package.json
+++ b/wallets/react-wallet-v2/package.json
@@ -25,7 +25,7 @@
},
"devDependencies": {
"@walletconnect/types": "2.0.0-beta.22",
- "@types/node": "17.0.17",
+ "@types/node": "17.0.18",
"@types/react": "17.0.39",
"eslint": "8.9.0",
"eslint-config-next": "12.0.10",
diff --git a/wallets/react-wallet-v2/public/main.css b/wallets/react-wallet-v2/public/main.css
index d862414..530451c 100644
--- a/wallets/react-wallet-v2/public/main.css
+++ b/wallets/react-wallet-v2/public/main.css
@@ -49,4 +49,12 @@
.codeBlock span {
background-color: transparent !important;
overflow: scroll;
+}
+
+.navLink {
+ transition: ease-in-out .2s opacity;
+}
+
+.navLink:hover {
+ opacity: 0.6;
}
\ No newline at end of file
diff --git a/wallets/react-wallet-v2/public/pairings-icon.svg b/wallets/react-wallet-v2/public/pairings-icon.svg
new file mode 100644
index 0000000..05d38a8
--- /dev/null
+++ b/wallets/react-wallet-v2/public/pairings-icon.svg
@@ -0,0 +1,59 @@
+
diff --git a/wallets/react-wallet-v2/public/sessions-icon.svg b/wallets/react-wallet-v2/public/sessions-icon.svg
new file mode 100644
index 0000000..0b74731
--- /dev/null
+++ b/wallets/react-wallet-v2/public/sessions-icon.svg
@@ -0,0 +1,19 @@
+
diff --git a/wallets/react-wallet-v2/src/components/AccountCard.tsx b/wallets/react-wallet-v2/src/components/AccountCard.tsx
index fb6ff69..0350aff 100644
--- a/wallets/react-wallet-v2/src/components/AccountCard.tsx
+++ b/wallets/react-wallet-v2/src/components/AccountCard.tsx
@@ -1,6 +1,5 @@
import { truncate } from '@/utils/HelperUtil'
import { Avatar, Card, Text } from '@nextui-org/react'
-import Link from 'next/link'
interface Props {
name: string
@@ -11,38 +10,35 @@ interface Props {
export default function AccountCard({ name, logo, rgb, address }: Props) {
return (
-
-
+
-
-
-
-
- {name}
-
-
- {truncate(address, 19)}
-
-
-
-
-
+
+
+
+ {name}
+
+
+ {truncate(address, 19)}
+
+
+
+
)
}
diff --git a/wallets/react-wallet-v2/src/components/Modal.tsx b/wallets/react-wallet-v2/src/components/Modal.tsx
index 4f66a34..cf7ee66 100644
--- a/wallets/react-wallet-v2/src/components/Modal.tsx
+++ b/wallets/react-wallet-v2/src/components/Modal.tsx
@@ -1,5 +1,6 @@
import ModalStore from '@/store/ModalStore'
import SessionProposalModal from '@/views/SessionProposalModal'
+import SessionSendTransactionModal from '@/views/SessionSendTransactionModal'
import SessionRequestModal from '@/views/SessionSignModal'
import SessionSignTypedDataModal from '@/views/SessionSignTypedDataModal'
import { Modal as NextModal } from '@nextui-org/react'
@@ -13,6 +14,7 @@ export default function Modal() {
{view === 'SessionProposalModal' && }
{view === 'SessionSignModal' && }
{view === 'SessionSignTypedDataModal' && }
+ {view === 'SessionSendTransactionModal' && }
)
}
diff --git a/wallets/react-wallet-v2/src/components/Navigation.tsx b/wallets/react-wallet-v2/src/components/Navigation.tsx
index 1802690..344db92 100644
--- a/wallets/react-wallet-v2/src/components/Navigation.tsx
+++ b/wallets/react-wallet-v2/src/components/Navigation.tsx
@@ -4,15 +4,21 @@ import Link from 'next/link'
export default function Navigation() {
return (
-
+
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
-
-
+
+
diff --git a/wallets/react-wallet-v2/src/data/EIP155Data.ts b/wallets/react-wallet-v2/src/data/EIP155Data.ts
index 7e7a730..58f55cf 100644
--- a/wallets/react-wallet-v2/src/data/EIP155Data.ts
+++ b/wallets/react-wallet-v2/src/data/EIP155Data.ts
@@ -21,52 +21,32 @@ export const EIP155_MAINNET_CHAINS = {
chainId: 1,
name: 'Ethereum',
logo: LOGO_BASE_URL + 'eip155:1.png',
- rgb: '99, 125, 234'
- },
- 'eip155:10': {
- chainId: 10,
- name: 'Optimism',
- logo: LOGO_BASE_URL + 'eip155:10.png',
- rgb: '233, 1, 1'
+ rgb: '99, 125, 234',
+ rpc: 'https://cloudflare-eth.com/'
},
'eip155:137': {
chainId: 137,
name: 'Polygon',
logo: LOGO_BASE_URL + 'eip155:137.png',
- rgb: '130, 71, 229'
+ rgb: '130, 71, 229',
+ rpc: 'https://polygon-rpc.com/'
},
'eip155:42161': {
chainId: 42161,
name: 'Arbitrum',
logo: LOGO_BASE_URL + 'eip155:42161.png',
- rgb: '44, 55, 75'
+ rgb: '44, 55, 75',
+ rpc: 'https://arb1.arbitrum.io/rpc/'
}
}
export const EIP155_TEST_CHAINS = {
- 'eip155:4': {
- chainId: 4,
- name: 'Ethereum Rinkeby',
- logo: LOGO_BASE_URL + 'eip155:1.png',
- rgb: '99, 125, 234'
- },
- 'eip155:69': {
- chainId: 69,
- name: 'Optimism Kovan',
- logo: LOGO_BASE_URL + 'eip155:10.png',
- rgb: '233, 1, 1'
- },
'eip155:80001': {
chainId: 80001,
name: 'Polygon Mumbai',
logo: LOGO_BASE_URL + 'eip155:137.png',
- rgb: '130, 71, 229'
- },
- 'eip155:421611': {
- chainId: 421611,
- name: 'Arbitrum Rinkeby',
- logo: LOGO_BASE_URL + 'eip155:42161.png',
- rgb: '44, 55, 75'
+ rgb: '130, 71, 229',
+ rpc: 'https://rpc-mumbai.maticvigil.com/'
}
}
diff --git a/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts b/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
index e1cd614..b182de4 100644
--- a/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
+++ b/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts
@@ -6,26 +6,30 @@ import { SessionTypes } from '@walletconnect/types'
import { useCallback, useEffect } from 'react'
export default function useWalletConnectEventsManager(initialized: boolean) {
- // 1. Open session proposal modal for confirmation / rejection
+ /******************************************************************************
+ * 1. Open session proposal modal for confirmation / rejection
+ *****************************************************************************/
const onSessionProposal = useCallback((proposal: SessionTypes.Proposal) => {
ModalStore.open('SessionProposalModal', { proposal })
}, [])
- // 2. Open session created modal to show success feedback
+ /******************************************************************************
+ * 2. Open session created modal to show success feedback
+ *****************************************************************************/
const onSessionCreated = useCallback((created: SessionTypes.Created) => {}, [])
- // 3. Open request handling modal based on method that was used
+ /******************************************************************************
+ * 3. Open request handling modal based on method that was used
+ *****************************************************************************/
const onSessionRequest = useCallback(async (requestEvent: SessionTypes.RequestEvent) => {
const { topic, request } = requestEvent
const { method } = request
const requestSession = await walletConnectClient.session.get(topic)
- // Hanle message signing requests of various formats
if ([EIP155_SIGNING_METHODS.ETH_SIGN, EIP155_SIGNING_METHODS.PERSONAL_SIGN].includes(method)) {
ModalStore.open('SessionSignModal', { requestEvent, requestSession })
}
- // Hanle data signing requests of various formats
if (
[
EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA,
@@ -35,8 +39,15 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
) {
ModalStore.open('SessionSignTypedDataModal', { requestEvent, requestSession })
}
+
+ if (EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION) {
+ ModalStore.open('SessionSendTransactionModal', { requestEvent, requestSession })
+ }
}, [])
+ /******************************************************************************
+ * Set up WalletConnect event listeners
+ *****************************************************************************/
useEffect(() => {
if (initialized) {
walletConnectClient.on(CLIENT_EVENTS.session.proposal, onSessionProposal)
diff --git a/wallets/react-wallet-v2/src/pages/pairings.tsx b/wallets/react-wallet-v2/src/pages/pairings.tsx
new file mode 100644
index 0000000..933c433
--- /dev/null
+++ b/wallets/react-wallet-v2/src/pages/pairings.tsx
@@ -0,0 +1,14 @@
+import PageHeader from '@/components/PageHeader'
+import { walletConnectClient } from '@/utils/WalletConnectUtil'
+import { Fragment } from 'react'
+
+export default function PairingsPage() {
+ console.log(walletConnectClient.session.values)
+ console.log(walletConnectClient.session.history.pending)
+
+ return (
+
+ Pairings
+
+ )
+}
diff --git a/wallets/react-wallet-v2/src/pages/sessions.tsx b/wallets/react-wallet-v2/src/pages/sessions.tsx
index 5b0e968..2e6b6b5 100644
--- a/wallets/react-wallet-v2/src/pages/sessions.tsx
+++ b/wallets/react-wallet-v2/src/pages/sessions.tsx
@@ -1,20 +1,14 @@
import PageHeader from '@/components/PageHeader'
-import { truncate } from '@/utils/HelperUtil'
import { walletConnectClient } from '@/utils/WalletConnectUtil'
-import { useRouter } from 'next/router'
-import { Fragment, useEffect } from 'react'
+import { Fragment } from 'react'
export default function SessionsPage() {
- const { query } = useRouter()
- const address = (query?.address as string) ?? 'Unknown'
-
- useEffect(() => {
- console.log(walletConnectClient.session.values)
- }, [])
+ console.log(walletConnectClient.session.values)
+ console.log(walletConnectClient.session.history.pending)
return (
- {truncate(address, 15)}
+ Sessions
)
}
diff --git a/wallets/react-wallet-v2/src/store/ModalStore.ts b/wallets/react-wallet-v2/src/store/ModalStore.ts
index 2fe913d..171553c 100644
--- a/wallets/react-wallet-v2/src/store/ModalStore.ts
+++ b/wallets/react-wallet-v2/src/store/ModalStore.ts
@@ -13,7 +13,11 @@ interface ModalData {
interface State {
open: boolean
- view?: 'SessionProposalModal' | 'SessionSignModal' | 'SessionSignTypedDataModal'
+ view?:
+ | 'SessionProposalModal'
+ | 'SessionSignModal'
+ | 'SessionSignTypedDataModal'
+ | 'SessionSendTransactionModal'
data?: ModalData
}
diff --git a/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts b/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
index 563b8a2..e428427 100644
--- a/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
+++ b/wallets/react-wallet-v2/src/utils/RequestHandlerUtil.ts
@@ -9,32 +9,26 @@ export async function approveEIP155Request(request: RequestEvent['request'], wal
const { method, params, id } = request
switch (method) {
- /**
- * Handle message signing requests
- */
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
case EIP155_SIGNING_METHODS.ETH_SIGN:
const message = getSignParamsMessage(params)
const signedMessage = await wallet.signMessage(message)
return formatJsonRpcResult(id, signedMessage)
- /**
- * Handle data signing requests
- */
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA:
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V3:
case EIP155_SIGNING_METHODS.ETH_SIGN_TYPED_DATA_V4:
const { domain, types, message: data } = getSignTypedDataParamsData(params)
-
// https://github.com/ethers-io/ethers.js/issues/687#issuecomment-714069471
delete types.EIP712Domain
-
const signedData = await wallet._signTypedData(domain, types, data)
return formatJsonRpcResult(id, signedData)
- /**
- * Handle unsuported methods
- */
+ case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION:
+ const transaction = params[0]
+ const { hash } = await wallet.sendTransaction(transaction)
+ return formatJsonRpcError(id, hash)
+
default:
throw new Error(ERROR.UNKNOWN_JSONRPC_METHOD.format().message)
}
diff --git a/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx b/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx
new file mode 100644
index 0000000..c288576
--- /dev/null
+++ b/wallets/react-wallet-v2/src/views/SessionSendTransactionModal.tsx
@@ -0,0 +1,182 @@
+import { EIP155_CHAINS, TEIP155Chain } from '@/data/EIP155Data'
+import ModalStore from '@/store/ModalStore'
+import { truncate } from '@/utils/HelperUtil'
+import { approveEIP155Request, rejectEIP155Request } from '@/utils/RequestHandlerUtil'
+import { walletConnectClient } from '@/utils/WalletConnectUtil'
+import { wallet } from '@/utils/WalletUtil'
+import {
+ Avatar,
+ Button,
+ Col,
+ Container,
+ Divider,
+ Link,
+ Loading,
+ Modal,
+ Row,
+ Text
+} from '@nextui-org/react'
+import { providers } from 'ethers'
+import { Fragment, useState } from 'react'
+
+export default function SessionSendTransactionModal() {
+ const [loading, setLoading] = useState(false)
+
+ // Get request and wallet data from store
+ const requestEvent = ModalStore.state.data?.requestEvent
+ const requestSession = ModalStore.state.data?.requestSession
+
+ // Ensure request and wallet are defined
+ if (!requestEvent || !requestSession) {
+ return Missing request data
+ }
+
+ // Get required proposal data
+ const { chainId } = requestEvent
+ const { method, params } = requestEvent.request
+ const { protocol } = requestSession.relay
+ const { name, icons, url } = requestSession.peer.metadata
+ const transaction = params[0]
+
+ console.log(transaction)
+
+ // Handle approve action
+ async function onApprove() {
+ if (requestEvent) {
+ setLoading(true)
+ const provider = new providers.JsonRpcProvider(EIP155_CHAINS[chainId as TEIP155Chain].rpc)
+ const connectedWallet = wallet.connect(provider)
+ const response = await approveEIP155Request(requestEvent.request, connectedWallet)
+ await walletConnectClient.respond({
+ topic: requestEvent.topic,
+ response
+ })
+ ModalStore.close()
+ }
+ }
+
+ // Handle reject action
+ async function onReject() {
+ if (requestEvent) {
+ const response = rejectEIP155Request(requestEvent.request)
+ await walletConnectClient.respond({
+ topic: requestEvent.topic,
+ response
+ })
+ ModalStore.close()
+ }
+ }
+
+ return (
+
+
+ Send Transaction
+
+
+
+
+
+
+
+
+
+ {name}
+ {url}
+
+
+
+
+
+
+
+ From
+ {truncate(transaction.from, 30)}
+
+
+
+
+
+
+
+ To
+ {truncate(transaction.to, 30)}
+
+
+
+
+
+
+
+ Value
+ {transaction.value}
+
+
+
+
+
+
+
+ Gas Price
+ {transaction.gasPrice}
+
+
+ Gas Limit
+ {transaction.gasLimit}
+
+
+
+
+
+
+
+ Nonce
+ {transaction.nonce}
+
+
+ Data
+ {transaction.data}
+
+
+
+
+
+
+
+ Blockchain
+
+ {EIP155_CHAINS[chainId as TEIP155Chain]?.name ?? chainId}
+
+
+
+
+
+
+
+
+ Method
+ {method}
+
+
+
+
+
+
+
+ Relay Protocol
+ {protocol}
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/wallets/react-wallet-v2/yarn.lock b/wallets/react-wallet-v2/yarn.lock
index db648e3..3ed644d 100644
--- a/wallets/react-wallet-v2/yarn.lock
+++ b/wallets/react-wallet-v2/yarn.lock
@@ -794,10 +794,10 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
-"@types/node@17.0.17":
- version "17.0.17"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.17.tgz#a8ddf6e0c2341718d74ee3dc413a13a042c45a0c"
- integrity sha512-e8PUNQy1HgJGV3iU/Bp2+D/DXh3PYeyli8LgIwsQcs1Ar1LoaWHSIT6Rw+H2rNJmiq6SNWiDytfx8+gYj7wDHw==
+"@types/node@17.0.18":
+ version "17.0.18"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.18.tgz#3b4fed5cfb58010e3a2be4b6e74615e4847f1074"
+ integrity sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==
"@types/prop-types@*":
version "15.7.4"