import type { Connection, TransactionSignature } from '@solana/web3.js'; import type { SendTransactionOptions, WalletAdapter, WalletAdapterProps } from './adapter.js'; import { BaseWalletAdapter } from './adapter.js'; import { WalletSendTransactionError, WalletSignTransactionError } from './errors.js'; import type { TransactionOrVersionedTransaction } from './types.js'; import { isVersionedTransaction } from './types.js'; export interface SignerWalletAdapterProps extends WalletAdapterProps { signTransaction>( transaction: T ): Promise; signAllTransactions>( transactions: T[] ): Promise; } export type SignerWalletAdapter = WalletAdapter & SignerWalletAdapterProps; export abstract class BaseSignerWalletAdapter extends BaseWalletAdapter implements SignerWalletAdapter { async sendTransaction( transaction: TransactionOrVersionedTransaction, connection: Connection, options: SendTransactionOptions = {} ): Promise { let emit = true; try { if (isVersionedTransaction(transaction)) { if (!this.supportedTransactionVersions) throw new WalletSendTransactionError( `Sending versioned transactions isn't supported by this wallet` ); if (!this.supportedTransactionVersions.has(transaction.version)) throw new WalletSendTransactionError( `Sending transaction version ${transaction.version} isn't supported by this wallet` ); try { transaction = await this.signTransaction(transaction); const rawTransaction = transaction.serialize(); return await connection.sendRawTransaction(rawTransaction, options); } catch (error: any) { // If the error was thrown by `signTransaction`, rethrow it and don't emit a duplicate event if (error instanceof WalletSignTransactionError) { emit = false; throw error; } throw new WalletSendTransactionError(error?.message, error); } } else { try { const { signers, ...sendOptions } = options; transaction = await this.prepareTransaction(transaction, connection, sendOptions); signers?.length && transaction.partialSign(...signers); transaction = await this.signTransaction(transaction); const rawTransaction = transaction.serialize(); return await connection.sendRawTransaction(rawTransaction, sendOptions); } catch (error: any) { // If the error was thrown by `signTransaction`, rethrow it and don't emit a duplicate event if (error instanceof WalletSignTransactionError) { emit = false; throw error; } throw new WalletSendTransactionError(error?.message, error); } } } catch (error: any) { if (emit) { this.emit('error', error); } throw error; } } abstract signTransaction>( transaction: T ): Promise; async signAllTransactions>( transactions: T[] ): Promise { for (const transaction of transactions) { if (isVersionedTransaction(transaction)) { if (!this.supportedTransactionVersions) throw new WalletSignTransactionError( `Signing versioned transactions isn't supported by this wallet` ); if (!this.supportedTransactionVersions.has(transaction.version)) throw new WalletSignTransactionError( `Signing transaction version ${transaction.version} isn't supported by this wallet` ); } } const signedTransactions: T[] = []; for (const transaction of transactions) { signedTransactions.push(await this.signTransaction(transaction)); } return signedTransactions; } } export interface MessageSignerWalletAdapterProps extends WalletAdapterProps { signMessage(message: Uint8Array): Promise; } export type MessageSignerWalletAdapter = WalletAdapter & MessageSignerWalletAdapterProps; export abstract class BaseMessageSignerWalletAdapter extends BaseSignerWalletAdapter implements MessageSignerWalletAdapter { abstract signMessage(message: Uint8Array): Promise; }