import type { Connection, Transaction, VersionedTransaction } from "@solana/web3.js"; import { SolanaSignAndSendTransactionMethod, SolanaSignMessageMethod, SolanaSignTransactionMethod } from "@solana/wallet-standard-features"; import type { Wallet } from "@wallet-standard/base"; import { base58 } from "@scure/base"; export interface ISolanaProtocolWallet { address: string; sendTransaction?: (transaction: Transaction | VersionedTransaction, connection: Connection, options?: any) => Promise; signMessage?: (message: string) => Promise; disconnect?: (data?: { silent?: boolean }) => Promise; } class SolanaProtocolWallet implements ISolanaProtocolWallet { constructor(readonly wallet: Wallet, readonly address: string) {} static async connect(wallet: Wallet, { silent = false }: { silent?: boolean } = {}): Promise { const a = new SolanaProtocolWallet(wallet, ""); const account = await a.getAccount({ silent }); return new SolanaProtocolWallet(wallet, account.address); } async getAccount({ silent = false }: { silent?: boolean } = {}) { let accounts = this.wallet.accounts || []; if (!accounts.length) { const connect = (this.wallet.features as any)["standard:connect"]?.connect; if (!connect) throw new Error("Wallet does not support standard:connect"); const { accounts: connectedAccounts } = await connect({ silent }); accounts = connectedAccounts || []; } if (!accounts.length) throw new Error("No account found"); return accounts[0]; } async disconnect() { const disconnect = (this.wallet.features as any)["standard:disconnect"]?.disconnect as (() => Promise) | undefined; if (disconnect) await disconnect(); } async sendTransaction(transaction: Transaction | VersionedTransaction, connection: Connection, options?: any): Promise { const account = await this.getAccount(); const features = this.wallet.features as any; const signTx = features["solana:signTransaction"]?.signTransaction as SolanaSignTransactionMethod; const [signed] = await signTx({ account, chain: account.chains[0], transaction: transaction.serialize() }); const signedTx = signed.signedTransaction as Transaction | VersionedTransaction | Uint8Array; const raw = signedTx instanceof Uint8Array ? signedTx : (signedTx as any).serialize(); const sig = await connection.sendRawTransaction(raw as Uint8Array, options as any); return sig; } async signMessage(message: string) { const account = await this.getAccount(); const features = this.wallet.features as any; const signMessageFeature = features["solana:signMessage"]?.signMessage as SolanaSignMessageMethod; if (!signMessageFeature) throw new Error("Wallet does not support solana:signMessage"); const [result] = await signMessageFeature({ account, message: new TextEncoder().encode(message) }); if (result.signature) return result.signature; if (Array.isArray(result) && result[0]?.signature) return result[0].signature as Uint8Array; throw new Error("Unexpected signMessage result"); } } export default SolanaProtocolWallet;