Save progress on solana transaction signing
This commit is contained in:
parent
518510ca1f
commit
8ba122d703
@ -20,6 +20,7 @@
|
||||
"react-qr-reader-es6": "2.2.1-2",
|
||||
"framer-motion": "6.2.8",
|
||||
"ethers": "5.6.0",
|
||||
"bs58": "5.0.0",
|
||||
"valtio": "1.3.1",
|
||||
"react-code-blocks": "0.0.9-0",
|
||||
"@cosmjs/proto-signing": "0.27.1",
|
||||
|
@ -3,6 +3,7 @@ import SessionProposalModal from '@/views/SessionProposalModal'
|
||||
import SessionSendTransactionModal from '@/views/SessionSendTransactionModal'
|
||||
import SessionSignCosmosModal from '@/views/SessionSignCosmosModal'
|
||||
import SessionRequestModal from '@/views/SessionSignModal'
|
||||
import SessionSignSolanaModal from '@/views/SessionSignSolanaModal'
|
||||
import SessionSignTypedDataModal from '@/views/SessionSignTypedDataModal'
|
||||
import SessionUnsuportedMethodModal from '@/views/SessionUnsuportedMethodModal'
|
||||
import { Modal as NextModal } from '@nextui-org/react'
|
||||
@ -19,6 +20,7 @@ export default function Modal() {
|
||||
{view === 'SessionSendTransactionModal' && <SessionSendTransactionModal />}
|
||||
{view === 'SessionUnsuportedMethodModal' && <SessionUnsuportedMethodModal />}
|
||||
{view === 'SessionSignCosmosModal' && <SessionSignCosmosModal />}
|
||||
{view === 'SessionSignSolanaModal' && <SessionSignSolanaModal />}
|
||||
</NextModal>
|
||||
)
|
||||
}
|
||||
|
@ -32,6 +32,6 @@ export const SOLANA_CHAINS = { ...SOLANA_MAINNET_CHAINS, ...SOLANA_TEST_CHAINS }
|
||||
* Methods
|
||||
*/
|
||||
export const SOLANA_SIGNING_METHODS = {
|
||||
SOLANA_SIGN_TRANSACTION: 'solana_signTransaction',
|
||||
SOLANA_SIGN_MESSAGE: 'solana_signMessage'
|
||||
SOLANA_SIGN_TRANSACTION: 'sol_signTransaction',
|
||||
SOLANA_SIGN_MESSAGE: 'sol_signMessage'
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { COSMOS_SIGNING_METHODS } from '@/data/COSMOSData'
|
||||
import { EIP155_SIGNING_METHODS } from '@/data/EIP155Data'
|
||||
import { SOLANA_SIGNING_METHODS } from '@/data/SolanaData'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { CLIENT_EVENTS } from '@walletconnect/client'
|
||||
@ -27,6 +28,9 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
const { method } = request
|
||||
const requestSession = await walletConnectClient.session.get(topic)
|
||||
|
||||
console.log(requestEvent, requestSession)
|
||||
console.log(method)
|
||||
|
||||
switch (method) {
|
||||
case EIP155_SIGNING_METHODS.ETH_SIGN:
|
||||
case EIP155_SIGNING_METHODS.PERSONAL_SIGN:
|
||||
@ -45,6 +49,10 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
|
||||
case COSMOS_SIGNING_METHODS.COSMOS_SIGN_AMINO:
|
||||
return ModalStore.open('SessionSignCosmosModal', { requestEvent, requestSession })
|
||||
|
||||
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_MESSAGE:
|
||||
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_TRANSACTION:
|
||||
return ModalStore.open('SessionSignSolanaModal', { requestEvent, requestSession })
|
||||
|
||||
default:
|
||||
return ModalStore.open('SessionUnsuportedMethodModal', { requestEvent, requestSession })
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Keypair } from '@solana/web3.js'
|
||||
import { Keypair, Transaction, TransactionInstructionCtorFields } from '@solana/web3.js'
|
||||
import bs58 from 'bs58'
|
||||
import nacl from 'tweetnacl'
|
||||
|
||||
export class Solana {
|
||||
keypair: Keypair
|
||||
@ -16,4 +18,19 @@ export class Solana {
|
||||
public async getAccount() {
|
||||
return await this.keypair.publicKey.toBase58()
|
||||
}
|
||||
|
||||
public async signMessage(message: string) {
|
||||
const signature = nacl.sign.detached(bs58.decode(message), this.keypair.secretKey)
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
public async signTransaction(transaction: TransactionInstructionCtorFields) {
|
||||
const tx = new Transaction()
|
||||
tx.add(transaction)
|
||||
await tx.sign(this.keypair)
|
||||
const { signature } = tx.signatures[tx.signatures.length - 1]
|
||||
|
||||
return signature
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ interface State {
|
||||
| 'SessionSendTransactionModal'
|
||||
| 'SessionUnsuportedMethodModal'
|
||||
| 'SessionSignCosmosModal'
|
||||
| 'SessionSignSolanaModal'
|
||||
data?: ModalData
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
import { SOLANA_SIGNING_METHODS } from '@/data/SolanaData'
|
||||
import { getWalletAddressFromParams } from '@/utils/HelperUtil'
|
||||
import { solanaAddresses, solanaWallets } from '@/utils/SolanaWalletUtil'
|
||||
import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'
|
||||
import { RequestEvent } from '@walletconnect/types'
|
||||
import { ERROR } from '@walletconnect/utils'
|
||||
|
||||
export async function approveSolanaRequest(requestEvent: RequestEvent) {
|
||||
const { method, params, id } = requestEvent.request
|
||||
const wallet = solanaWallets[getWalletAddressFromParams(solanaAddresses, params)]
|
||||
|
||||
switch (method) {
|
||||
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_MESSAGE:
|
||||
const signedMessage = await wallet.signMessage(params.signDoc)
|
||||
return formatJsonRpcResult(id, signedMessage)
|
||||
|
||||
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_TRANSACTION:
|
||||
const signedTransaction = await wallet.signTransaction(params.instructions)
|
||||
return formatJsonRpcResult(id, signedTransaction)
|
||||
|
||||
default:
|
||||
throw new Error(ERROR.UNKNOWN_JSONRPC_METHOD.format().message)
|
||||
}
|
||||
}
|
||||
|
||||
export function rejectSolanaRequest(request: RequestEvent['request']) {
|
||||
const { id } = request
|
||||
|
||||
return formatJsonRpcError(id, ERROR.JSONRPC_REQUEST_METHOD_REJECTED.format().message)
|
||||
}
|
80
wallets/react-wallet-v2/src/views/SessionSignSolanaModal.tsx
Normal file
80
wallets/react-wallet-v2/src/views/SessionSignSolanaModal.tsx
Normal file
@ -0,0 +1,80 @@
|
||||
import ProjectInfoCard from '@/components/ProjectInfoCard'
|
||||
import RequestDataCard from '@/components/RequestDataCard'
|
||||
import RequesDetailsCard from '@/components/RequestDetalilsCard'
|
||||
import RequestMethodCard from '@/components/RequestMethodCard'
|
||||
import RequestModalContainer from '@/components/RequestModalContainer'
|
||||
import ModalStore from '@/store/ModalStore'
|
||||
import { approveSolanaRequest, rejectSolanaRequest } from '@/utils/SolanaRequestHandlerUtil'
|
||||
import { walletConnectClient } from '@/utils/WalletConnectUtil'
|
||||
import { Button, Divider, Modal, Text } from '@nextui-org/react'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function SessionSignSolanaModal() {
|
||||
// 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 <Text>Missing request data</Text>
|
||||
}
|
||||
|
||||
// Get required request data
|
||||
const { method, params } = requestEvent.request
|
||||
|
||||
// Handle approve action (logic varies based on request method)
|
||||
async function onApprove() {
|
||||
if (requestEvent) {
|
||||
const response = await approveSolanaRequest(requestEvent)
|
||||
await walletConnectClient.respond({
|
||||
topic: requestEvent.topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reject action
|
||||
async function onReject() {
|
||||
if (requestEvent) {
|
||||
const response = rejectSolanaRequest(requestEvent.request)
|
||||
await walletConnectClient.respond({
|
||||
topic: requestEvent.topic,
|
||||
response
|
||||
})
|
||||
ModalStore.close()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<RequestModalContainer title="Sign Message">
|
||||
<ProjectInfoCard metadata={requestSession.peer.metadata} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequesDetailsCard
|
||||
chains={[requestEvent.chainId ?? '']}
|
||||
protocol={requestSession.relay.protocol}
|
||||
/>
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequestDataCard data={params} />
|
||||
|
||||
<Divider y={2} />
|
||||
|
||||
<RequestMethodCard methods={[method]} />
|
||||
</RequestModalContainer>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button auto flat color="error" onClick={onReject}>
|
||||
Reject
|
||||
</Button>
|
||||
<Button auto flat color="success" onClick={onApprove}>
|
||||
Approve
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
@ -1419,6 +1419,11 @@ base-x@^3.0.2:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
base-x@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a"
|
||||
integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==
|
||||
|
||||
base64-js@^1.3.0, base64-js@^1.3.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||
@ -1524,6 +1529,13 @@ brorand@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
|
||||
|
||||
bs58@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279"
|
||||
integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==
|
||||
dependencies:
|
||||
base-x "^4.0.0"
|
||||
|
||||
bs58@^4.0.0, bs58@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
|
||||
|
Loading…
Reference in New Issue
Block a user