import type { EventEmitter, SendTransactionOptions, WalletName } from '@solana/wallet-adapter-base'; import { BaseMessageSignerWalletAdapter, scopePollingDetectionStrategy, WalletAccountError, WalletConnectionError, WalletDisconnectedError, WalletDisconnectionError, WalletNotConnectedError, WalletNotReadyError, WalletPublicKeyError, WalletReadyState, WalletSendTransactionError, WalletSignMessageError, WalletSignTransactionError, } from '@solana/wallet-adapter-base'; import type { Connection, SendOptions, Signer, Transaction, TransactionSignature } from '@solana/web3.js'; import { PublicKey } from '@solana/web3.js'; interface BackpackWalletEvents { connect(...args: unknown[]): unknown; disconnect(...args: unknown[]): unknown; } interface BackpackWallet extends EventEmitter { isBackpack?: boolean; publicKey?: { toBytes(): Uint8Array }; isConnected: boolean; signTransaction(transaction: Transaction, publicKey?: PublicKey | null): Promise; signAllTransactions(transactions: Transaction[], publicKey?: PublicKey | null): Promise; send( transaction: Transaction, signers?: Signer[], options?: SendOptions, connection?: Connection, publicKey?: PublicKey | null ): Promise; signMessage(message: Uint8Array, publicKey?: PublicKey | null): Promise; connect(): Promise; disconnect(): Promise; } interface BackpackWindow extends Window { backpack?: BackpackWallet; } declare const window: BackpackWindow; export interface BackpackWalletAdapterConfig {} export const BackpackWalletName = 'Backpack' as WalletName<'Backpack'>; export class BackpackWalletAdapter extends BaseMessageSignerWalletAdapter { name = BackpackWalletName; url = 'https://backpack.app'; icon = 'data:image/png;base64,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'; readonly supportedTransactionVersions = null; private _connecting: boolean; private _wallet: BackpackWallet | null; private _publicKey: PublicKey | null; private _readyState: WalletReadyState = typeof window === 'undefined' || typeof document === 'undefined' ? WalletReadyState.Unsupported : WalletReadyState.NotDetected; constructor(config: BackpackWalletAdapterConfig = {}) { super(); this._connecting = false; this._wallet = null; this._publicKey = null; if (this._readyState !== WalletReadyState.Unsupported) { scopePollingDetectionStrategy(() => { if (window.backpack?.isBackpack) { this._readyState = WalletReadyState.Installed; this.emit('readyStateChange', this._readyState); return true; } return false; }); } } get publicKey() { return this._publicKey; } get connecting() { return this._connecting; } get connected() { return !!this._wallet?.isConnected; } get readyState() { return this._readyState; } async connect(): Promise { try { if (this.connected || this.connecting) return; if (this._readyState !== WalletReadyState.Installed) throw new WalletNotReadyError(); this._connecting = true; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const wallet = window.backpack!; try { await wallet.connect(); } catch (error: any) { throw new WalletConnectionError(error?.message, error); } if (!wallet.publicKey) throw new WalletAccountError(); let publicKey: PublicKey; try { publicKey = new PublicKey(wallet.publicKey.toBytes()); } catch (error: any) { throw new WalletPublicKeyError(error?.message, error); } wallet.on('disconnect', this._disconnected); this._wallet = wallet; this._publicKey = publicKey; this.emit('connect', publicKey); } catch (error: any) { this.emit('error', error); throw error; } finally { this._connecting = false; } } async disconnect(): Promise { const wallet = this._wallet; if (wallet) { wallet.off('disconnect', this._disconnected); this._wallet = null; this._publicKey = null; try { await wallet.disconnect(); } catch (error: any) { this.emit('error', new WalletDisconnectionError(error?.message, error)); } } this.emit('disconnect'); } async sendTransaction( transaction: Transaction, connection: Connection, options: SendTransactionOptions = {} ): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); const { signers, ...sendOptions } = options; try { return await wallet.send(transaction, signers, sendOptions, connection, this.publicKey); } catch (error: any) { throw new WalletSendTransactionError(error?.message, error); } } catch (error: any) { this.emit('error', error); throw error; } } async signTransaction(transaction: T): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); try { return (await wallet.signTransaction(transaction, this.publicKey)) as T; } catch (error: any) { throw new WalletSignTransactionError(error?.message, error); } } catch (error: any) { this.emit('error', error); throw error; } } async signAllTransactions(transactions: T[]): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); try { return (await wallet.signAllTransactions(transactions, this.publicKey)) as T[]; } catch (error: any) { throw new WalletSignTransactionError(error?.message, error); } } catch (error: any) { this.emit('error', error); throw error; } } async signMessage(message: Uint8Array): Promise { try { const wallet = this._wallet; if (!wallet) throw new WalletNotConnectedError(); try { return await wallet.signMessage(message, this.publicKey); } catch (error: any) { throw new WalletSignMessageError(error?.message, error); } } catch (error: any) { this.emit('error', error); throw error; } } private _disconnected = () => { const wallet = this._wallet; if (wallet) { wallet.off('disconnect', this._disconnected); this._wallet = null; this._publicKey = null; this.emit('error', new WalletDisconnectedError()); this.emit('disconnect'); } }; }