diff --git a/src/features/connect.ts b/src/features/connect.ts index 26e539a..7469a76 100644 --- a/src/features/connect.ts +++ b/src/features/connect.ts @@ -11,13 +11,13 @@ export const BitcoinConnect = 'bitcoin:connect'; * @group Connect */ export type BitcoinConnectFeature = { - /** Name of the feature. */ - readonly [BitcoinConnect]: { - /** Version of the feature implemented by the Wallet. */ - readonly version: BitcoinConnectVersion; - /** Method to call to use the feature. */ - readonly connect: BitcoinConnectMethod; - }; + /** Name of the feature. */ + readonly [BitcoinConnect]: { + /** Version of the feature implemented by the Wallet. */ + readonly version: BitcoinConnectVersion; + /** Method to call to use the feature. */ + readonly connect: BitcoinConnectMethod; + }; }; /** @@ -40,8 +40,8 @@ export type BitcoinConnectMethod = (input: BitcoinConnectInput) => Promise Promise; diff --git a/src/features/index.ts b/src/features/index.ts index eed6c99..1d29786 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -1,13 +1,15 @@ import type { WalletWithFeatures } from '@wallet-standard/base'; import type { BitcoinConnectFeature } from './connect'; +import type { BitcoinDisconnectFeature } from './disconnect'; +import type { BitcoinSatsConnectFeature } from './satsConnect'; import type { BitcoinSignAndSendTransactionFeature } from './signAndSendTransaction'; import type { BitcoinSignMessageFeature } from './signMessage'; import type { BitcoinSignTransactionFeature } from './signTransaction'; -import { BitcoinSatsConnectFeature } from './satsConnect'; /** Type alias for some or all Bitcoin features. */ export type BitcoinStandardFeatures = BitcoinConnectFeature & + BitcoinDisconnectFeature & BitcoinSignTransactionFeature & BitcoinSignAndSendTransactionFeature & BitcoinSignMessageFeature; @@ -19,6 +21,7 @@ export type WalletWithBitcoinStandardFeatures = WalletWithFeatures; export * from './connect'; +export * from './disconnect'; export * from './signTransaction'; export * from './signAndSendTransaction'; export * from './signMessage'; diff --git a/src/features/signAndSendTransaction.ts b/src/features/signAndSendTransaction.ts index bc1d142..3290c0d 100644 --- a/src/features/signAndSendTransaction.ts +++ b/src/features/signAndSendTransaction.ts @@ -14,14 +14,14 @@ export const BitcoinSignAndSendTransaction = 'bitcoin:signAndSendTransaction'; * @group SignAndSendTransaction */ export type BitcoinSignAndSendTransactionFeature = { - /** Name of the feature. */ - readonly [BitcoinSignAndSendTransaction]: { - /** Version of the feature implemented by the Wallet. */ - readonly version: BitcoinSignAndSendTransactionVersion; - - /** Method to call to use the feature. */ - readonly signAndSendTransaction: BitcoinSignAndSendTransactionMethod; - }; + /** Name of the feature. */ + readonly [BitcoinSignAndSendTransaction]: { + /** Version of the feature implemented by the Wallet. */ + readonly version: BitcoinSignAndSendTransactionVersion; + + /** Method to call to use the feature. */ + readonly signAndSendTransaction: BitcoinSignAndSendTransactionMethod; + }; }; /** @@ -37,7 +37,7 @@ export type BitcoinSignAndSendTransactionVersion = '1.0.0'; * @group SignAndSendTransaction */ export type BitcoinSignAndSendTransactionMethod = ( - ...inputs: readonly BitcoinSignAndSendTransactionInput[] + ...inputs: readonly BitcoinSignAndSendTransactionInput[] ) => Promise; /** @@ -46,8 +46,8 @@ export type BitcoinSignAndSendTransactionMethod = ( * @group SignAndSendTransaction */ export interface BitcoinSignAndSendTransactionInput extends BitcoinSignTransactionInput { - /** Chain to use. */ - readonly chain: IdentifierString; + /** Chain to use. */ + readonly chain: IdentifierString; } /** @@ -56,6 +56,6 @@ export interface BitcoinSignAndSendTransactionInput extends BitcoinSignTransacti * @group SignAndSendTransaction */ export interface BitcoinSignAndSendTransactionOutput { - /** Transaction ID (transaction hash). */ - readonly txId: string; + /** Transaction ID (transaction hash). */ + readonly txId: string; } diff --git a/src/features/signMessage.ts b/src/features/signMessage.ts index 6d972ec..590004f 100644 --- a/src/features/signMessage.ts +++ b/src/features/signMessage.ts @@ -15,14 +15,14 @@ export const BitcoinSignMessage = 'bitcoin:signMessage'; * @group SignMessage */ export type BitcoinSignMessageFeature = { - /** Name of the feature. */ - readonly [BitcoinSignMessage]: { - /** Version of the feature implemented by the Wallet. */ - readonly version: BitcoinSignMessageVersion; + /** Name of the feature. */ + readonly [BitcoinSignMessage]: { + /** Version of the feature implemented by the Wallet. */ + readonly version: BitcoinSignMessageVersion; - /** Method to call to use the feature. */ - readonly signMessage: BitcoinSignMessageMethod; - }; + /** Method to call to use the feature. */ + readonly signMessage: BitcoinSignMessageMethod; + }; }; /** @@ -38,7 +38,7 @@ export type BitcoinSignMessageVersion = '1.0.0'; * @group SignMessage */ export type BitcoinSignMessageMethod = ( - ...inputs: readonly BitcoinSignMessageInput[] + ...inputs: readonly BitcoinSignMessageInput[] ) => Promise; /** @@ -47,11 +47,11 @@ export type BitcoinSignMessageMethod = ( * @group SignMessage */ export interface BitcoinSignMessageInput { - /** Account to use. */ - readonly account: WalletAccount; + /** Account to use. */ + readonly account: WalletAccount; - /** Message to sign, as raw bytes. */ - readonly message: Uint8Array; + /** Message to sign, as raw bytes. */ + readonly message: Uint8Array; } /** @@ -60,12 +60,12 @@ export interface BitcoinSignMessageInput { * @group SignMessage */ export interface BitcoinSignMessageOutput { - /** - * Message bytes that were signed. - * The wallet may prefix or otherwise modify the message before signing it. - */ - readonly signedMessage: Uint8Array; + /** + * Message bytes that were signed. + * The wallet may prefix or otherwise modify the message before signing it. + */ + readonly signedMessage: Uint8Array; - /** Message signature produced. */ - readonly signature: Uint8Array; + /** Message signature produced. */ + readonly signature: Uint8Array; } diff --git a/src/features/signTransaction.ts b/src/features/signTransaction.ts index 3980776..121dd89 100644 --- a/src/features/signTransaction.ts +++ b/src/features/signTransaction.ts @@ -11,14 +11,14 @@ export const BitcoinSignTransaction = 'bitcoin:signTransaction'; * @group SignTransaction */ export type BitcoinSignTransactionFeature = { - /** Name of the feature. */ - readonly [BitcoinSignTransaction]: { - /** Version of the feature implemented by the Wallet. */ - readonly version: BitcoinSignTransactionVersion; + /** Name of the feature. */ + readonly [BitcoinSignTransaction]: { + /** Version of the feature implemented by the Wallet. */ + readonly version: BitcoinSignTransactionVersion; - /** Method to call to use the feature. */ - readonly signTransaction: BitcoinSignTransactionMethod; - }; + /** Method to call to use the feature. */ + readonly signTransaction: BitcoinSignTransactionMethod; + }; }; /** @@ -34,7 +34,7 @@ export type BitcoinSignTransactionVersion = '1.0.0'; * @group SignTransaction */ export type BitcoinSignTransactionMethod = ( - ...inputs: readonly BitcoinSignTransactionInput[] + ...inputs: readonly BitcoinSignTransactionInput[] ) => Promise; /** @@ -43,14 +43,14 @@ export type BitcoinSignTransactionMethod = ( * @group SignTransaction */ export interface BitcoinSignTransactionInput { - /** Partially Signed Bitcoin Transaction (PSBT), as raw bytes. */ - readonly psbt: Uint8Array; + /** Partially Signed Bitcoin Transaction (PSBT), as raw bytes. */ + readonly psbt: Uint8Array; - /** Transaction inputs to sign. */ - readonly inputsToSign: InputToSign[]; + /** Transaction inputs to sign. */ + readonly inputsToSign: InputToSign[]; - /** Chain to use. */ - readonly chain?: IdentifierString; + /** Chain to use. */ + readonly chain?: IdentifierString; } /** @@ -59,14 +59,14 @@ export interface BitcoinSignTransactionInput { * @group SignTransaction * */ export interface InputToSign { - /** Account to use. */ - readonly account: WalletAccount; + /** Account to use. */ + readonly account: WalletAccount; - /** List of input indexes that should be signed by the account. */ - readonly signingIndexes: number[]; + /** List of input indexes that should be signed by the account. */ + readonly signingIndexes: number[]; - /** A SIGHASH flag. */ - readonly sigHash?: BitcoinSigHashFlag; + /** A SIGHASH flag. */ + readonly sigHash?: BitcoinSigHashFlag; } /** @@ -75,15 +75,15 @@ export interface InputToSign { * @group SignTransaction */ export interface BitcoinSignTransactionOutput { - /** Signed Partially Signed Bitcoin Transaction (PSBT), as raw bytes. */ - readonly signedPsbt: Uint8Array; + /** Signed Partially Signed Bitcoin Transaction (PSBT), as raw bytes. */ + readonly signedPsbt: Uint8Array; } /** SIGHASH flag. */ export type BitcoinSigHashFlag = - | 'ALL' - | 'NONE' - | 'SINGLE' - | 'ALL|ANYONECANPAY' - | 'NONE|ANYONECANPAY' - | 'SINGLE|ANYONECANPAY'; + | 'ALL' + | 'NONE' + | 'SINGLE' + | 'ALL|ANYONECANPAY' + | 'NONE|ANYONECANPAY' + | 'SINGLE|ANYONECANPAY'; diff --git a/src/satsConnectWallet.ts b/src/satsConnectWallet.ts index 9a477b1..436e1b5 100644 --- a/src/satsConnectWallet.ts +++ b/src/satsConnectWallet.ts @@ -6,6 +6,7 @@ import type { StandardConnectOutput, StandardEventsListeners, StandardEventsName import { ReadonlyWalletAccount } from '@wallet-standard/wallet'; import { decodeToken } from 'jsontokens'; import { + BitcoinDisconnect, BitcoinSignAndSendTransaction, type BitcoinSignAndSendTransactionInput, type BitcoinSignAndSendTransactionOutput, @@ -93,6 +94,10 @@ export class BitcoinWallet implements Wallet { version: this.version, connect: this.#connect, }, + [BitcoinDisconnect]: { + version: this.version, + disconnect: this.#disconnect, + }, [SatsConnectFeatureName]: { provider: this.#getSatsConnectProvider(), }, @@ -296,6 +301,21 @@ export class BitcoinWallet implements Wallet { }; } + #disconnect = async (): Promise => { + const selectedAccount = this.#account; + + if (!selectedAccount) { + throw new Error('No connected account'); + } + + await this.client.revokeSession({ scopes: [this.scope ?? CaipScope.MAINNET] }); + + this.#account = undefined; + this.scope = undefined; + this.#removeAccountsChangedListener?.(); + this.#removeAccountsChangedListener = undefined; + }; + #tryRestoringSession = async (): Promise => { try { const existingSession = await this.client.getSession();