Save progress on solana transaction signing

This commit is contained in:
Ilja 2022-03-15 11:11:58 +02:00
parent 518510ca1f
commit 8ba122d703
9 changed files with 154 additions and 3 deletions

View File

@ -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",

View File

@ -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>
)
}

View File

@ -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'
}

View File

@ -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 })
}

View File

@ -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
}
}

View File

@ -20,6 +20,7 @@ interface State {
| 'SessionSendTransactionModal'
| 'SessionUnsuportedMethodModal'
| 'SessionSignCosmosModal'
| 'SessionSignSolanaModal'
data?: ModalData
}

View File

@ -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)
}

View 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>
)
}

View File

@ -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"