bitcoin-wallet-connector 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +208 -0
  2. package/lib/BitcoinConnectionProvider.d.ts +23 -0
  3. package/lib/BitcoinWalletAdapterConnector-Bq835yj0.mjs +123 -0
  4. package/lib/BitcoinWalletAdapterConnector-Bq835yj0.mjs.map +1 -0
  5. package/lib/BitcoinWalletAdapterConnector-DMef0iHV.js +2 -0
  6. package/lib/BitcoinWalletAdapterConnector-DMef0iHV.js.map +1 -0
  7. package/lib/BitcoinWalletAdapterConnector.d.ts +30 -0
  8. package/lib/BitgetWalletAdapter.impl-C_HLO7Oi.mjs +10 -0
  9. package/lib/BitgetWalletAdapter.impl-C_HLO7Oi.mjs.map +1 -0
  10. package/lib/BitgetWalletAdapter.impl-CxnKMf7U.js +2 -0
  11. package/lib/BitgetWalletAdapter.impl-CxnKMf7U.js.map +1 -0
  12. package/lib/LeatherWalletAdapter.impl-B2QgX_tO.js +2 -0
  13. package/lib/LeatherWalletAdapter.impl-B2QgX_tO.js.map +1 -0
  14. package/lib/LeatherWalletAdapter.impl-RUYx555r.mjs +184 -0
  15. package/lib/LeatherWalletAdapter.impl-RUYx555r.mjs.map +1 -0
  16. package/lib/MagicEdenWalletAdapter.impl-CrA6SGvG.mjs +235 -0
  17. package/lib/MagicEdenWalletAdapter.impl-CrA6SGvG.mjs.map +1 -0
  18. package/lib/MagicEdenWalletAdapter.impl-Di3Nu2S5.js +2 -0
  19. package/lib/MagicEdenWalletAdapter.impl-Di3Nu2S5.js.map +1 -0
  20. package/lib/OkxWalletAdapter.impl-BepoUL1B.mjs +67 -0
  21. package/lib/OkxWalletAdapter.impl-BepoUL1B.mjs.map +1 -0
  22. package/lib/OkxWalletAdapter.impl-C8kesjGu.js +2 -0
  23. package/lib/OkxWalletAdapter.impl-C8kesjGu.js.map +1 -0
  24. package/lib/UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js +2 -0
  25. package/lib/UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js.map +1 -0
  26. package/lib/UnisatCompatibleWalletAdapterImpl-M38FqkZI.mjs +137 -0
  27. package/lib/UnisatCompatibleWalletAdapterImpl-M38FqkZI.mjs.map +1 -0
  28. package/lib/UnisatWalletAdapter.impl-CJB22se8.mjs +14 -0
  29. package/lib/UnisatWalletAdapter.impl-CJB22se8.mjs.map +1 -0
  30. package/lib/UnisatWalletAdapter.impl-EISvxdpc.js +2 -0
  31. package/lib/UnisatWalletAdapter.impl-EISvxdpc.js.map +1 -0
  32. package/lib/WalletAdapters.types-CnvOqHFH.mjs +32 -0
  33. package/lib/WalletAdapters.types-CnvOqHFH.mjs.map +1 -0
  34. package/lib/WalletAdapters.types-De_x1lzr.js +2 -0
  35. package/lib/WalletAdapters.types-De_x1lzr.js.map +1 -0
  36. package/lib/WalletAdapters.types.d.ts +110 -0
  37. package/lib/XverseCompatibleWalletAdapterImpl-Bf-BK5VK.js +2 -0
  38. package/lib/XverseCompatibleWalletAdapterImpl-Bf-BK5VK.js.map +1 -0
  39. package/lib/XverseCompatibleWalletAdapterImpl-DXKnO_-V.mjs +151 -0
  40. package/lib/XverseCompatibleWalletAdapterImpl-DXKnO_-V.mjs.map +1 -0
  41. package/lib/XverseWalletAdapter.impl-CZO0RQva.mjs +105 -0
  42. package/lib/XverseWalletAdapter.impl-CZO0RQva.mjs.map +1 -0
  43. package/lib/XverseWalletAdapter.impl-lJwMi-Iv.js +2 -0
  44. package/lib/XverseWalletAdapter.impl-lJwMi-Iv.js.map +1 -0
  45. package/lib/adapters/BitgetWalletAdapter.d.ts +2 -0
  46. package/lib/adapters/BitgetWalletAdapter.impl.d.ts +8 -0
  47. package/lib/adapters/LeatherWalletAdapter.d.ts +2 -0
  48. package/lib/adapters/LeatherWalletAdapter.impl.d.ts +41 -0
  49. package/lib/adapters/MagicEdenWalletAdapter.d.ts +11 -0
  50. package/lib/adapters/MagicEdenWalletAdapter.impl.d.ts +22 -0
  51. package/lib/adapters/MockAddressWalletAdapter.d.ts +33 -0
  52. package/lib/adapters/OkxWalletAdapter.d.ts +2 -0
  53. package/lib/adapters/OkxWalletAdapter.impl.d.ts +51 -0
  54. package/lib/adapters/UnisatWalletAdapter.d.ts +2 -0
  55. package/lib/adapters/UnisatWalletAdapter.impl.d.ts +14 -0
  56. package/lib/adapters/XverseWalletAdapter.d.ts +3 -0
  57. package/lib/adapters/XverseWalletAdapter.impl.d.ts +14 -0
  58. package/lib/adapters/index.d.ts +7 -0
  59. package/lib/adapters.js +2 -0
  60. package/lib/adapters.js.map +1 -0
  61. package/lib/adapters.mjs +11 -0
  62. package/lib/adapters.mjs.map +1 -0
  63. package/lib/bitget-C7oB4Ffq.mjs +5 -0
  64. package/lib/bitget-C7oB4Ffq.mjs.map +1 -0
  65. package/lib/bitget-DXnsxx_y.js +2 -0
  66. package/lib/bitget-DXnsxx_y.js.map +1 -0
  67. package/lib/index-CaV3F1Nm.js +424 -0
  68. package/lib/index-CaV3F1Nm.js.map +1 -0
  69. package/lib/index-CcQUdePc.mjs +12224 -0
  70. package/lib/index-CcQUdePc.mjs.map +1 -0
  71. package/lib/index-D7YwhNAG.mjs +3946 -0
  72. package/lib/index-D7YwhNAG.mjs.map +1 -0
  73. package/lib/index-Zx0KcpYx.js +2 -0
  74. package/lib/index-Zx0KcpYx.js.map +1 -0
  75. package/lib/index.d.ts +3 -0
  76. package/lib/index.js +2 -0
  77. package/lib/index.js.map +1 -0
  78. package/lib/index.mjs +20 -0
  79. package/lib/index.mjs.map +1 -0
  80. package/lib/leather-BoQG_CPn.mjs +5 -0
  81. package/lib/leather-BoQG_CPn.mjs.map +1 -0
  82. package/lib/leather-DJ8nWmM8.js +2 -0
  83. package/lib/leather-DJ8nWmM8.js.map +1 -0
  84. package/lib/magiceden-B36CEQa6.js +2 -0
  85. package/lib/magiceden-B36CEQa6.js.map +1 -0
  86. package/lib/magiceden-Cg7d3agI.mjs +5 -0
  87. package/lib/magiceden-Cg7d3agI.mjs.map +1 -0
  88. package/lib/misc-B5EWO_dn.mjs +10 -0
  89. package/lib/misc-B5EWO_dn.mjs.map +1 -0
  90. package/lib/misc-CigR0RqC.js +2 -0
  91. package/lib/misc-CigR0RqC.js.map +1 -0
  92. package/lib/okx-ChwzM0dK.js +2 -0
  93. package/lib/okx-ChwzM0dK.js.map +1 -0
  94. package/lib/okx-DWbHwazu.mjs +5 -0
  95. package/lib/okx-DWbHwazu.mjs.map +1 -0
  96. package/lib/react.d.ts +2 -0
  97. package/lib/react.js +2 -0
  98. package/lib/react.js.map +1 -0
  99. package/lib/react.mjs +128 -0
  100. package/lib/react.mjs.map +1 -0
  101. package/lib/transaction-CiLOYSE_.mjs +1063 -0
  102. package/lib/transaction-CiLOYSE_.mjs.map +1 -0
  103. package/lib/transaction-CzdnbXSo.js +2 -0
  104. package/lib/transaction-CzdnbXSo.js.map +1 -0
  105. package/lib/unisat-BvZW5h0U.js +2 -0
  106. package/lib/unisat-BvZW5h0U.js.map +1 -0
  107. package/lib/unisat-pLgab4nG.mjs +5 -0
  108. package/lib/unisat-pLgab4nG.mjs.map +1 -0
  109. package/lib/utils/StateChannel.d.ts +14 -0
  110. package/lib/utils/UnisatCompatibleWalletAdapterImpl.d.ts +99 -0
  111. package/lib/utils/XverseCompatibleWalletAdapterImpl.d.ts +80 -0
  112. package/lib/utils/XverseCompatibleWalletAdapterImpl_legacy.d.ts +44 -0
  113. package/lib/utils/bitcoinAddressHelpers.d.ts +14 -0
  114. package/lib/utils/bitcoinNetworkHelpers.d.ts +4 -0
  115. package/lib/utils/createAdapterAvailability.d.ts +15 -0
  116. package/lib/utils/error.d.ts +6 -0
  117. package/lib/utils/misc.d.ts +3 -0
  118. package/lib/xverse-IKOHyGi-.js +2 -0
  119. package/lib/xverse-IKOHyGi-.js.map +1 -0
  120. package/lib/xverse-iHLNanCB.mjs +5 -0
  121. package/lib/xverse-iHLNanCB.mjs.map +1 -0
  122. package/package.json +86 -0
  123. package/src/BitcoinConnectionProvider.stories.tsx +329 -0
  124. package/src/BitcoinConnectionProvider.tsx +234 -0
  125. package/src/BitcoinWalletAdapterConnector.ts +166 -0
  126. package/src/WalletAdapters.types.ts +154 -0
  127. package/src/_/bitget.png +0 -0
  128. package/src/_/leather.svg +4 -0
  129. package/src/_/magiceden.png +0 -0
  130. package/src/_/okx.png +0 -0
  131. package/src/_/unisat.svg +31 -0
  132. package/src/_/xverse.png +0 -0
  133. package/src/adapters/BitgetWalletAdapter.impl.ts +22 -0
  134. package/src/adapters/BitgetWalletAdapter.ts +44 -0
  135. package/src/adapters/LeatherWalletAdapter.impl.ts +324 -0
  136. package/src/adapters/LeatherWalletAdapter.ts +35 -0
  137. package/src/adapters/MagicEdenWalletAdapter.impl.ts +139 -0
  138. package/src/adapters/MagicEdenWalletAdapter.ts +51 -0
  139. package/src/adapters/MockAddressWalletAdapter.ts +199 -0
  140. package/src/adapters/OkxWalletAdapter.impl.ts +168 -0
  141. package/src/adapters/OkxWalletAdapter.ts +37 -0
  142. package/src/adapters/UnisatWalletAdapter.impl.ts +32 -0
  143. package/src/adapters/UnisatWalletAdapter.ts +50 -0
  144. package/src/adapters/XverseWalletAdapter.impl.ts +150 -0
  145. package/src/adapters/XverseWalletAdapter.ts +37 -0
  146. package/src/adapters/index.ts +7 -0
  147. package/src/env.d.ts +9 -0
  148. package/src/index.ts +3 -0
  149. package/src/react.ts +9 -0
  150. package/src/utils/StateChannel.ts +39 -0
  151. package/src/utils/UnisatCompatibleWalletAdapterImpl.ts +342 -0
  152. package/src/utils/XverseCompatibleWalletAdapterImpl.ts +288 -0
  153. package/src/utils/XverseCompatibleWalletAdapterImpl_legacy.ts +278 -0
  154. package/src/utils/bitcoinAddressHelpers.ts +132 -0
  155. package/src/utils/bitcoinNetworkHelpers.ts +17 -0
  156. package/src/utils/createAdapterAvailability.ts +92 -0
  157. package/src/utils/error.ts +13 -0
  158. package/src/utils/misc.ts +10 -0
@@ -0,0 +1,199 @@
1
+ import { hex } from "@scure/base"
2
+ import { Script } from "@scure/btc-signer"
3
+ import {
4
+ addressToScriptPubKeyHex,
5
+ getAddressType,
6
+ } from "../utils/bitcoinAddressHelpers"
7
+ import { BitcoinNetwork, isMainnet } from "../utils/bitcoinNetworkHelpers"
8
+ import { BitcoinWalletAdapterError } from "../utils/error"
9
+ import { checkNever } from "../utils/misc"
10
+ import {
11
+ SignMessageResult,
12
+ WalletAdapter,
13
+ WalletAdapter_onAddressesChanged_callback,
14
+ WalletAdapterAddress,
15
+ WalletAdapterAddressPurpose,
16
+ WalletAdapterAddressType,
17
+ WalletAdapterBitcoinNetwork,
18
+ } from "../WalletAdapters.types"
19
+
20
+ const randomTapInternalKey =
21
+ "0000000000000000000000000000000000000000000000000000000000000000"
22
+
23
+ const randomPublicKey =
24
+ "0000000000000000000000000000000000000000000000000000000000000000"
25
+
26
+ const randomRedeemScript = hex.encode(
27
+ Script.encode(["OP_1", hex.decode(randomPublicKey), "OP_1", "CHECKMULTISIG"]),
28
+ )
29
+
30
+ export class MockAddressWalletAdapter implements WalletAdapter {
31
+ constructor(
32
+ private network: BitcoinNetwork,
33
+ private inner: WalletAdapter,
34
+ private addresses: Partial<{
35
+ bitcoin: Partial<WalletAdapterAddress> & { address: string }
36
+ ordinals: Partial<WalletAdapterAddress> & { address: string }
37
+ }>,
38
+ ) {}
39
+
40
+ async connect(): Promise<void> {
41
+ await this.inner.connect()
42
+ }
43
+
44
+ async disconnect(): Promise<void> {
45
+ await this.inner.disconnect()
46
+ }
47
+
48
+ async getAddresses(): Promise<WalletAdapterAddress[]> {
49
+ const addresses = await this.inner.getAddresses()
50
+
51
+ const getWalletAdapterAddress = (
52
+ addressName: string,
53
+ info: {
54
+ address: string
55
+ purposes: WalletAdapterAddressPurpose[]
56
+ },
57
+ ): WalletAdapterAddress => {
58
+ const addrType = getAddressType(this.network, info.address)
59
+
60
+ // prettier-ignore
61
+ const addressType =
62
+ addrType === "p2tr" ? WalletAdapterAddressType.P2TR :
63
+ addrType === "p2sh" ? WalletAdapterAddressType.P2SH_P2WPKH :
64
+ addrType === "p2wpkh" ? WalletAdapterAddressType.P2WPKH :
65
+ addrType === 'p2pkh' ? WalletAdapterAddressType.P2PKH :
66
+ addrType === 'p2wsh' ? undefined /* unsupported */ :
67
+ addrType === 'unknown' ? undefined :
68
+ (checkNever(addrType), undefined)
69
+
70
+ if (addressType == null) {
71
+ throw new BitcoinWalletAdapterError(
72
+ `[MockAddressWalletAdapter] Please provide a supported ${addressName} address`,
73
+ )
74
+ }
75
+
76
+ return {
77
+ network: isMainnet(this.network)
78
+ ? WalletAdapterBitcoinNetwork.MAINNET
79
+ : WalletAdapterBitcoinNetwork.TESTNET,
80
+ purposes: info.purposes,
81
+ addressType,
82
+ address: info.address,
83
+ scriptPubKey: addressToScriptPubKeyHex(this.network, info.address),
84
+ publicKey: randomPublicKey,
85
+ redeemScript: randomRedeemScript,
86
+ tapInternalKey: randomTapInternalKey,
87
+ }
88
+ }
89
+
90
+ let bitcoinAddress: undefined | WalletAdapterAddress
91
+ let ordinalsAddress: undefined | WalletAdapterAddress
92
+
93
+ if (this.addresses.bitcoin != null) {
94
+ bitcoinAddress = getWalletAdapterAddress("bitcoin", {
95
+ ...this.addresses.bitcoin,
96
+ purposes: [WalletAdapterAddressPurpose.Bitcoin],
97
+ })
98
+ }
99
+
100
+ if (this.addresses.ordinals != null) {
101
+ ordinalsAddress = getWalletAdapterAddress("ordinals", {
102
+ ...this.addresses.ordinals,
103
+ purposes: [
104
+ WalletAdapterAddressPurpose.Ordinals,
105
+ WalletAdapterAddressPurpose.BRC20,
106
+ WalletAdapterAddressPurpose.Runes,
107
+ ],
108
+ })
109
+ }
110
+
111
+ return addresses.flatMap(a => {
112
+ const result: WalletAdapterAddress[] = []
113
+ let restPurposes = a.purposes
114
+
115
+ if (
116
+ bitcoinAddress != null &&
117
+ restPurposes.includes(WalletAdapterAddressPurpose.Bitcoin)
118
+ ) {
119
+ result.push(bitcoinAddress)
120
+ restPurposes = restPurposes.filter(
121
+ p => p !== WalletAdapterAddressPurpose.Bitcoin,
122
+ )
123
+ }
124
+
125
+ if (
126
+ ordinalsAddress != null &&
127
+ restPurposes.includes(WalletAdapterAddressPurpose.Ordinals)
128
+ ) {
129
+ result.push(ordinalsAddress)
130
+ restPurposes = restPurposes.filter(
131
+ p => p !== WalletAdapterAddressPurpose.Ordinals,
132
+ )
133
+ }
134
+
135
+ if (restPurposes.length > 0) {
136
+ result.push({ ...a, purposes: restPurposes })
137
+ }
138
+
139
+ return result
140
+ })
141
+ }
142
+
143
+ async signMessage(
144
+ address: string,
145
+ message: string,
146
+ ): Promise<SignMessageResult> {
147
+ throw new BitcoinWalletAdapterError(
148
+ `[MockAddressWalletAdapter] it's a mock adapter, can't send inscription`,
149
+ )
150
+ }
151
+
152
+ get sendBitcoinFeeRateCapability(): "unavailable" | "available" | "required" {
153
+ return this.inner.sendBitcoinFeeRateCapability
154
+ }
155
+
156
+ get sendInscriptionFeeRateCapability():
157
+ | "unavailable"
158
+ | "available"
159
+ | "required" {
160
+ return this.inner.sendInscriptionFeeRateCapability
161
+ }
162
+
163
+ sendBitcoin(
164
+ fromAddress: string,
165
+ receiverAddress: string,
166
+ satoshiAmount: bigint,
167
+ ): Promise<{ txid: string }> {
168
+ throw new BitcoinWalletAdapterError(
169
+ `[MockAddressWalletAdapter] it's a mock adapter, can't send bitcoin`,
170
+ )
171
+ }
172
+
173
+ sendInscription(
174
+ fromAddress: string,
175
+ receiverAddress: string,
176
+ inscriptionId: string,
177
+ ): Promise<{ txid: string }> {
178
+ throw new BitcoinWalletAdapterError(
179
+ `[MockAddressWalletAdapter] it's a mock adapter, can't send inscription`,
180
+ )
181
+ }
182
+
183
+ signAndFinalizePsbt(psbtHex: string): Promise<{ signedPsbtHex: string }> {
184
+ throw new BitcoinWalletAdapterError(
185
+ `[MockAddressWalletAdapter] it's a mock adapter, can't sign transaction`,
186
+ )
187
+ }
188
+
189
+ onAddressesChanged(_callback: WalletAdapter_onAddressesChanged_callback): {
190
+ unsubscribe: () => void
191
+ } {
192
+ // Mock adapter doesn't support address change events
193
+ return {
194
+ unsubscribe: () => {
195
+ // No-op
196
+ },
197
+ }
198
+ }
199
+ }
@@ -0,0 +1,168 @@
1
+ import { UserRejectError, BitcoinWalletAdapterError } from "../utils/error"
2
+ import {
3
+ SignMessageResult,
4
+ WalletAdapter,
5
+ WalletAdapter_onAddressesChanged_callback,
6
+ } from "../WalletAdapters.types"
7
+ import {
8
+ UniSatEvents,
9
+ UnisatCompatibleProviderAPI,
10
+ UnisatCompatibleWalletAdapterImpl,
11
+ } from "../utils/UnisatCompatibleWalletAdapterImpl"
12
+
13
+ enum RpcErrorCode {
14
+ PARSE_ERROR = -32700,
15
+ INVALID_REQUEST = -32600,
16
+ METHOD_NOT_FOUND = -32601,
17
+ INVALID_PARAMS = -32602,
18
+ INTERNAL_ERROR = -32603,
19
+ SERVER_ERROR = -32000,
20
+ USER_REJECTION = 4001,
21
+ METHOD_NOT_SUPPORTED = 4002,
22
+ }
23
+
24
+ interface RpcError<TErrorData = unknown> {
25
+ code: number | RpcErrorCode
26
+ message: string
27
+ data?: TErrorData
28
+ }
29
+
30
+ interface OkxBitcoinProvider
31
+ extends UnisatCompatibleProviderAPI, Record<string, any> {
32
+ connect(): Promise<void>
33
+ on<K extends keyof UniSatEvents>(
34
+ event: K,
35
+ handler: (...args: UniSatEvents[K]) => void,
36
+ ): void
37
+ on(event: "accountChanged" | "networkChanged", handler: () => void): void
38
+ removeListener<K extends keyof UniSatEvents>(
39
+ event: K,
40
+ handler: (...args: UniSatEvents[K]) => void,
41
+ ): void
42
+ removeListener(
43
+ event: "accountChanged" | "networkChanged",
44
+ handler: () => void,
45
+ ): void
46
+ }
47
+
48
+ export class OkxWalletAdapterImpl
49
+ extends UnisatCompatibleWalletAdapterImpl
50
+ implements WalletAdapter
51
+ {
52
+ private okxwallet: OkxBitcoinProvider
53
+ constructor(provider: OkxBitcoinProvider) {
54
+ /**
55
+ * OKX Provider API:
56
+ *
57
+ * https://web3.okx.com/zh-hans/build/dev-docs/sdks/chains/bitcoin/provider
58
+ */
59
+ super(provider, "OKX")
60
+ this.okxwallet = provider
61
+ }
62
+
63
+ async connect(): Promise<void> {
64
+ // if not authorized, okx wallet will pop up a window to ask user to authorize
65
+ // if authorized, okx wallet will do nothing
66
+ await this.okxwallet.connect()
67
+ }
68
+
69
+ async signMessage(
70
+ address: string,
71
+ message: string,
72
+ ): Promise<SignMessageResult> {
73
+ return handleRpcError(super.signMessage(address, message))
74
+ }
75
+
76
+ async sendBitcoin(
77
+ fromAddress: string,
78
+ receiverAddress: string,
79
+ satoshiAmount: bigint,
80
+ options?: { feeRate?: number },
81
+ ): Promise<{
82
+ txid: string
83
+ }> {
84
+ return handleRpcError(
85
+ super.sendBitcoin(fromAddress, receiverAddress, satoshiAmount, options),
86
+ )
87
+ }
88
+
89
+ async sendInscription(
90
+ fromAddress: string,
91
+ receiverAddress: string,
92
+ inscriptionId: string,
93
+ options?: { feeRate?: number },
94
+ ): Promise<{
95
+ txid: string
96
+ }> {
97
+ return handleRpcError(
98
+ super.sendInscription(
99
+ fromAddress,
100
+ receiverAddress,
101
+ inscriptionId,
102
+ options,
103
+ ),
104
+ )
105
+ }
106
+
107
+ async signAndFinalizePsbt(
108
+ psbtHex: string,
109
+ signIndices: [address: string, signIndex: number][],
110
+ ): Promise<{
111
+ signedPsbtHex: string
112
+ }> {
113
+ return handleRpcError(super.signAndFinalizePsbt(psbtHex, signIndices))
114
+ }
115
+
116
+ onAddressesChanged(callback: WalletAdapter_onAddressesChanged_callback): {
117
+ unsubscribe: () => void
118
+ } {
119
+ // OKX uses 'accountChanged' (no 's') and 'networkChanged' events
120
+ // https://web3.okx.com/build/dev-docs/sdks/chains/bitcoin/provider
121
+ if (this.okxwallet?.on && this.okxwallet?.removeListener) {
122
+ const handler = async (): Promise<void> => {
123
+ try {
124
+ const addresses = await this.getAddresses()
125
+ callback({ addresses })
126
+ } catch (error) {
127
+ console.warn("[OKX] Failed to get addresses on change:", error)
128
+ }
129
+ }
130
+
131
+ // Listen to account and network changes (OKX uses 'accountChanged' not 'accountsChanged')
132
+ this.okxwallet.on("accountChanged", handler)
133
+ this.okxwallet.on("networkChanged", handler)
134
+
135
+ return {
136
+ unsubscribe: () => {
137
+ this.okxwallet.removeListener("accountChanged", handler)
138
+ this.okxwallet.removeListener("networkChanged", handler)
139
+ },
140
+ }
141
+ } else {
142
+ // Fallback to parent implementation (polling)
143
+ return super.onAddressesChanged(callback)
144
+ }
145
+ }
146
+ }
147
+
148
+ export class OkxWalletAdapterError extends BitcoinWalletAdapterError {
149
+ constructor(rpcError: RpcError) {
150
+ super("OKX wallet error: " + rpcError.message, { cause: rpcError })
151
+ }
152
+ }
153
+
154
+ const handleRpcError = async <T>(promise: Promise<T>): Promise<T> => {
155
+ try {
156
+ return await promise
157
+ } catch (e: any) {
158
+ if (e instanceof UserRejectError) {
159
+ throw e
160
+ }
161
+
162
+ if (e.code === RpcErrorCode.USER_REJECTION) {
163
+ throw new UserRejectError()
164
+ }
165
+
166
+ throw new OkxWalletAdapterError(e)
167
+ }
168
+ }
@@ -0,0 +1,37 @@
1
+ import type {
2
+ WalletAdapter,
3
+ WalletAdapterStatic,
4
+ } from "../WalletAdapters.types"
5
+ import type { UnisatCompatibleProviderAPI } from "../utils/UnisatCompatibleWalletAdapterImpl"
6
+ import { createAvailability } from "../utils/createAdapterAvailability"
7
+
8
+ const adapterId = "okxwallet.bitcoin"
9
+
10
+ const metadata = {
11
+ name: "OKX Wallet",
12
+ iconUrl: import("../_/okx.png").then(m => m.default),
13
+ websiteUrl: "https://web3.okx.com/",
14
+ downloadUrl: "https://web3.okx.com/download",
15
+ }
16
+
17
+ const availability = createAvailability<
18
+ UnisatCompatibleProviderAPI,
19
+ WalletAdapter
20
+ >({
21
+ getPrecondition: () => {
22
+ const provider = (window as any).okxwallet?.bitcoin as
23
+ | UnisatCompatibleProviderAPI
24
+ | undefined
25
+ return provider == null ? null : { value: provider }
26
+ },
27
+ initializer: async provider => {
28
+ const { OkxWalletAdapterImpl } = await import("./OkxWalletAdapter.impl")
29
+ return new OkxWalletAdapterImpl(provider as any)
30
+ },
31
+ })
32
+
33
+ export const OkxWalletAdapter: WalletAdapterStatic<WalletAdapter> = {
34
+ adapterId,
35
+ metadata,
36
+ getAdapter: () => availability,
37
+ }
@@ -0,0 +1,32 @@
1
+ import {
2
+ UnisatCompatibleProviderAPI,
3
+ UnisatCompatibleWalletAdapterImpl,
4
+ } from "../utils/UnisatCompatibleWalletAdapterImpl"
5
+ import { WalletAdapter } from "../WalletAdapters.types"
6
+
7
+ /**
8
+ * Derivation path (Native SegWit) (BIP-84): m/84'/0'/0'/0/address_index
9
+ * Derivation path (Nested SegWit) (BIP-49): m/49'/0'/0'/0/address_index
10
+ * Derivation path (Taproot) (BIP-86): m/86'/0'/0'/0/address_index
11
+ * Derivation path (Taproot) (BIP-44): m/44'/0'/0'/0/address_index
12
+ * Derivation path (Legacy) (BIP-44): m/44'/0'/0'/0/address_index
13
+ */
14
+ export class UnisatWalletAdapterImpl
15
+ extends UnisatCompatibleWalletAdapterImpl
16
+ implements WalletAdapter
17
+ {
18
+ constructor(provider: UnisatCompatibleProviderAPI) {
19
+ /**
20
+ * UniSat Provider API:
21
+ *
22
+ * https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet
23
+ */
24
+ super(provider, "UniSat")
25
+ }
26
+
27
+ sendBitcoinFeeRateCapability = "required" as const
28
+
29
+ // The default fee rate of unisat is not aligned with mempool.space, so
30
+ // sometimes the tx will be rejected by mempool due to uneligible network fee.
31
+ sendInscriptionFeeRateCapability = "unavailable" as const
32
+ }
@@ -0,0 +1,50 @@
1
+ import { createAvailability } from "../utils/createAdapterAvailability"
2
+ import type { UnisatCompatibleProviderAPI } from "../utils/UnisatCompatibleWalletAdapterImpl"
3
+ import type {
4
+ WalletAdapter,
5
+ WalletAdapterMetadata,
6
+ WalletAdapterStatic,
7
+ } from "../WalletAdapters.types"
8
+
9
+ /**
10
+ * Derivation path (Native SegWit) (BIP-84): m/84'/0'/0'/0/address_index
11
+ * Derivation path (Nested SegWit) (BIP-49): m/49'/0'/0'/0/address_index
12
+ * Derivation path (Taproot) (BIP-86): m/86'/0'/0'/0/address_index
13
+ * Derivation path (Taproot) (BIP-44): m/44'/0'/0'/0/address_index
14
+ * Derivation path (Legacy) (BIP-44): m/44'/0'/0'/0/address_index
15
+ */
16
+
17
+ const adapterId = "unisat"
18
+
19
+ const metadata: WalletAdapterMetadata = {
20
+ name: "UniSat",
21
+ /**
22
+ * https://next-cdn.unisat.io/_/2025-v965/UniSat%20Logo.zip
23
+ */
24
+ iconUrl: import("../_/unisat.svg").then(m => m.default),
25
+ websiteUrl: "https://unisat.io/",
26
+ downloadUrl: "https://unisat.io/download",
27
+ }
28
+
29
+ const availability = createAvailability<
30
+ UnisatCompatibleProviderAPI,
31
+ WalletAdapter
32
+ >({
33
+ getPrecondition: () => {
34
+ const provider = (window as any).unisat as
35
+ | UnisatCompatibleProviderAPI
36
+ | undefined
37
+ return provider == null ? null : { value: provider }
38
+ },
39
+ initializer: async provider => {
40
+ const { UnisatWalletAdapterImpl } =
41
+ await import("./UnisatWalletAdapter.impl")
42
+ return new UnisatWalletAdapterImpl(provider)
43
+ },
44
+ })
45
+
46
+ export const UnisatWalletAdapter: WalletAdapterStatic<WalletAdapter> = {
47
+ adapterId,
48
+ metadata,
49
+ getAdapter: () => availability,
50
+ }
@@ -0,0 +1,150 @@
1
+ import { hex } from "@scure/base"
2
+ import {
3
+ addressToScriptPubKey,
4
+ getRedeemScriptOf_P2SH_P2WPKH_publicKey,
5
+ } from "../utils/bitcoinAddressHelpers"
6
+ import { getBitcoinNetwork } from "../utils/bitcoinNetworkHelpers"
7
+ import { checkNever } from "../utils/misc"
8
+ import {
9
+ WalletAdapter,
10
+ WalletAdapterAddressPurpose,
11
+ WalletAdapterAddressType,
12
+ WalletAdapterBitcoinNetwork,
13
+ } from "../WalletAdapters.types"
14
+ import {
15
+ XverseCompatibleWalletAdapterImpl,
16
+ XverseCompatibleWalletAdapterImplAddress,
17
+ } from "../utils/XverseCompatibleWalletAdapterImpl"
18
+ import { XVERSE_PROVIDER_ID } from "./XverseWalletAdapter"
19
+
20
+ declare global {
21
+ interface Window {
22
+ btc_providers?: import("sats-connect").Provider[]
23
+ }
24
+ }
25
+
26
+ export type XverseWalletAdapterAddresses =
27
+ XverseCompatibleWalletAdapterImplAddress
28
+
29
+ /**
30
+ * Derivation path (BIP-49): m/49'/0'/0'/0/ address_index
31
+ */
32
+
33
+ export class XverseWalletAdapterImpl
34
+ extends XverseCompatibleWalletAdapterImpl
35
+ implements WalletAdapter
36
+ {
37
+ constructor() {
38
+ super({
39
+ walletDisplayName: "Xverse",
40
+ getProviderId: async () => {
41
+ return XVERSE_PROVIDER_ID
42
+ },
43
+ parseAddresses: async ({ sdk, network: xverseNetwork, addresses }) => {
44
+ // prettier-ignore
45
+ const network =
46
+ xverseNetwork === sdk.BitcoinNetworkType.Mainnet ? WalletAdapterBitcoinNetwork.MAINNET :
47
+ xverseNetwork === sdk.BitcoinNetworkType.Testnet ? WalletAdapterBitcoinNetwork.TESTNET :
48
+ xverseNetwork === sdk.BitcoinNetworkType.Testnet4 ? WalletAdapterBitcoinNetwork.TESTNET :
49
+ xverseNetwork === sdk.BitcoinNetworkType.Signet ? WalletAdapterBitcoinNetwork.UNKNOWN :
50
+ xverseNetwork === sdk.BitcoinNetworkType.Regtest ? WalletAdapterBitcoinNetwork.UNKNOWN :
51
+ (checkNever(xverseNetwork), WalletAdapterBitcoinNetwork.UNKNOWN)
52
+
53
+ const bitcoinNetwork = getBitcoinNetwork(
54
+ network === WalletAdapterBitcoinNetwork.MAINNET
55
+ ? "mainnet"
56
+ : "testnet",
57
+ )
58
+
59
+ return addresses.flatMap((a): XverseWalletAdapterAddresses[] => {
60
+ const purposes: WalletAdapterAddressPurpose[] = []
61
+ switch (a.purpose) {
62
+ case sdk.AddressPurpose.Ordinals:
63
+ purposes.push(
64
+ WalletAdapterAddressPurpose.Ordinals,
65
+ WalletAdapterAddressPurpose.BRC20,
66
+ WalletAdapterAddressPurpose.Runes,
67
+ )
68
+ break
69
+ case sdk.AddressPurpose.Payment:
70
+ purposes.push(WalletAdapterAddressPurpose.Bitcoin)
71
+ break
72
+ }
73
+
74
+ const scriptPubKey = hex.encode(
75
+ addressToScriptPubKey(bitcoinNetwork, a.address),
76
+ )
77
+
78
+ switch (a.addressType) {
79
+ case sdk.AddressType.stacks:
80
+ return []
81
+ case sdk.AddressType.p2pkh:
82
+ return [
83
+ {
84
+ purposes,
85
+ network,
86
+ addressType: WalletAdapterAddressType.P2PKH,
87
+ address: a.address,
88
+ scriptPubKey,
89
+ publicKey: a.publicKey,
90
+ },
91
+ ]
92
+ case sdk.AddressType.p2wpkh:
93
+ return [
94
+ {
95
+ purposes,
96
+ network,
97
+ addressType: WalletAdapterAddressType.P2WPKH,
98
+ address: a.address,
99
+ scriptPubKey,
100
+ publicKey: a.publicKey,
101
+ },
102
+ ]
103
+ case sdk.AddressType.p2tr: {
104
+ const tapInternalKey: string = a.publicKey
105
+ return [
106
+ {
107
+ purposes,
108
+ network,
109
+ addressType: WalletAdapterAddressType.P2TR,
110
+ address: a.address,
111
+ scriptPubKey,
112
+ publicKey: a.publicKey,
113
+ tapInternalKey,
114
+ },
115
+ ]
116
+ }
117
+ case sdk.AddressType.p2sh: {
118
+ const redeemScript = hex.encode(
119
+ getRedeemScriptOf_P2SH_P2WPKH_publicKey(
120
+ bitcoinNetwork,
121
+ hex.decode(a.publicKey),
122
+ ),
123
+ )
124
+ return [
125
+ {
126
+ purposes,
127
+ network,
128
+ addressType: WalletAdapterAddressType.P2SH_P2WPKH,
129
+ address: a.address,
130
+ scriptPubKey,
131
+ publicKey: a.publicKey,
132
+ redeemScript,
133
+ },
134
+ ]
135
+ }
136
+ case sdk.AddressType.p2wsh:
137
+ // not supported
138
+ return []
139
+ case sdk.AddressType.starknet:
140
+ case sdk.AddressType.spark:
141
+ return []
142
+ default:
143
+ checkNever(a.addressType)
144
+ return []
145
+ }
146
+ })
147
+ },
148
+ })
149
+ }
150
+ }
@@ -0,0 +1,37 @@
1
+ import type {
2
+ WalletAdapter,
3
+ WalletAdapterStatic,
4
+ } from "../WalletAdapters.types"
5
+ import { createAvailability } from "../utils/createAdapterAvailability"
6
+
7
+ export const XVERSE_PROVIDER_ID = "XverseProviders.BitcoinProvider"
8
+
9
+ const metadata = {
10
+ name: "Xverse",
11
+ iconUrl: import("../_/xverse.png").then(m => m.default),
12
+ websiteUrl: "https://xverse.app/",
13
+ downloadUrl: "https://www.xverse.app/download",
14
+ }
15
+
16
+ const availability = createAvailability<
17
+ import("sats-connect").Provider,
18
+ WalletAdapter
19
+ >({
20
+ getPrecondition: () => {
21
+ const provider = (window.btc_providers ?? []).find(
22
+ p => p.id === XVERSE_PROVIDER_ID,
23
+ )
24
+ return provider == null ? null : { value: provider }
25
+ },
26
+ initializer: async () => {
27
+ const { XverseWalletAdapterImpl } =
28
+ await import("./XverseWalletAdapter.impl")
29
+ return new XverseWalletAdapterImpl()
30
+ },
31
+ })
32
+
33
+ export const XverseWalletAdapter: WalletAdapterStatic<WalletAdapter> = {
34
+ adapterId: XVERSE_PROVIDER_ID,
35
+ metadata,
36
+ getAdapter: () => availability,
37
+ }
@@ -0,0 +1,7 @@
1
+ export { BitgetWalletAdapter } from "./BitgetWalletAdapter"
2
+ export { LeatherWalletAdapter } from "./LeatherWalletAdapter"
3
+ export { MagicEdenWalletAdapterFactory } from "./MagicEdenWalletAdapter"
4
+ export { OkxWalletAdapter } from "./OkxWalletAdapter"
5
+ export { UnisatWalletAdapter } from "./UnisatWalletAdapter"
6
+ export { XverseWalletAdapter } from "./XverseWalletAdapter"
7
+ export { MockAddressWalletAdapter } from "./MockAddressWalletAdapter"
package/src/env.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ declare module "*.png" {
2
+ const content: string
3
+ export default content
4
+ }
5
+
6
+ declare module "*.svg" {
7
+ const content: string
8
+ export default content
9
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./BitcoinWalletAdapterConnector"
2
+ export * from "./WalletAdapters.types"
3
+ export * from "./adapters"