Skip to content

Commit 5fc7b7b

Browse files
authored
feat: solana sign and send transaction (#664)
* feat: add solana signAndSendTransaction function * refactor: remove blockhash param * feat: add signAndSendTransaction options and confirmation * fix: remove unnecessary extra condition
1 parent 2bfb822 commit 5fc7b7b

File tree

4 files changed

+74
-6
lines changed

4 files changed

+74
-6
lines changed

advanced/wallets/react-wallet-v2/src/data/SolanaData.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const SOLANA_MAINNET_CHAINS = {
2121
name: 'Solana',
2222
logo: '/chain-logos/solana-5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.png',
2323
rgb: '30, 240, 166',
24-
rpc: '',
24+
rpc: 'https://api.mainnet-beta.solana.com',
2525
namespace: 'solana'
2626
}
2727
}
@@ -41,15 +41,15 @@ export const SOLANA_TEST_CHAINS = {
4141
name: 'Solana Devnet',
4242
logo: '/chain-logos/solana-5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.png',
4343
rgb: '30, 240, 166',
44-
rpc: '',
44+
rpc: 'https://api.devnet.solana.com',
4545
namespace: 'solana'
4646
},
4747
'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z': {
4848
chainId: '4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',
4949
name: 'Solana Testnet',
5050
logo: '/chain-logos/solana-5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.png',
5151
rgb: '30, 240, 166',
52-
rpc: '',
52+
rpc: 'https://api.testnet.solana.com',
5353
namespace: 'solana'
5454
}
5555
}
@@ -61,5 +61,6 @@ export const SOLANA_CHAINS = { ...SOLANA_MAINNET_CHAINS, ...SOLANA_TEST_CHAINS }
6161
*/
6262
export const SOLANA_SIGNING_METHODS = {
6363
SOLANA_SIGN_TRANSACTION: 'solana_signTransaction',
64-
SOLANA_SIGN_MESSAGE: 'solana_signMessage'
64+
SOLANA_SIGN_MESSAGE: 'solana_signMessage',
65+
SOLANA_SIGN_AND_SEND_TRANSACTION: 'solana_signAndSendTransaction'
6566
}

advanced/wallets/react-wallet-v2/src/hooks/useWalletConnectEventsManager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ export default function useWalletConnectEventsManager(initialized: boolean) {
106106

107107
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_MESSAGE:
108108
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_TRANSACTION:
109+
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_AND_SEND_TRANSACTION:
109110
return ModalStore.open('SessionSignSolanaModal', { requestEvent, requestSession })
110111

111112
case POLKADOT_SIGNING_METHODS.POLKADOT_SIGN_MESSAGE:

advanced/wallets/react-wallet-v2/src/lib/SolanaLib.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
import { Keypair } from '@solana/web3.js'
1+
import {
2+
Keypair,
3+
Connection,
4+
Transaction,
5+
TransactionInstruction,
6+
PublicKey,
7+
SendOptions
8+
} from '@solana/web3.js'
29
import bs58 from 'bs58'
310
import nacl from 'tweetnacl'
411
import SolanaWallet, { SolanaSignTransaction } from 'solana-wallet'
12+
import { SOLANA_MAINNET_CHAINS, SOLANA_TEST_CHAINS } from '@/data/SolanaData'
513

614
/**
715
* Types
@@ -58,4 +66,52 @@ export default class SolanaLib {
5866

5967
return { signature }
6068
}
69+
70+
public async signAndSendTransaction(
71+
feePayer: SolanaSignTransaction['feePayer'],
72+
instructions: SolanaSignTransaction['instructions'],
73+
chainId: string,
74+
options: SendOptions = {}
75+
) {
76+
const rpc = { ...SOLANA_TEST_CHAINS, ...SOLANA_MAINNET_CHAINS }[chainId]?.rpc
77+
78+
if (!rpc) {
79+
throw new Error('There is no RPC URL for the provided chain')
80+
}
81+
82+
const connection = new Connection(rpc)
83+
84+
const parsedInstructions = instructions.map(instruction => {
85+
const keys = instruction.keys.map(key => ({
86+
pubkey: new PublicKey(key.pubkey),
87+
isSigner: key.isSigner,
88+
isWritable: key.isWritable
89+
}))
90+
const programId = new PublicKey(instruction.programId)
91+
const data =
92+
typeof instruction.data === 'string'
93+
? Buffer.from(bs58.decode(instruction.data).buffer)
94+
: instruction.data
95+
96+
return new TransactionInstruction({
97+
keys,
98+
programId,
99+
data
100+
})
101+
})
102+
103+
const transaction = new Transaction().add(...parsedInstructions)
104+
transaction.feePayer = new PublicKey(feePayer)
105+
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash
106+
transaction.sign(this.keypair)
107+
108+
const signature = await connection.sendRawTransaction(transaction.serialize())
109+
const confirmation = await connection.confirmTransaction(signature, options.preflightCommitment)
110+
111+
if (confirmation.value.err) {
112+
throw new Error(confirmation.value.err.toString())
113+
}
114+
115+
return { signature }
116+
}
61117
}

advanced/wallets/react-wallet-v2/src/utils/SolanaRequestHandlerUtil.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export async function approveSolanaRequest(
99
requestEvent: SignClientTypes.EventArguments['session_request']
1010
) {
1111
const { params, id } = requestEvent
12-
const { request } = params
12+
const { request, chainId } = params
1313
const wallet = solanaWallets[getWalletAddressFromParams(solanaAddresses, params)]
1414

1515
switch (request.method) {
@@ -26,6 +26,16 @@ export async function approveSolanaRequest(
2626

2727
return formatJsonRpcResult(id, signedTransaction)
2828

29+
case SOLANA_SIGNING_METHODS.SOLANA_SIGN_AND_SEND_TRANSACTION:
30+
const signedAndSentTransaction = await wallet.signAndSendTransaction(
31+
request.params.feePayer,
32+
request.params.instructions,
33+
chainId,
34+
request.params.options
35+
)
36+
37+
return formatJsonRpcResult(id, signedAndSentTransaction)
38+
2939
default:
3040
throw new Error(getSdkError('INVALID_METHOD').message)
3141
}

0 commit comments

Comments
 (0)