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.
- package/README.md +208 -0
- package/lib/BitcoinConnectionProvider.d.ts +23 -0
- package/lib/BitcoinWalletAdapterConnector-Bq835yj0.mjs +123 -0
- package/lib/BitcoinWalletAdapterConnector-Bq835yj0.mjs.map +1 -0
- package/lib/BitcoinWalletAdapterConnector-DMef0iHV.js +2 -0
- package/lib/BitcoinWalletAdapterConnector-DMef0iHV.js.map +1 -0
- package/lib/BitcoinWalletAdapterConnector.d.ts +30 -0
- package/lib/BitgetWalletAdapter.impl-C_HLO7Oi.mjs +10 -0
- package/lib/BitgetWalletAdapter.impl-C_HLO7Oi.mjs.map +1 -0
- package/lib/BitgetWalletAdapter.impl-CxnKMf7U.js +2 -0
- package/lib/BitgetWalletAdapter.impl-CxnKMf7U.js.map +1 -0
- package/lib/LeatherWalletAdapter.impl-B2QgX_tO.js +2 -0
- package/lib/LeatherWalletAdapter.impl-B2QgX_tO.js.map +1 -0
- package/lib/LeatherWalletAdapter.impl-RUYx555r.mjs +184 -0
- package/lib/LeatherWalletAdapter.impl-RUYx555r.mjs.map +1 -0
- package/lib/MagicEdenWalletAdapter.impl-CrA6SGvG.mjs +235 -0
- package/lib/MagicEdenWalletAdapter.impl-CrA6SGvG.mjs.map +1 -0
- package/lib/MagicEdenWalletAdapter.impl-Di3Nu2S5.js +2 -0
- package/lib/MagicEdenWalletAdapter.impl-Di3Nu2S5.js.map +1 -0
- package/lib/OkxWalletAdapter.impl-BepoUL1B.mjs +67 -0
- package/lib/OkxWalletAdapter.impl-BepoUL1B.mjs.map +1 -0
- package/lib/OkxWalletAdapter.impl-C8kesjGu.js +2 -0
- package/lib/OkxWalletAdapter.impl-C8kesjGu.js.map +1 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js +2 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js.map +1 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-M38FqkZI.mjs +137 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-M38FqkZI.mjs.map +1 -0
- package/lib/UnisatWalletAdapter.impl-CJB22se8.mjs +14 -0
- package/lib/UnisatWalletAdapter.impl-CJB22se8.mjs.map +1 -0
- package/lib/UnisatWalletAdapter.impl-EISvxdpc.js +2 -0
- package/lib/UnisatWalletAdapter.impl-EISvxdpc.js.map +1 -0
- package/lib/WalletAdapters.types-CnvOqHFH.mjs +32 -0
- package/lib/WalletAdapters.types-CnvOqHFH.mjs.map +1 -0
- package/lib/WalletAdapters.types-De_x1lzr.js +2 -0
- package/lib/WalletAdapters.types-De_x1lzr.js.map +1 -0
- package/lib/WalletAdapters.types.d.ts +110 -0
- package/lib/XverseCompatibleWalletAdapterImpl-Bf-BK5VK.js +2 -0
- package/lib/XverseCompatibleWalletAdapterImpl-Bf-BK5VK.js.map +1 -0
- package/lib/XverseCompatibleWalletAdapterImpl-DXKnO_-V.mjs +151 -0
- package/lib/XverseCompatibleWalletAdapterImpl-DXKnO_-V.mjs.map +1 -0
- package/lib/XverseWalletAdapter.impl-CZO0RQva.mjs +105 -0
- package/lib/XverseWalletAdapter.impl-CZO0RQva.mjs.map +1 -0
- package/lib/XverseWalletAdapter.impl-lJwMi-Iv.js +2 -0
- package/lib/XverseWalletAdapter.impl-lJwMi-Iv.js.map +1 -0
- package/lib/adapters/BitgetWalletAdapter.d.ts +2 -0
- package/lib/adapters/BitgetWalletAdapter.impl.d.ts +8 -0
- package/lib/adapters/LeatherWalletAdapter.d.ts +2 -0
- package/lib/adapters/LeatherWalletAdapter.impl.d.ts +41 -0
- package/lib/adapters/MagicEdenWalletAdapter.d.ts +11 -0
- package/lib/adapters/MagicEdenWalletAdapter.impl.d.ts +22 -0
- package/lib/adapters/MockAddressWalletAdapter.d.ts +33 -0
- package/lib/adapters/OkxWalletAdapter.d.ts +2 -0
- package/lib/adapters/OkxWalletAdapter.impl.d.ts +51 -0
- package/lib/adapters/UnisatWalletAdapter.d.ts +2 -0
- package/lib/adapters/UnisatWalletAdapter.impl.d.ts +14 -0
- package/lib/adapters/XverseWalletAdapter.d.ts +3 -0
- package/lib/adapters/XverseWalletAdapter.impl.d.ts +14 -0
- package/lib/adapters/index.d.ts +7 -0
- package/lib/adapters.js +2 -0
- package/lib/adapters.js.map +1 -0
- package/lib/adapters.mjs +11 -0
- package/lib/adapters.mjs.map +1 -0
- package/lib/bitget-C7oB4Ffq.mjs +5 -0
- package/lib/bitget-C7oB4Ffq.mjs.map +1 -0
- package/lib/bitget-DXnsxx_y.js +2 -0
- package/lib/bitget-DXnsxx_y.js.map +1 -0
- package/lib/index-CaV3F1Nm.js +424 -0
- package/lib/index-CaV3F1Nm.js.map +1 -0
- package/lib/index-CcQUdePc.mjs +12224 -0
- package/lib/index-CcQUdePc.mjs.map +1 -0
- package/lib/index-D7YwhNAG.mjs +3946 -0
- package/lib/index-D7YwhNAG.mjs.map +1 -0
- package/lib/index-Zx0KcpYx.js +2 -0
- package/lib/index-Zx0KcpYx.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +20 -0
- package/lib/index.mjs.map +1 -0
- package/lib/leather-BoQG_CPn.mjs +5 -0
- package/lib/leather-BoQG_CPn.mjs.map +1 -0
- package/lib/leather-DJ8nWmM8.js +2 -0
- package/lib/leather-DJ8nWmM8.js.map +1 -0
- package/lib/magiceden-B36CEQa6.js +2 -0
- package/lib/magiceden-B36CEQa6.js.map +1 -0
- package/lib/magiceden-Cg7d3agI.mjs +5 -0
- package/lib/magiceden-Cg7d3agI.mjs.map +1 -0
- package/lib/misc-B5EWO_dn.mjs +10 -0
- package/lib/misc-B5EWO_dn.mjs.map +1 -0
- package/lib/misc-CigR0RqC.js +2 -0
- package/lib/misc-CigR0RqC.js.map +1 -0
- package/lib/okx-ChwzM0dK.js +2 -0
- package/lib/okx-ChwzM0dK.js.map +1 -0
- package/lib/okx-DWbHwazu.mjs +5 -0
- package/lib/okx-DWbHwazu.mjs.map +1 -0
- package/lib/react.d.ts +2 -0
- package/lib/react.js +2 -0
- package/lib/react.js.map +1 -0
- package/lib/react.mjs +128 -0
- package/lib/react.mjs.map +1 -0
- package/lib/transaction-CiLOYSE_.mjs +1063 -0
- package/lib/transaction-CiLOYSE_.mjs.map +1 -0
- package/lib/transaction-CzdnbXSo.js +2 -0
- package/lib/transaction-CzdnbXSo.js.map +1 -0
- package/lib/unisat-BvZW5h0U.js +2 -0
- package/lib/unisat-BvZW5h0U.js.map +1 -0
- package/lib/unisat-pLgab4nG.mjs +5 -0
- package/lib/unisat-pLgab4nG.mjs.map +1 -0
- package/lib/utils/StateChannel.d.ts +14 -0
- package/lib/utils/UnisatCompatibleWalletAdapterImpl.d.ts +99 -0
- package/lib/utils/XverseCompatibleWalletAdapterImpl.d.ts +80 -0
- package/lib/utils/XverseCompatibleWalletAdapterImpl_legacy.d.ts +44 -0
- package/lib/utils/bitcoinAddressHelpers.d.ts +14 -0
- package/lib/utils/bitcoinNetworkHelpers.d.ts +4 -0
- package/lib/utils/createAdapterAvailability.d.ts +15 -0
- package/lib/utils/error.d.ts +6 -0
- package/lib/utils/misc.d.ts +3 -0
- package/lib/xverse-IKOHyGi-.js +2 -0
- package/lib/xverse-IKOHyGi-.js.map +1 -0
- package/lib/xverse-iHLNanCB.mjs +5 -0
- package/lib/xverse-iHLNanCB.mjs.map +1 -0
- package/package.json +86 -0
- package/src/BitcoinConnectionProvider.stories.tsx +329 -0
- package/src/BitcoinConnectionProvider.tsx +234 -0
- package/src/BitcoinWalletAdapterConnector.ts +166 -0
- package/src/WalletAdapters.types.ts +154 -0
- package/src/_/bitget.png +0 -0
- package/src/_/leather.svg +4 -0
- package/src/_/magiceden.png +0 -0
- package/src/_/okx.png +0 -0
- package/src/_/unisat.svg +31 -0
- package/src/_/xverse.png +0 -0
- package/src/adapters/BitgetWalletAdapter.impl.ts +22 -0
- package/src/adapters/BitgetWalletAdapter.ts +44 -0
- package/src/adapters/LeatherWalletAdapter.impl.ts +324 -0
- package/src/adapters/LeatherWalletAdapter.ts +35 -0
- package/src/adapters/MagicEdenWalletAdapter.impl.ts +139 -0
- package/src/adapters/MagicEdenWalletAdapter.ts +51 -0
- package/src/adapters/MockAddressWalletAdapter.ts +199 -0
- package/src/adapters/OkxWalletAdapter.impl.ts +168 -0
- package/src/adapters/OkxWalletAdapter.ts +37 -0
- package/src/adapters/UnisatWalletAdapter.impl.ts +32 -0
- package/src/adapters/UnisatWalletAdapter.ts +50 -0
- package/src/adapters/XverseWalletAdapter.impl.ts +150 -0
- package/src/adapters/XverseWalletAdapter.ts +37 -0
- package/src/adapters/index.ts +7 -0
- package/src/env.d.ts +9 -0
- package/src/index.ts +3 -0
- package/src/react.ts +9 -0
- package/src/utils/StateChannel.ts +39 -0
- package/src/utils/UnisatCompatibleWalletAdapterImpl.ts +342 -0
- package/src/utils/XverseCompatibleWalletAdapterImpl.ts +288 -0
- package/src/utils/XverseCompatibleWalletAdapterImpl_legacy.ts +278 -0
- package/src/utils/bitcoinAddressHelpers.ts +132 -0
- package/src/utils/bitcoinNetworkHelpers.ts +17 -0
- package/src/utils/createAdapterAvailability.ts +92 -0
- package/src/utils/error.ts +13 -0
- 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
package/src/index.ts
ADDED