diff --git a/CHANGELOG.md b/CHANGELOG.md index 1932321..6ddf907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add testnet4 support (`CaipScope.TESTNET4`, `Chain.TESTNET4`, `scopeToChain` mapping) +- Support `ordinals` purpose in `bitcoin:connect` to return P2TR addresses ## [1.0.0] diff --git a/README.md b/README.md index c7d9904..16e5c7a 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,11 @@ const { accounts } = await metamask_wallet.features['bitcoin:connect'].connect({ purposes: ['payment'], }) +// Request a taproot account for ordinals +const { accounts: ordinalAccounts } = await metamask_wallet.features['bitcoin:connect'].connect({ + purposes: ['ordinals'], +}) + wallet.features['bitcoin:events'].on('change', (event => { // Handle events })); @@ -191,6 +196,12 @@ const connectResponse = await WalletV4.request('getAddresses', { message: 'Address for receiving BTC', }); +// Connect and get a taproot address for ordinals +const ordinalsResponse = await WalletV4.request('getAddresses', { + purposes: ['ordinals'], + message: 'Address for receiving ordinals', +}); + if (connectResponse.status === 'error') { throw new Error(connectResponse.error.message); } diff --git a/src/wallet.test.ts b/src/wallet.test.ts index eb54c7f..9e8e160 100644 --- a/src/wallet.test.ts +++ b/src/wallet.test.ts @@ -674,6 +674,30 @@ describe('MetamaskWallet', () => { }, }); }); + + it('should return P2TR address type for ordinals purpose', async () => { + await reconnectAndSetAccount(address); + + const result = await wallet.features[BitcoinSatsConnect].provider.request('getAddresses', { + purposes: [AddressPurpose.Ordinals], + }); + + expect(result).toMatchObject({ + jsonrpc: '2.0', + result: { + addresses: [ + { + address, + publicKey: Buffer.from(address).toString('hex'), + purpose: AddressPurpose.Ordinals, + addressType: AddressType.p2tr, + walletType: WalletType.SOFTWARE, + }, + ], + network: expectedMainnetNetwork, + }, + }); + }); }); describe('getAccounts', () => { diff --git a/src/wallet.ts b/src/wallet.ts index 61dd165..01e2301 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -436,9 +436,6 @@ export class MetaMaskWallet implements Wallet { } const { purposes } = payload as unknown as BitcoinConnectInput; - if (purposes.length !== 1 || purposes.at(0) !== AddressPurpose.Payment) { - throw new Error(`Only payment addresses are supported. Received: ${purposes.join(', ')}`); - } await this.#connect(); @@ -447,7 +444,7 @@ export class MetaMaskWallet implements Wallet { } return { - addresses: this.accounts.map(this.#standardAccountToSatsAccount), + addresses: this.accounts.map((account) => this.#standardAccountToSatsAccount(account, purposes)), }; }, @@ -519,7 +516,8 @@ export class MetaMaskWallet implements Wallet { if (method === 'wallet_requestPermissions') { return success(true); } - const addresses = this.accounts.map(this.#standardAccountToSatsAccount); + const reqPurposes = (options as Record)?.purposes as readonly string[] | undefined; + const addresses = this.accounts.map((account) => this.#standardAccountToSatsAccount(account, reqPurposes)); if (method === 'getAccounts') { return success(addresses); } @@ -656,12 +654,13 @@ export class MetaMaskWallet implements Wallet { }; }; - #standardAccountToSatsAccount(account: WalletStandardWalletAccount): Address { + #standardAccountToSatsAccount(account: WalletStandardWalletAccount, purposes?: readonly string[]): Address { + const isOrdinals = purposes?.includes('ordinals'); return { address: account.address, publicKey: Buffer.from(account.publicKey).toString('hex'), - purpose: AddressPurpose.Payment, - addressType: AddressType.p2wpkh, + purpose: isOrdinals ? AddressPurpose.Ordinals : AddressPurpose.Payment, + addressType: isOrdinals ? AddressType.p2tr : AddressType.p2wpkh, walletType: WalletType.SOFTWARE, }; }