@sip-protocol/sdk 0.3.1 → 0.4.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/dist/browser.d.mts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +1028 -146
- package/dist/browser.mjs +49 -1
- package/dist/chunk-AOZIY3GU.mjs +12995 -0
- package/dist/chunk-BCLIX5T2.mjs +12940 -0
- package/dist/chunk-EU4UEWWG.mjs +12164 -0
- package/dist/chunk-FKXPHKYD.mjs +12955 -0
- package/dist/chunk-OPQ2GQIO.mjs +13013 -0
- package/dist/index-BcWNakUD.d.ts +7990 -0
- package/dist/index-BsKY3Hr0.d.mts +7990 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +999 -117
- package/dist/index.mjs +49 -1
- package/package.json +2 -1
- package/src/adapters/near-intents.ts +8 -0
- package/src/bitcoin/index.ts +51 -0
- package/src/bitcoin/silent-payments.ts +865 -0
- package/src/bitcoin/taproot.ts +590 -0
- package/src/cosmos/ibc-stealth.ts +825 -0
- package/src/cosmos/index.ts +83 -0
- package/src/cosmos/stealth.ts +487 -0
- package/src/index.ts +51 -0
- package/src/move/aptos.ts +369 -0
- package/src/move/index.ts +35 -0
- package/src/move/sui.ts +367 -0
- package/src/oracle/types.ts +8 -0
- package/src/settlement/backends/direct-chain.ts +8 -0
- package/src/settlement/backends/near-intents.ts +11 -0
- package/src/stealth.ts +3 -3
- package/src/validation.ts +42 -1
- package/src/wallet/aptos/adapter.ts +422 -0
- package/src/wallet/aptos/index.ts +10 -0
- package/src/wallet/aptos/mock.ts +410 -0
- package/src/wallet/aptos/types.ts +278 -0
- package/src/wallet/bitcoin/adapter.ts +470 -0
- package/src/wallet/bitcoin/index.ts +38 -0
- package/src/wallet/bitcoin/mock.ts +516 -0
- package/src/wallet/bitcoin/types.ts +274 -0
- package/src/wallet/cosmos/adapter.ts +484 -0
- package/src/wallet/cosmos/index.ts +63 -0
- package/src/wallet/cosmos/mock.ts +596 -0
- package/src/wallet/cosmos/types.ts +462 -0
- package/src/wallet/index.ts +127 -0
- package/src/wallet/sui/adapter.ts +471 -0
- package/src/wallet/sui/index.ts +10 -0
- package/src/wallet/sui/mock.ts +439 -0
- package/src/wallet/sui/types.ts +245 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bitcoin Wallet Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implementation of WalletAdapter for Bitcoin.
|
|
5
|
+
* Supports Unisat, Xverse, Leather, and OKX wallets.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
HexString,
|
|
10
|
+
Asset,
|
|
11
|
+
Signature,
|
|
12
|
+
UnsignedTransaction,
|
|
13
|
+
SignedTransaction,
|
|
14
|
+
TransactionReceipt,
|
|
15
|
+
} from '@sip-protocol/types'
|
|
16
|
+
import { WalletErrorCode } from '@sip-protocol/types'
|
|
17
|
+
import { BaseWalletAdapter } from '../base-adapter'
|
|
18
|
+
import { WalletError } from '../errors'
|
|
19
|
+
import type {
|
|
20
|
+
UnisatAPI,
|
|
21
|
+
BitcoinAdapterConfig,
|
|
22
|
+
BitcoinWalletName,
|
|
23
|
+
BitcoinNetwork,
|
|
24
|
+
BitcoinAddress,
|
|
25
|
+
BitcoinBalance,
|
|
26
|
+
SignPsbtOptions,
|
|
27
|
+
} from './types'
|
|
28
|
+
import {
|
|
29
|
+
getBitcoinProvider,
|
|
30
|
+
bitcoinPublicKeyToHex,
|
|
31
|
+
isValidTaprootAddress,
|
|
32
|
+
} from './types'
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Bitcoin wallet adapter
|
|
36
|
+
*
|
|
37
|
+
* Provides SIP-compatible wallet interface for Bitcoin.
|
|
38
|
+
* Works with Unisat, OKX, Xverse, and Leather wallets.
|
|
39
|
+
*
|
|
40
|
+
* @example Browser usage with Unisat
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const wallet = new BitcoinWalletAdapter({ wallet: 'unisat' })
|
|
43
|
+
* await wallet.connect()
|
|
44
|
+
*
|
|
45
|
+
* const balance = await wallet.getBalance()
|
|
46
|
+
* console.log(`Balance: ${balance} sats`)
|
|
47
|
+
*
|
|
48
|
+
* // Sign a message
|
|
49
|
+
* const sig = await wallet.signMessage(new TextEncoder().encode('Hello Bitcoin'))
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example With custom network
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const wallet = new BitcoinWalletAdapter({
|
|
55
|
+
* wallet: 'unisat',
|
|
56
|
+
* network: 'testnet',
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export class BitcoinWalletAdapter extends BaseWalletAdapter {
|
|
61
|
+
readonly chain = 'bitcoin' as const
|
|
62
|
+
readonly name: string
|
|
63
|
+
|
|
64
|
+
private provider: UnisatAPI | undefined
|
|
65
|
+
private walletName: BitcoinWalletName
|
|
66
|
+
private network: BitcoinNetwork
|
|
67
|
+
|
|
68
|
+
constructor(config: BitcoinAdapterConfig = {}) {
|
|
69
|
+
super()
|
|
70
|
+
this.walletName = config.wallet ?? 'unisat'
|
|
71
|
+
this.name = `bitcoin-${this.walletName}`
|
|
72
|
+
this.network = config.network ?? 'livenet'
|
|
73
|
+
|
|
74
|
+
// Allow injecting provider for testing
|
|
75
|
+
if (config.provider) {
|
|
76
|
+
this.provider = config.provider
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the current Bitcoin network
|
|
82
|
+
*/
|
|
83
|
+
getNetwork(): BitcoinNetwork {
|
|
84
|
+
return this.network
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Set the Bitcoin network
|
|
89
|
+
*/
|
|
90
|
+
async setNetwork(network: BitcoinNetwork): Promise<void> {
|
|
91
|
+
if (!this.provider) {
|
|
92
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await this.provider.switchNetwork(network)
|
|
97
|
+
this.network = network
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const message = error instanceof Error ? error.message : 'Failed to switch network'
|
|
100
|
+
throw new WalletError(message, WalletErrorCode.UNKNOWN, { cause: error as Error })
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Connect to the wallet
|
|
106
|
+
*/
|
|
107
|
+
async connect(): Promise<void> {
|
|
108
|
+
this._connectionState = 'connecting'
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
// Get provider if not already set
|
|
112
|
+
if (!this.provider) {
|
|
113
|
+
this.provider = getBitcoinProvider(this.walletName)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (!this.provider) {
|
|
117
|
+
this.setError(
|
|
118
|
+
WalletErrorCode.NOT_INSTALLED,
|
|
119
|
+
`${this.walletName} wallet is not installed`
|
|
120
|
+
)
|
|
121
|
+
throw new WalletError(
|
|
122
|
+
`${this.walletName} wallet is not installed`,
|
|
123
|
+
WalletErrorCode.NOT_INSTALLED
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Request account access
|
|
128
|
+
const accounts = await this.provider.requestAccounts()
|
|
129
|
+
|
|
130
|
+
if (!accounts || accounts.length === 0) {
|
|
131
|
+
throw new WalletError(
|
|
132
|
+
'No accounts returned from wallet',
|
|
133
|
+
WalletErrorCode.CONNECTION_FAILED
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get the first account (Taproot address)
|
|
138
|
+
const address = accounts[0]
|
|
139
|
+
|
|
140
|
+
// Validate Taproot address format
|
|
141
|
+
if (!isValidTaprootAddress(address, this.network)) {
|
|
142
|
+
throw new WalletError(
|
|
143
|
+
`Invalid Taproot address format: ${address}`,
|
|
144
|
+
WalletErrorCode.CONNECTION_FAILED
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Get public key
|
|
149
|
+
const publicKey = await this.provider.getPublicKey()
|
|
150
|
+
const hexPubKey = bitcoinPublicKeyToHex(publicKey)
|
|
151
|
+
|
|
152
|
+
// Update state
|
|
153
|
+
this.setConnected(address, hexPubKey)
|
|
154
|
+
} catch (error) {
|
|
155
|
+
const message = error instanceof Error ? error.message : 'Connection failed'
|
|
156
|
+
|
|
157
|
+
// Check if user rejected
|
|
158
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('cancelled')) {
|
|
159
|
+
this.setError(WalletErrorCode.CONNECTION_REJECTED, message)
|
|
160
|
+
throw new WalletError(message, WalletErrorCode.CONNECTION_REJECTED)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
this.setError(WalletErrorCode.CONNECTION_FAILED, message)
|
|
164
|
+
throw error instanceof WalletError
|
|
165
|
+
? error
|
|
166
|
+
: new WalletError(message, WalletErrorCode.CONNECTION_FAILED, { cause: error as Error })
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Disconnect from the wallet
|
|
172
|
+
*/
|
|
173
|
+
async disconnect(): Promise<void> {
|
|
174
|
+
this.setDisconnected('User disconnected')
|
|
175
|
+
// Note: Unisat doesn't have a disconnect method
|
|
176
|
+
// The wallet remains accessible but we clear our state
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Sign a message
|
|
181
|
+
*
|
|
182
|
+
* Uses BIP-322 simple signature format by default
|
|
183
|
+
*/
|
|
184
|
+
async signMessage(message: Uint8Array): Promise<Signature> {
|
|
185
|
+
this.requireConnected()
|
|
186
|
+
|
|
187
|
+
if (!this.provider) {
|
|
188
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
// Convert message to string (Unisat expects string)
|
|
193
|
+
const messageStr = new TextDecoder().decode(message)
|
|
194
|
+
|
|
195
|
+
// Sign using BIP-322 simple format (preferred for Taproot)
|
|
196
|
+
const signature = await this.provider.signMessage(messageStr, 'bip322-simple')
|
|
197
|
+
|
|
198
|
+
// Signature is returned as base64, convert to hex
|
|
199
|
+
const sigBytes = Buffer.from(signature, 'base64')
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
signature: ('0x' + sigBytes.toString('hex')) as HexString,
|
|
203
|
+
publicKey: this._publicKey as HexString,
|
|
204
|
+
}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
const message = error instanceof Error ? error.message : 'Signing failed'
|
|
207
|
+
|
|
208
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('cancelled')) {
|
|
209
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
|
|
213
|
+
cause: error as Error,
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Sign a PSBT (Partially Signed Bitcoin Transaction)
|
|
220
|
+
*
|
|
221
|
+
* The transaction data should be a PSBT in hex format
|
|
222
|
+
*/
|
|
223
|
+
async signTransaction(tx: UnsignedTransaction): Promise<SignedTransaction> {
|
|
224
|
+
this.requireConnected()
|
|
225
|
+
|
|
226
|
+
if (!this.provider) {
|
|
227
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
// Extract PSBT from transaction data
|
|
232
|
+
const psbtHex = tx.data as string
|
|
233
|
+
const options = tx.metadata?.signPsbtOptions as SignPsbtOptions | undefined
|
|
234
|
+
|
|
235
|
+
// Sign PSBT
|
|
236
|
+
const signedPsbt = await this.provider.signPsbt(psbtHex, options)
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
unsigned: tx,
|
|
240
|
+
signatures: [
|
|
241
|
+
{
|
|
242
|
+
signature: ('0x' + signedPsbt) as HexString,
|
|
243
|
+
publicKey: this._publicKey as HexString,
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
serialized: ('0x' + signedPsbt) as HexString,
|
|
247
|
+
}
|
|
248
|
+
} catch (error) {
|
|
249
|
+
const message = error instanceof Error ? error.message : 'Signing failed'
|
|
250
|
+
|
|
251
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('cancelled')) {
|
|
252
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
|
|
256
|
+
cause: error as Error,
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Sign and send a PSBT
|
|
263
|
+
*
|
|
264
|
+
* Note: This signs the PSBT and broadcasts the finalized transaction
|
|
265
|
+
*/
|
|
266
|
+
async signAndSendTransaction(tx: UnsignedTransaction): Promise<TransactionReceipt> {
|
|
267
|
+
this.requireConnected()
|
|
268
|
+
|
|
269
|
+
if (!this.provider) {
|
|
270
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
// First, sign the transaction
|
|
275
|
+
const signed = await this.signTransaction(tx)
|
|
276
|
+
|
|
277
|
+
// Extract the signed PSBT hex (without 0x prefix)
|
|
278
|
+
const signedPsbt = signed.serialized.slice(2)
|
|
279
|
+
|
|
280
|
+
// If PSBT is not finalized, we need to finalize it
|
|
281
|
+
// For now, assume it's finalized (autoFinalized: true in options)
|
|
282
|
+
// TODO: Add PSBT finalization logic here
|
|
283
|
+
|
|
284
|
+
// Broadcast the transaction
|
|
285
|
+
const txid = await this.provider.pushTx(signedPsbt)
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
txHash: ('0x' + txid) as HexString,
|
|
289
|
+
status: 'pending', // Transaction is broadcast but not confirmed
|
|
290
|
+
timestamp: Date.now(),
|
|
291
|
+
}
|
|
292
|
+
} catch (error) {
|
|
293
|
+
const message = error instanceof Error ? error.message : 'Transaction failed'
|
|
294
|
+
|
|
295
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('cancelled')) {
|
|
296
|
+
throw new WalletError(message, WalletErrorCode.TRANSACTION_REJECTED)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (message.includes('insufficient') || message.includes('Insufficient')) {
|
|
300
|
+
throw new WalletError(message, WalletErrorCode.INSUFFICIENT_FUNDS)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
throw new WalletError(message, WalletErrorCode.TRANSACTION_FAILED, {
|
|
304
|
+
cause: error as Error,
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Get native BTC balance
|
|
311
|
+
*/
|
|
312
|
+
async getBalance(): Promise<bigint> {
|
|
313
|
+
this.requireConnected()
|
|
314
|
+
|
|
315
|
+
if (!this.provider) {
|
|
316
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
const balance = await this.provider.getBalance()
|
|
321
|
+
return BigInt(balance.total)
|
|
322
|
+
} catch (error) {
|
|
323
|
+
throw new WalletError(
|
|
324
|
+
'Failed to get balance',
|
|
325
|
+
WalletErrorCode.UNKNOWN,
|
|
326
|
+
{ cause: error as Error }
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Get token balance
|
|
333
|
+
*
|
|
334
|
+
* For Bitcoin, this would return balance of inscriptions or BRC-20 tokens
|
|
335
|
+
* Not implemented yet - returns 0
|
|
336
|
+
*/
|
|
337
|
+
async getTokenBalance(asset: Asset): Promise<bigint> {
|
|
338
|
+
this.requireConnected()
|
|
339
|
+
|
|
340
|
+
if (asset.chain !== 'bitcoin') {
|
|
341
|
+
throw new WalletError(
|
|
342
|
+
`Asset chain ${asset.chain} not supported by Bitcoin adapter`,
|
|
343
|
+
WalletErrorCode.UNSUPPORTED_CHAIN
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// TODO: Implement BRC-20 token balance query
|
|
348
|
+
// For now, return 0
|
|
349
|
+
return 0n
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Get Bitcoin addresses
|
|
354
|
+
*
|
|
355
|
+
* Returns the current Taproot address with metadata
|
|
356
|
+
*/
|
|
357
|
+
async getAddresses(): Promise<BitcoinAddress[]> {
|
|
358
|
+
this.requireConnected()
|
|
359
|
+
|
|
360
|
+
if (!this.provider) {
|
|
361
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
try {
|
|
365
|
+
const accounts = await this.provider.getAccounts()
|
|
366
|
+
const publicKey = await this.provider.getPublicKey()
|
|
367
|
+
|
|
368
|
+
return accounts.map((address) => ({
|
|
369
|
+
address,
|
|
370
|
+
publicKey,
|
|
371
|
+
type: 'p2tr' as const, // Unisat uses Taproot by default
|
|
372
|
+
}))
|
|
373
|
+
} catch (error) {
|
|
374
|
+
throw new WalletError(
|
|
375
|
+
'Failed to get addresses',
|
|
376
|
+
WalletErrorCode.UNKNOWN,
|
|
377
|
+
{ cause: error as Error }
|
|
378
|
+
)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get detailed balance information
|
|
384
|
+
*/
|
|
385
|
+
async getBalanceDetails(): Promise<BitcoinBalance> {
|
|
386
|
+
this.requireConnected()
|
|
387
|
+
|
|
388
|
+
if (!this.provider) {
|
|
389
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
const balance = await this.provider.getBalance()
|
|
394
|
+
return {
|
|
395
|
+
confirmed: BigInt(balance.confirmed),
|
|
396
|
+
unconfirmed: BigInt(balance.unconfirmed),
|
|
397
|
+
total: BigInt(balance.total),
|
|
398
|
+
}
|
|
399
|
+
} catch (error) {
|
|
400
|
+
throw new WalletError(
|
|
401
|
+
'Failed to get balance details',
|
|
402
|
+
WalletErrorCode.UNKNOWN,
|
|
403
|
+
{ cause: error as Error }
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Sign a PSBT directly
|
|
410
|
+
*
|
|
411
|
+
* Bitcoin-specific method for PSBT signing with options
|
|
412
|
+
*/
|
|
413
|
+
async signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string> {
|
|
414
|
+
this.requireConnected()
|
|
415
|
+
|
|
416
|
+
if (!this.provider) {
|
|
417
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
return await this.provider.signPsbt(psbtHex, options)
|
|
422
|
+
} catch (error) {
|
|
423
|
+
const message = error instanceof Error ? error.message : 'PSBT signing failed'
|
|
424
|
+
|
|
425
|
+
if (message.includes('User rejected') || message.includes('rejected') || message.includes('cancelled')) {
|
|
426
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_REJECTED)
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
throw new WalletError(message, WalletErrorCode.SIGNING_FAILED, {
|
|
430
|
+
cause: error as Error,
|
|
431
|
+
})
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Push a raw transaction to the network
|
|
437
|
+
*
|
|
438
|
+
* Bitcoin-specific method for broadcasting transactions
|
|
439
|
+
*/
|
|
440
|
+
async pushTx(rawTx: string): Promise<string> {
|
|
441
|
+
this.requireConnected()
|
|
442
|
+
|
|
443
|
+
if (!this.provider) {
|
|
444
|
+
throw new WalletError('Provider not available', WalletErrorCode.NOT_CONNECTED)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
try {
|
|
448
|
+
return await this.provider.pushTx(rawTx)
|
|
449
|
+
} catch (error) {
|
|
450
|
+
const message = error instanceof Error ? error.message : 'Transaction broadcast failed'
|
|
451
|
+
|
|
452
|
+
if (message.includes('insufficient') || message.includes('Insufficient')) {
|
|
453
|
+
throw new WalletError(message, WalletErrorCode.INSUFFICIENT_FUNDS)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
throw new WalletError(message, WalletErrorCode.TRANSACTION_FAILED, {
|
|
457
|
+
cause: error as Error,
|
|
458
|
+
})
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Create a Bitcoin wallet adapter with default configuration
|
|
465
|
+
*/
|
|
466
|
+
export function createBitcoinAdapter(
|
|
467
|
+
config: BitcoinAdapterConfig = {}
|
|
468
|
+
): BitcoinWalletAdapter {
|
|
469
|
+
return new BitcoinWalletAdapter(config)
|
|
470
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bitcoin Wallet Module
|
|
3
|
+
*
|
|
4
|
+
* Bitcoin wallet adapter for SIP Protocol.
|
|
5
|
+
* Supports Unisat, Xverse, Leather, and OKX wallets.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Adapter
|
|
9
|
+
export { BitcoinWalletAdapter, createBitcoinAdapter } from './adapter'
|
|
10
|
+
|
|
11
|
+
// Mock adapter
|
|
12
|
+
export {
|
|
13
|
+
MockBitcoinAdapter,
|
|
14
|
+
createMockBitcoinAdapter,
|
|
15
|
+
createMockBitcoinProvider,
|
|
16
|
+
type MockBitcoinAdapterConfig,
|
|
17
|
+
} from './mock'
|
|
18
|
+
|
|
19
|
+
// Types and utilities
|
|
20
|
+
export {
|
|
21
|
+
getBitcoinProvider,
|
|
22
|
+
detectBitcoinWallets,
|
|
23
|
+
bitcoinAddressToHex,
|
|
24
|
+
bitcoinPublicKeyToHex,
|
|
25
|
+
isValidTaprootAddress,
|
|
26
|
+
} from './types'
|
|
27
|
+
|
|
28
|
+
export type {
|
|
29
|
+
BitcoinAddressType,
|
|
30
|
+
BitcoinNetwork,
|
|
31
|
+
BitcoinAddress,
|
|
32
|
+
BitcoinBalance,
|
|
33
|
+
SignPsbtOptions,
|
|
34
|
+
ToSignInput,
|
|
35
|
+
BitcoinWalletName,
|
|
36
|
+
BitcoinAdapterConfig,
|
|
37
|
+
UnisatAPI,
|
|
38
|
+
} from './types'
|