Skip to content

Commit

Permalink
feat(bitcoin): Add phantom wallet adapter (#1267)
Browse files Browse the repository at this point in the history
* feat(bitcoin): Add phantom wallet adapter

* changeset

* type def

* Update packages/bitcoin/src/adapter/wallets/phantom.ts

Co-authored-by: thinkasany <[email protected]>

* doc

* fix eslint

* x

* build error

* get balance

* doc

* impl getInscriptions

* ignore test coverage

* update demo

* doc

* add NotImplementError

* update lock

* fix dep version

* chore: update lock

---------

Co-authored-by: thinkasany <[email protected]>
  • Loading branch information
gin-lsl and thinkasany authored Dec 26, 2024
1 parent 9a6dc16 commit 80f0dc2
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 71 deletions.
5 changes: 5 additions & 0 deletions .changeset/mighty-dogs-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ant-design/web3-bitcoin': minor
---

feat(bitcoin): Add phantom wallet adapter
3 changes: 2 additions & 1 deletion packages/bitcoin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"dependencies": {
"@ant-design/web3-common": "workspace:*",
"@ant-design/web3-icons": "workspace:*",
"sats-connect": "^2.4.0"
"sats-connect": "~2.4.0",
"uint8array-tools": "~0.0.9"
},
"devDependencies": {
"father": "^4.4.4",
Expand Down
1 change: 1 addition & 0 deletions packages/bitcoin/src/adapter/wallets/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './unisat';
export * from './xverse';
export * from './okx';
export * from './phantom';
131 changes: 131 additions & 0 deletions packages/bitcoin/src/adapter/wallets/phantom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/* v8 ignore start */
import type { Account } from '@ant-design/web3-common';
import { fromHex, fromUtf8, toBase64, toHex } from 'uint8array-tools';

import { NoAddressError, NoProviderError, NotImplementedError } from '../../error';
import { getBalanceByMempool, getInscriptionsByAddress } from '../../helpers';
import type { SignPsbtParams, TransferParams } from '../../types';
import type { BitcoinWallet } from '../useBitcoinWallet';

type AccountType = {
address: string;
addressType: string;
publicKey: string;
purpose: string;
};

/**
* @link https://docs.phantom.app/bitcoin/provider-api-reference#options-parameters
*/
type PhantomSignPsbtOptions = {
sigHash?: number;
address: string;
signingIndexes: number[];
}[];

export class PhantomBitcoinWallet implements BitcoinWallet {
name: string;
provider?: any;
account?: Account;
payment?: string;

constructor(name: string) {
this.name = name;
this.provider = window.phantom?.bitcoin;
this.account = undefined;
}

connect = async () => {
if (!this.provider) {
throw new NoProviderError();
}

try {
const accounts: AccountType[] = await this.provider.requestAccounts();
const ordinals = accounts.find((acc) => acc.purpose === 'ordinals');
const payment = accounts.find((acc) => acc.purpose === 'payment');

this.account = ordinals ? { address: ordinals.address } : undefined;
this.payment = payment?.address;
} catch (error) {
throw error;
}
};

getBalance = async () => {
if (!this.payment) {
throw new NoAddressError();
}

const balance = await getBalanceByMempool(this.payment);
return balance;
};

signMessage = async (message: string) => {
if (!this.provider) {
throw new NoProviderError();
}

if (!this.account?.address) {
throw new NoAddressError();
}

const { signature } = await this.provider.signMessage(this.account.address, fromUtf8(message));

return toBase64(signature);
};

signPsbt = async ({ psbt, options = {} }: SignPsbtParams) => {
if (!this.provider) {
throw new NoProviderError();
}

if (!this.account?.address) {
throw new NoAddressError();
}

const serializedPsbt = fromHex(psbt);

const {
// `broadcast` not supported
// broadcast,
signInputs,
signHash,
} = options;
const inputsToSign: PhantomSignPsbtOptions = [];

if (signInputs) {
for (const address in signInputs) {
inputsToSign.push({
sigHash: signHash,
address,
signingIndexes: signInputs[address],
});
}
}

const signedPsbt = await this.provider.signPSBT(serializedPsbt, { inputsToSign });
const hexPsbt = toHex(signedPsbt);

return {
psbt: hexPsbt,
};
};

sendTransfer = async (params: TransferParams) => {
throw new NotImplementedError();
};

getInscriptions = async (offset = 0, limit = 20) => {
if (!this.account?.address) {
throw new NoAddressError();
}

const inscriptions = await getInscriptionsByAddress({
address: this.account.address,
offset,
limit,
});
return inscriptions;
};
}
9 changes: 9 additions & 0 deletions packages/bitcoin/src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ export class NoInscriptionError extends Error {
this.name = this.constructor.name;
}
}

export class NotImplementedError extends Error {
name: string;

constructor(message = 'Not implemented') {
super(message);
this.name = this.constructor.name;
}
}
1 change: 1 addition & 0 deletions packages/bitcoin/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ declare interface Window {
unisat?: Unisat.Provider;
// TODO: 与其他 okx 冲突
okxwallet?: any;
phantom?: any;
}

declare namespace Unisat {
Expand Down
1 change: 1 addition & 0 deletions packages/bitcoin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './provider';
export * from './wallets';
export * from './types';
export * from './error';
export { useBitcoinWallet } from './adapter/useBitcoinWallet';
15 changes: 13 additions & 2 deletions packages/bitcoin/src/wallets/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
/* v8 ignore start */
import { metadata_OkxWallet, metadata_Unisat, metadata_Xverse } from '@ant-design/web3-assets';
import {
metadata_OkxWallet,
metadata_Phantom,
metadata_Unisat,
metadata_Xverse,
} from '@ant-design/web3-assets';

import { OkxBitcoinWallet, UnisatBitcoinWallet, XverseBitcoinWallet } from '../adapter';
import {
OkxBitcoinWallet,
PhantomBitcoinWallet,
UnisatBitcoinWallet,
XverseBitcoinWallet,
} from '../adapter';
import { WalletFactory } from './factory';

export const UnisatWallet = () => WalletFactory(UnisatBitcoinWallet, metadata_Unisat);
export const XverseWallet = () => WalletFactory(XverseBitcoinWallet, metadata_Xverse);
export const OkxWallet = () => WalletFactory(OkxBitcoinWallet, metadata_OkxWallet);
export const PhantomWallet = () => WalletFactory(PhantomBitcoinWallet, metadata_Phantom);
5 changes: 4 additions & 1 deletion packages/web3/src/bitcoin/demos/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ConnectButton, Connector } from '@ant-design/web3';
import {
BitcoinWeb3ConfigProvider,
OkxWallet,
PhantomWallet,
UnisatWallet,
XverseWallet,
} from '@ant-design/web3-bitcoin';
Expand All @@ -12,7 +13,9 @@ import {
*/
const App: React.FC = () => {
return (
<BitcoinWeb3ConfigProvider autoConnect wallets={[XverseWallet(), UnisatWallet(), OkxWallet()]}>
<BitcoinWeb3ConfigProvider
wallets={[XverseWallet(), UnisatWallet(), OkxWallet(), PhantomWallet()]}
>
<Connector
modalProps={{
group: false,
Expand Down
5 changes: 4 additions & 1 deletion packages/web3/src/bitcoin/demos/get-inscriptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ConnectButton, Connector, NFTImage } from '@ant-design/web3';
import {
BitcoinWeb3ConfigProvider,
OkxWallet,
PhantomWallet,
UnisatWallet,
useBitcoinWallet,
XverseWallet,
Expand Down Expand Up @@ -52,7 +53,9 @@ const GetInscriptions: React.FC = () => {
*/
const App: React.FC = () => {
return (
<BitcoinWeb3ConfigProvider wallets={[UnisatWallet(), XverseWallet(), OkxWallet()]}>
<BitcoinWeb3ConfigProvider
wallets={[UnisatWallet(), XverseWallet(), OkxWallet(), PhantomWallet()]}
>
<Space direction="vertical">
<Connector>
<ConnectButton />
Expand Down
12 changes: 11 additions & 1 deletion packages/web3/src/bitcoin/demos/send-transfer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ConnectButton, Connector } from '@ant-design/web3';
import {
BitcoinWeb3ConfigProvider,
NotImplementedError,
OkxWallet,
PhantomWallet,
UnisatWallet,
useBitcoinWallet,
XverseWallet,
Expand All @@ -25,6 +27,11 @@ const SendBitcoin: React.FC = () => {
sats: 10000,
});
} catch (error) {
if (error instanceof NotImplementedError) {
console.log('Not implemented');
return;
}

console.log('sign message error:', error);
}
}}
Expand All @@ -40,7 +47,10 @@ const SendBitcoin: React.FC = () => {
*/
const App: React.FC = () => {
return (
<BitcoinWeb3ConfigProvider wallets={[XverseWallet(), UnisatWallet(), OkxWallet()]} balance>
<BitcoinWeb3ConfigProvider
wallets={[XverseWallet(), UnisatWallet(), OkxWallet(), PhantomWallet()]}
balance
>
<Space>
<Connector>
<ConnectButton />
Expand Down
26 changes: 17 additions & 9 deletions packages/web3/src/bitcoin/demos/sign.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
import React from 'react';
import { ConnectButton, Connector } from '@ant-design/web3';
import { metadata_Phantom } from '@ant-design/web3-assets';
import {
BitcoinWeb3ConfigProvider,
OkxWallet,
PhantomWallet,
UnisatWallet,
useBitcoinWallet,
XverseWallet,
} from '@ant-design/web3-bitcoin';
import { Button, Space } from 'antd';

const PSBT_FOR_PHANTOM =
'70736274ff0100fd940102000000048a841e4104389e3b5b04c1522ed7bfc0e64c3760cb801a2ee2406d1c2373d81d0300000000ffffffff8a841e4104389e3b5b04c1522ed7bfc0e64c3760cb801a2ee2406d1c2373d81d0400000000ffffffffaf3341cffbd7ce8b4a51dec0f358a21809fad67be1a11bf70b86e83ec4567ace0100000000ffffffff8eceb072b7c47ebd9c1aa2e17c2541145835c70a8667eb21fa2ff3cac503170e0600000000ffffffff07b004000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed04a01000000000000225120b1a548f1672b6bc666e23943b0b138a4216e2ce5f9bc687469e0f52a917bbf274b0100000000000017a91433ab469b293fa7700f0954c96ec630895892f189874402000000000000160014c015c65276d5f38d599d445c4cb03aa7aa0dc3655802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed072fe050000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed000000000000100fdf50102000000000101a1f8bb2bde4e13b2f397a82a8a101b378e90af13354710b93742be79b773e3840000000000ffffffff0b5802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed00d4c070000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed00247304402204d2e9da8a14537a1c37b59e6a7eb828816249747dbec041315ade14a181c826a022044dcc381227cef6ab18431e692dccc7c27e2a10fed4d3131e0523094819d1dda0121028b8437ac47a4434d4b86d19ab7eeb255887f75cfa43ca135168bfc8281ae8bb90000000001011f5802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed0000100fdf50102000000000101a1f8bb2bde4e13b2f397a82a8a101b378e90af13354710b93742be79b773e3840000000000ffffffff0b5802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed00d4c070000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed00247304402204d2e9da8a14537a1c37b59e6a7eb828816249747dbec041315ade14a181c826a022044dcc381227cef6ab18431e692dccc7c27e2a10fed4d3131e0523094819d1dda0121028b8437ac47a4434d4b86d19ab7eeb255887f75cfa43ca135168bfc8281ae8bb90000000001011f5802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed0000100fd6f0302000000000104a81c37519eca22bd78a4705230dcc471fb59f285bb2f22165c803de5bbe10b4c08000000171600147e3a872889766d0e3aebacf19f7936fd659b2605ffffffffa81c37519eca22bd78a4705230dcc471fb59f285bb2f22165c803de5bbe10b4c03000000171600147e3a872889766d0e3aebacf19f7936fd659b2605ffffffff33ec9dbdfa3ecb3654683b54855eac430d41b9b87b028f8cc84c6766bf7cc3870100000000ffffffff14e64f84c47029f5b8687519707c6e18080f675f37323746c695a681b0fdfece06000000171600147e3a872889766d0e3aebacf19f7936fd659b2605ffffffff07b00400000000000017a91433ab469b293fa7700f0954c96ec630895892f189874a01000000000000225120a9af1fae42dbe9b0604e0ed64ae6e26d56d1c9bbcc4e1e66326914bdb5149606591a000000000000225120cfb72754409e197bce4ea0670bd4f977104bcc86f7ea65d8981609dc66e984454402000000000000160014c015c65276d5f38d599d445c4cb03aa7aa0dc365580200000000000017a91433ab469b293fa7700f0954c96ec630895892f18987580200000000000017a91433ab469b293fa7700f0954c96ec630895892f18987d8c300000000000017a91433ab469b293fa7700f0954c96ec630895892f189870247304402204c291efdec8e7442aef45ad4751938ae21b847bedde8ce8c9eb208f7a29537880220247a6767215d12c0c5ebc751b6386c50c3a9d5ba0792e0396e2ae420b736a5ab0121032765788cbacba654f3cdf679026db3cdb5a5d0310f870f4da223926a2813259902483045022100bceed8f98e1fbed310cfc01e2bdd3dcbd146064c6fc9d423e787367602d8df7c02204e300e2c9e6c4be50f2c9db54c2f6aeb5eae1897db38bf6406f16ee2e3de4f5e0121032765788cbacba654f3cdf679026db3cdb5a5d0310f870f4da223926a2813259901414045d5e077660865bde16a0af320b426f636b49ea7674f1cc1a9d7c86643638cdbb21c9a281c79aeaa118d833840eca4ec0b3cc6a807f1900bb7395ab4eb72ff830247304402204fdc2e31b88b42081c42dc6c249297aeffe1147071fa6994f95ded6257d93d9602205bf9c30fc7cf0d2b78a1e0027e1cc4eae6e45aef7281017fac932058ee1674d70121032765788cbacba654f3cdf679026db3cdb5a5d0310f870f4da223926a281325990000000001012b4a01000000000000225120a9af1fae42dbe9b0604e0ed64ae6e26d56d1c9bbcc4e1e66326914bdb51496060117207f003df863d4c17579f7b22f7498e39525b81c947aef234859b0466d3dd8dfb3000100fd2603020000000001048a841e4104389e3b5b04c1522ed7bfc0e64c3760cb801a2ee2406d1c2373d81d0800000000ffffffff8a841e4104389e3b5b04c1522ed7bfc0e64c3760cb801a2ee2406d1c2373d81d0500000000ffffffff9584f0b205109f6790fbf08f782166892f22facb8e2598b705cd9136b25aabc30000000000ffffffff4f4b0bbc053b9e3cb6261cb83c063481eba8a8a32a448c63f1c1218d6fe330380600000000ffffffff07b004000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed02202000000000000225120b1a548f1672b6bc666e23943b0b138a4216e2ce5f9bc687469e0f52a917bbf2775120000000000002251208ef171ead3a8f91d9dca9ae4b645537aafada16559f9f714cbe524ef672ab4144402000000000000160014c015c65276d5f38d599d445c4cb03aa7aa0dc3655802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed05802000000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed04057060000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed002483045022100a5cf71b0115db7980055fa9158c24fca9e3cc09cca0d1a0c54f17e8fa92d3e2402201b7dce27ff09e06c40a87b54aa2db693f49291e2f1a32f055155a3750607d01e0121028b8437ac47a4434d4b86d19ab7eeb255887f75cfa43ca135168bfc8281ae8bb902473044022049edbc2650ed737bad10d567c072da54c6b592fcfe2240fabcd49d8aa176422102206c8101ba6f8d6a155ed916ca7b25bf69395d76c020cb6ed9cf8293d65870346e0121028b8437ac47a4434d4b86d19ab7eeb255887f75cfa43ca135168bfc8281ae8bb901410a4a56764a5f9ed3fee4a869f6edee7b9b72f87bdba96d08310191a6df94bcf56f32152e63a836844cea71611886e3f96f74a2cc06d88ddf508184857f5fb4138302473044022075b779781668f4a487c2308aca9217125b897d089f617d831122612db02a672402200ef61ec6ddb6cac999e528e9e4fe27acb0a1cba4f8b33204b180ee458a8d82790121028b8437ac47a4434d4b86d19ab7eeb255887f75cfa43ca135168bfc8281ae8bb90000000001011f4057060000000000160014b2c9b35e4b02e8b16236ae5c0540cf2d56605ed00000000000000000';

const PSBT =
'cHNidP8BAF4CAAAAAa/v4ZPYjm+iJc1pB3IybYY6wPpScPDlxvHmNE557J2vAQAAAAD/////AWqKAAAAAAAAIlEgZDcUdAs/gCZIkazJyMw1I54n2QGxN1W2ph6m+4zYHBkAAAAACPwCbWUDc2lnQE+yrULMRi3UwxQDf8idtfykJVzjE08jIP9fdU/6yvEfdlqCAWNwXFgSx1Nb7jrfPFYlY7gLaQ87EpcDpwaLdzQL/AJtZQZzaWdleHAIQnj3E+QqoAAAAQErIgIAAAAAAAAiUSBkNxR0Cz+AJkiRrMnIzDUjnifZAbE3VbamHqb7jNgcGQEDBIMAAAABFyCauIGVY+9bxYwyEp3poW+sSayOhwQuSrI4DnH80/zCuwAA';

/**
* Component to sign a message.
* @returns {JSX.Element | null} The rendered component.
*/
const SignMessage: React.FC = () => {
const { signMessage, account } = useBitcoinWallet();

return account ? (
<Button
onClick={async () => {
Expand All @@ -32,19 +41,17 @@ const SignMessage: React.FC = () => {

/**
* Component to sign a PSBT (Partially Signed Bitcoin Transaction).
* @returns {JSX.Element | null} The rendered component.
*/
const SignPsbt: React.FC = () => {
const { signPsbt, account } = useBitcoinWallet();
const { signPsbt, account, name: walletName } = useBitcoinWallet();

// You can use libraries like 'bitcoinjs-lib' or 'scure-btc-signer' to create PSBTs.
// This is a real PSBT base64 data for example.
const psbt =
'cHNidP8BAF4CAAAAAa/v4ZPYjm+iJc1pB3IybYY6wPpScPDlxvHmNE557J2vAQAAAAD/////AWqKAAAAAAAAIlEgZDcUdAs/gCZIkazJyMw1I54n2QGxN1W2ph6m+4zYHBkAAAAACPwCbWUDc2lnQE+yrULMRi3UwxQDf8idtfykJVzjE08jIP9fdU/6yvEfdlqCAWNwXFgSx1Nb7jrfPFYlY7gLaQ87EpcDpwaLdzQL/AJtZQZzaWdleHAIQnj3E+QqoAAAAQErIgIAAAAAAAAiUSBkNxR0Cz+AJkiRrMnIzDUjnifZAbE3VbamHqb7jNgcGQEDBIMAAAABFyCauIGVY+9bxYwyEp3poW+sSayOhwQuSrI4DnH80/zCuwAA';
return account ? (
<Button
onClick={async () => {
try {
// You can use libraries like 'bitcoinjs-lib' or 'scure-btc-signer' to create PSBTs.
// This is a real PSBT base64 data for example.
const psbt = walletName === metadata_Phantom.name ? PSBT_FOR_PHANTOM : PSBT;
const result = await signPsbt?.({ psbt });
console.log('sign psbt success!', result);
} catch (error) {
Expand All @@ -59,11 +66,12 @@ const SignPsbt: React.FC = () => {

/**
* Main application component that sets up the BitcoinWeb3ConfigProvider and Connector.
* @returns {JSX.Element} The rendered application component.
*/
const App: React.FC = () => {
return (
<BitcoinWeb3ConfigProvider wallets={[XverseWallet(), UnisatWallet(), OkxWallet()]}>
<BitcoinWeb3ConfigProvider
wallets={[XverseWallet(), UnisatWallet(), OkxWallet(), PhantomWallet()]}
>
<Space>
<Connector>
<ConnectButton />
Expand Down
5 changes: 5 additions & 0 deletions packages/web3/src/bitcoin/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,22 @@ The wallets currently supported are as follows, and we also welcome you to submi
- [Xverse](https://docs.xverse.app/sats-connect)
- [OKX](https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider)
- [Unisat](https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet)
- [Phantom](https://docs.phantom.app/bitcoin/integrating-phantom)

## WalletConnect

<code src="./demos/basic.tsx"></code>

## SignMessage / SignPsbt

> Phantom currently only provides partial support for PSBT, please test it fully before using it.
<code src="./demos/sign.tsx"></code>

## SendTransfer

> If the wallet does not yet support `sendTransfer`, a `NotImplementedError` will be thrown.
<code src="./demos/send-transfer.tsx"></code>

## GetInscriptions
Expand Down
5 changes: 5 additions & 0 deletions packages/web3/src/bitcoin/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,22 @@ Ant Design Web3 官方提供了 `@ant-design/web3-bitcoin` 来适配比特币,
- [Xverse](https://docs.xverse.app/sats-connect)
- [OKX](https://www.okx.com/web3/build/docs/sdks/chains/bitcoin/provider)
- [Unisat](https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet)
- [Phantom](https://docs.phantom.app/bitcoin/integrating-phantom)

## 连接钱包

<code src="./demos/basic.tsx"></code>

## 签名 / PSBT

> Phantom 目前仅对 PSBT 提供部分支持,使用之前请充分测试。
<code src="./demos/sign.tsx"></code>

## 发送交易

> 如果钱包暂未支持 `sendTransfer`,将会抛出 `NotImplementedError`
<code src="./demos/send-transfer.tsx"></code>

## 获取铭文信息展示
Expand Down
Loading

0 comments on commit 80f0dc2

Please sign in to comment.