orbis1-sdk-rn 0.0.6 → 0.0.8
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 +24 -6
- package/lib/module/Orbis1SDK.js +6 -1
- package/lib/module/Orbis1SDK.js.map +1 -1
- package/lib/module/features/gas-free/GasFreeModule.js +118 -30
- package/lib/module/features/gas-free/GasFreeModule.js.map +1 -1
- package/lib/module/features/gas-free/types/StageResults.js +2 -0
- package/lib/module/features/gas-free/types/StageResults.js.map +1 -0
- package/lib/module/features/gas-free/types/index.js +2 -0
- package/lib/module/features/gas-free/types/index.js.map +1 -1
- package/lib/module/features/watch-tower/WatchTowerModule.js +19 -9
- package/lib/module/features/watch-tower/WatchTowerModule.js.map +1 -1
- package/lib/module/features/watch-tower/types/WatchTowerRequest.js +2 -0
- package/lib/module/features/watch-tower/types/WatchTowerRequest.js.map +1 -0
- package/lib/module/features/watch-tower/types/WatchTowerResponse.js +4 -0
- package/lib/module/features/watch-tower/types/WatchTowerResponse.js.map +1 -0
- package/lib/module/index.js +0 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/SDKConfig.js +6 -4
- package/lib/module/types/SDKConfig.js.map +1 -1
- package/lib/typescript/src/Orbis1SDK.d.ts.map +1 -1
- package/lib/typescript/src/features/gas-free/GasFreeModule.d.ts +115 -38
- package/lib/typescript/src/features/gas-free/GasFreeModule.d.ts.map +1 -1
- package/lib/typescript/src/features/gas-free/types/StageResults.d.ts +85 -0
- package/lib/typescript/src/features/gas-free/types/StageResults.d.ts.map +1 -0
- package/lib/typescript/src/features/gas-free/types/index.d.ts +1 -0
- package/lib/typescript/src/features/gas-free/types/index.d.ts.map +1 -1
- package/lib/typescript/src/features/watch-tower/WatchTowerModule.d.ts +8 -5
- package/lib/typescript/src/features/watch-tower/WatchTowerModule.d.ts.map +1 -1
- package/lib/typescript/src/features/watch-tower/index.d.ts +1 -1
- package/lib/typescript/src/features/watch-tower/index.d.ts.map +1 -1
- package/lib/typescript/src/features/watch-tower/types/WatchTowerRequest.d.ts +40 -0
- package/lib/typescript/src/features/watch-tower/types/WatchTowerRequest.d.ts.map +1 -0
- package/lib/typescript/src/features/watch-tower/types/WatchTowerResponse.d.ts +43 -0
- package/lib/typescript/src/features/watch-tower/types/WatchTowerResponse.d.ts.map +1 -0
- package/lib/typescript/src/features/watch-tower/types/index.d.ts +2 -0
- package/lib/typescript/src/features/watch-tower/types/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/SDKConfig.d.ts +4 -2
- package/lib/typescript/src/types/SDKConfig.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/Orbis1SDK.ts +10 -0
- package/src/features/gas-free/GasFreeModule.ts +138 -60
- package/src/features/gas-free/types/StageResults.ts +95 -0
- package/src/features/gas-free/types/index.ts +8 -0
- package/src/features/watch-tower/WatchTowerModule.ts +23 -10
- package/src/features/watch-tower/index.ts +9 -1
- package/src/features/watch-tower/types/WatchTowerRequest.ts +47 -0
- package/src/features/watch-tower/types/WatchTowerResponse.ts +52 -0
- package/src/features/watch-tower/types/index.ts +10 -0
- package/src/{index.tsx → index.ts} +14 -1
- package/src/types/SDKConfig.ts +9 -4
|
@@ -22,27 +22,17 @@ import type {
|
|
|
22
22
|
GasFreeTransferRequest,
|
|
23
23
|
GasFreeTransferResult,
|
|
24
24
|
} from './types/GasFreeRequest';
|
|
25
|
+
import type {
|
|
26
|
+
FeeQuote,
|
|
27
|
+
VerificationResult,
|
|
28
|
+
PSBTBuildResult,
|
|
29
|
+
PSBTSubmitResult,
|
|
30
|
+
BroadcastResult,
|
|
31
|
+
TransferState,
|
|
32
|
+
} from './types';
|
|
25
33
|
import { GasFreeError, GasFreeErrorCode } from './errors/GasFreeError';
|
|
26
34
|
import type { AssignmentType } from '../../core/Interfaces';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Transfer state tracking
|
|
30
|
-
*/
|
|
31
|
-
interface TransferState {
|
|
32
|
-
quoteId?: string;
|
|
33
|
-
quoteExpiresAt?: number;
|
|
34
|
-
psbtBase64?: string;
|
|
35
|
-
txid?: string;
|
|
36
|
-
status:
|
|
37
|
-
| 'idle'
|
|
38
|
-
| 'quote-requested'
|
|
39
|
-
| 'psbt-built'
|
|
40
|
-
| 'submitted'
|
|
41
|
-
| 'broadcasted'
|
|
42
|
-
| 'verified'
|
|
43
|
-
| 'failed';
|
|
44
|
-
error?: Error;
|
|
45
|
-
}
|
|
35
|
+
import { Feature } from '../../types/Feature';
|
|
46
36
|
|
|
47
37
|
/**
|
|
48
38
|
* Gas-Free Transfer Module
|
|
@@ -55,7 +45,7 @@ interface TransferState {
|
|
|
55
45
|
* 5. Verify transfer completion
|
|
56
46
|
*/
|
|
57
47
|
export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
58
|
-
public readonly name =
|
|
48
|
+
public readonly name = Feature.GAS_FREE;
|
|
59
49
|
public readonly version = '1.0.0';
|
|
60
50
|
public readonly config: GasFreeConfig;
|
|
61
51
|
|
|
@@ -156,8 +146,19 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
156
146
|
*
|
|
157
147
|
* @param request - Transfer request parameters
|
|
158
148
|
* @returns Fee quote with pricing and expiration details
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* const quote = await gasFree.requestFeeQuote({
|
|
153
|
+
* userId: 'user-123',
|
|
154
|
+
* assetId: 'rgb:...',
|
|
155
|
+
* amount: '100',
|
|
156
|
+
* recipientInvoice: 'rgb:...'
|
|
157
|
+
* });
|
|
158
|
+
* console.log('Service fee:', quote.serviceFeeAmount);
|
|
159
|
+
* ```
|
|
159
160
|
*/
|
|
160
|
-
async requestFeeQuote(request: GasFreeTransferRequest): Promise<
|
|
161
|
+
async requestFeeQuote(request: GasFreeTransferRequest): Promise<FeeQuote> {
|
|
161
162
|
this.logger?.debug('Requesting fee quote', {
|
|
162
163
|
assetId: request.assetId,
|
|
163
164
|
amount: request.amount,
|
|
@@ -197,7 +198,7 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
/**
|
|
200
|
-
* Stage 2: Confirm and execute transfer using a fee quote
|
|
201
|
+
* Stage 2: Confirm and execute transfer using a fee quote (One-shot method)
|
|
201
202
|
*
|
|
202
203
|
* Executes the complete transfer workflow:
|
|
203
204
|
* 1. Build PSBT with external mining inputs
|
|
@@ -205,13 +206,26 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
205
206
|
* 3. Sign RGB inputs and broadcast transaction
|
|
206
207
|
* 4. Verify transfer completion with service
|
|
207
208
|
*
|
|
209
|
+
* For advanced users who need more control, use the individual stage methods:
|
|
210
|
+
* - buildPSBT()
|
|
211
|
+
* - submitPSBT()
|
|
212
|
+
* - broadcastTransfer()
|
|
213
|
+
* - verifyTransfer()
|
|
214
|
+
*
|
|
208
215
|
* @param request - Original transfer request parameters
|
|
209
216
|
* @param feeQuote - Fee quote obtained from requestFeeQuote()
|
|
210
217
|
* @returns Transfer result with txid and fee breakdown
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* const quote = await gasFree.requestFeeQuote(request);
|
|
222
|
+
* const result = await gasFree.confirmTransfer(request, quote);
|
|
223
|
+
* console.log('Transaction ID:', result.txid);
|
|
224
|
+
* ```
|
|
211
225
|
*/
|
|
212
226
|
async confirmTransfer(
|
|
213
227
|
request: GasFreeTransferRequest,
|
|
214
|
-
feeQuote:
|
|
228
|
+
feeQuote: FeeQuote
|
|
215
229
|
): Promise<GasFreeTransferResult> {
|
|
216
230
|
this.logger?.debug('Confirming transfer with quote', {
|
|
217
231
|
quoteId: feeQuote.quoteId,
|
|
@@ -355,9 +369,32 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
355
369
|
}
|
|
356
370
|
|
|
357
371
|
/**
|
|
358
|
-
*
|
|
372
|
+
* Advanced Stage 2a: Build PSBT with external mining inputs
|
|
373
|
+
*
|
|
374
|
+
* Builds an unsigned PSBT that includes:
|
|
375
|
+
* - External mining input from the service (provides BTC for fees)
|
|
376
|
+
* - User's RGB asset inputs
|
|
377
|
+
* - Two RGB recipients: merchant + service fee
|
|
378
|
+
* - External change output (BTC change back to service)
|
|
379
|
+
*
|
|
380
|
+
* This method writes the RGB consignment file to disk which will be read
|
|
381
|
+
* in the next stage (submitPSBT).
|
|
382
|
+
*
|
|
383
|
+
* @param request - Transfer request parameters
|
|
384
|
+
* @param feeQuote - Fee quote from requestFeeQuote()
|
|
385
|
+
* @returns PSBT build result with unsigned PSBT and mining details
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```typescript
|
|
389
|
+
* const quote = await gasFree.requestFeeQuote(request);
|
|
390
|
+
* const psbtResult = await gasFree.buildPSBT(request, quote);
|
|
391
|
+
* console.log('Unsigned PSBT:', psbtResult.unsignedPsbt);
|
|
392
|
+
* ```
|
|
359
393
|
*/
|
|
360
|
-
|
|
394
|
+
async buildPSBT(
|
|
395
|
+
request: GasFreeTransferRequest,
|
|
396
|
+
feeQuote: FeeQuote
|
|
397
|
+
): Promise<PSBTBuildResult> {
|
|
361
398
|
this.logger?.debug('Step 2: Building PSBT with external inputs');
|
|
362
399
|
|
|
363
400
|
// Check quote not expired
|
|
@@ -404,6 +441,8 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
404
441
|
|
|
405
442
|
// Build recipient map for sendBegin
|
|
406
443
|
// Note: Recipient requires assignment field with type and amount
|
|
444
|
+
// Important: Decoded invoices may have 'ANY' type (wildcard), but sendBegin
|
|
445
|
+
// requires a concrete assignment type. Always use 'FUNGIBLE' for asset transfers.
|
|
407
446
|
const recipientMap: Record<
|
|
408
447
|
string,
|
|
409
448
|
Array<{
|
|
@@ -417,11 +456,10 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
417
456
|
// Recipient 1: The actual transfer to the merchant / end recipient
|
|
418
457
|
recipientId: decodedRecipientInvoice.recipientId,
|
|
419
458
|
assignment: {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
amount
|
|
423
|
-
|
|
424
|
-
decodedRecipientInvoice.assignment.amount,
|
|
459
|
+
// Use FUNGIBLE type for asset transfers (invoice may have 'ANY' wildcard type)
|
|
460
|
+
type: 'FUNGIBLE',
|
|
461
|
+
// Use amount from request (in base units (w/ precision), as integer)
|
|
462
|
+
amount: parseInt(request.amount, 10),
|
|
425
463
|
},
|
|
426
464
|
transportEndpoints: decodedRecipientInvoice.transportEndpoints,
|
|
427
465
|
},
|
|
@@ -430,11 +468,10 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
430
468
|
// as payment for covering the Bitcoin mining fee.
|
|
431
469
|
recipientId: decodedServiceInvoice.recipientId,
|
|
432
470
|
assignment: {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
amount
|
|
436
|
-
|
|
437
|
-
decodedServiceInvoice.assignment.amount,
|
|
471
|
+
// Use FUNGIBLE type for service fee (invoice may have 'ANY' wildcard type)
|
|
472
|
+
type: 'FUNGIBLE',
|
|
473
|
+
// Use service fee amount from quote
|
|
474
|
+
amount: feeQuote.serviceFeeAmount, // includes precision
|
|
438
475
|
},
|
|
439
476
|
transportEndpoints: decodedServiceInvoice.transportEndpoints,
|
|
440
477
|
},
|
|
@@ -467,22 +504,39 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
467
504
|
}
|
|
468
505
|
|
|
469
506
|
/**
|
|
470
|
-
*
|
|
507
|
+
* Advanced Stage 2b: Submit unsigned PSBT to service for co-signing
|
|
508
|
+
*
|
|
509
|
+
* Submits the unsigned PSBT along with the RGB consignment to the service.
|
|
510
|
+
* The service will:
|
|
511
|
+
* 1. Cryptographically verify the RGB fee allocation in the consignment
|
|
512
|
+
* 2. Co-sign the mining input
|
|
513
|
+
* 3. Return the PSBT with its signature attached
|
|
471
514
|
*
|
|
472
|
-
*
|
|
473
|
-
* 1. Verifies the consignment cryptographically
|
|
474
|
-
* 2. Co-signs the mining input
|
|
475
|
-
* 3. Returns the PSBT with its signature attached — user's RGB inputs
|
|
476
|
-
* are still unsigned at this point
|
|
515
|
+
* Note: User's RGB inputs remain unsigned at this stage.
|
|
477
516
|
*
|
|
478
|
-
*
|
|
517
|
+
* @param quoteId - Quote ID from the fee quote
|
|
518
|
+
* @param psbtResult - PSBT build result from buildPSBT()
|
|
519
|
+
* @param serviceFeeInvoice - Service fee RGB invoice from the quote
|
|
520
|
+
* @param assetId - Asset ID being transferred
|
|
521
|
+
* @returns Submit result with service-signed PSBT
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```typescript
|
|
525
|
+
* const submitResult = await gasFree.submitPSBT(
|
|
526
|
+
* quote.quoteId,
|
|
527
|
+
* psbtResult,
|
|
528
|
+
* quote.serviceFeeInvoice,
|
|
529
|
+
* request.assetId
|
|
530
|
+
* );
|
|
531
|
+
* console.log('Service signed PSBT:', submitResult.signedPsbtBase64);
|
|
532
|
+
* ```
|
|
479
533
|
*/
|
|
480
|
-
|
|
534
|
+
async submitPSBT(
|
|
481
535
|
quoteId: string,
|
|
482
|
-
psbtResult:
|
|
536
|
+
psbtResult: PSBTBuildResult,
|
|
483
537
|
serviceFeeInvoice: string,
|
|
484
538
|
assetId: string
|
|
485
|
-
) {
|
|
539
|
+
): Promise<PSBTSubmitResult> {
|
|
486
540
|
this.logger?.debug('Step 3: Reading consignment and submitting to service');
|
|
487
541
|
|
|
488
542
|
const consignmentBase64 = await this.consignmentReader!.readForAsset(
|
|
@@ -508,20 +562,27 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
508
562
|
}
|
|
509
563
|
|
|
510
564
|
/**
|
|
511
|
-
*
|
|
565
|
+
* Advanced Stage 2c: Sign RGB inputs and broadcast transaction
|
|
512
566
|
*
|
|
513
567
|
* Takes the PSBT returned by the service (mining input already signed),
|
|
514
|
-
* adds the user's RGB input signatures, then calls sendEnd() which:
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
568
|
+
* adds the user's RGB input signatures, then calls wallet.sendEnd() which:
|
|
569
|
+
* - Finalizes all inputs (combines witness data)
|
|
570
|
+
* - Posts consignments to the RGB proxy
|
|
571
|
+
* - Broadcasts the transaction to the Bitcoin network
|
|
572
|
+
*
|
|
573
|
+
* @param serviceSignedPsbt - Service-signed PSBT from submitPSBT()
|
|
574
|
+
* @returns Broadcast result with txid and fully-signed PSBT
|
|
518
575
|
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
576
|
+
* @example
|
|
577
|
+
* ```typescript
|
|
578
|
+
* const broadcastResult = await gasFree.broadcastTransfer(
|
|
579
|
+
* submitResult.signedPsbtBase64
|
|
580
|
+
* );
|
|
581
|
+
* console.log('Transaction ID:', broadcastResult.txid);
|
|
582
|
+
* console.log('Fully signed PSBT:', broadcastResult.userSignedPsbt);
|
|
583
|
+
* ```
|
|
521
584
|
*/
|
|
522
|
-
|
|
523
|
-
serviceSignedPsbt: string
|
|
524
|
-
): Promise<{ txid: string; userSignedPsbt: string }> {
|
|
585
|
+
async broadcastTransfer(serviceSignedPsbt: string): Promise<BroadcastResult> {
|
|
525
586
|
this.logger?.debug(
|
|
526
587
|
'Step 4: User signs RGB inputs and broadcasts via sendEnd'
|
|
527
588
|
);
|
|
@@ -550,17 +611,34 @@ export class GasFreeModule implements IFeatureModule<GasFreeConfig> {
|
|
|
550
611
|
}
|
|
551
612
|
|
|
552
613
|
/**
|
|
553
|
-
*
|
|
614
|
+
* Advanced Stage 2d: Verify transfer completion with service
|
|
554
615
|
*
|
|
555
616
|
* Notifies the service that the transaction has been broadcast. The service
|
|
556
|
-
* will
|
|
557
|
-
*
|
|
617
|
+
* will:
|
|
618
|
+
* - Look up the txid in mempool to confirm it landed
|
|
619
|
+
* - Call its own wallet.refresh() to claim the RGB service fee
|
|
620
|
+
*
|
|
621
|
+
* @param quoteId - Quote ID from the fee quote
|
|
622
|
+
* @param txid - Transaction ID from broadcastTransfer()
|
|
623
|
+
* @param signedPsbtBase64 - Fully-signed PSBT from broadcastTransfer()
|
|
624
|
+
* @returns Verification result from the service
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```typescript
|
|
628
|
+
* const verifyResult = await gasFree.verifyTransfer(
|
|
629
|
+
* quote.quoteId,
|
|
630
|
+
* broadcastResult.txid,
|
|
631
|
+
* broadcastResult.userSignedPsbt
|
|
632
|
+
* );
|
|
633
|
+
* console.log('Verification status:', verifyResult.status);
|
|
634
|
+
* console.log('In mempool:', verifyResult.inMempool);
|
|
635
|
+
* ```
|
|
558
636
|
*/
|
|
559
|
-
|
|
637
|
+
async verifyTransfer(
|
|
560
638
|
quoteId: string,
|
|
561
639
|
txid: string,
|
|
562
640
|
signedPsbtBase64: string
|
|
563
|
-
) {
|
|
641
|
+
): Promise<VerificationResult> {
|
|
564
642
|
this.logger?.debug('Step 4: Verifying transfer');
|
|
565
643
|
|
|
566
644
|
const verifyResult = await this.serviceClient!.verifyTransfer({
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gas-Free Transfer Stage Result Types
|
|
3
|
+
*
|
|
4
|
+
* Result types for individual stages of the gas-free transfer workflow.
|
|
5
|
+
* These types are used by advanced users who want granular control over
|
|
6
|
+
* each stage of the transfer process.
|
|
7
|
+
*
|
|
8
|
+
* @module features/gas-free/types/StageResults
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Transfer state tracking
|
|
13
|
+
*
|
|
14
|
+
* Internal state used by the GasFreeModule to track the progress
|
|
15
|
+
* of a gas-free transfer through its various stages.
|
|
16
|
+
*/
|
|
17
|
+
export interface TransferState {
|
|
18
|
+
/** Quote ID from the fee quote */
|
|
19
|
+
quoteId?: string;
|
|
20
|
+
/** Quote expiration timestamp (milliseconds) */
|
|
21
|
+
quoteExpiresAt?: number;
|
|
22
|
+
/** Base64-encoded PSBT */
|
|
23
|
+
psbtBase64?: string;
|
|
24
|
+
/** Transaction ID */
|
|
25
|
+
txid?: string;
|
|
26
|
+
/** Current transfer status */
|
|
27
|
+
status:
|
|
28
|
+
| 'idle'
|
|
29
|
+
| 'quote-requested'
|
|
30
|
+
| 'psbt-built'
|
|
31
|
+
| 'submitted'
|
|
32
|
+
| 'broadcasted'
|
|
33
|
+
| 'verified'
|
|
34
|
+
| 'failed';
|
|
35
|
+
/** Error if transfer failed */
|
|
36
|
+
error?: Error;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Result of PSBT building stage (buildPSBT)
|
|
41
|
+
*
|
|
42
|
+
* Contains the unsigned PSBT with external mining inputs from the service,
|
|
43
|
+
* along with details about the mining fee and external inputs.
|
|
44
|
+
*/
|
|
45
|
+
export interface PSBTBuildResult {
|
|
46
|
+
/** Unsigned PSBT (base64) with external mining inputs */
|
|
47
|
+
unsignedPsbt: string;
|
|
48
|
+
/** Mining fee in satoshis */
|
|
49
|
+
miningFee: number;
|
|
50
|
+
/** External inputs added to the PSBT */
|
|
51
|
+
externalInputs: Array<{
|
|
52
|
+
txid: string;
|
|
53
|
+
vout: number;
|
|
54
|
+
value: number;
|
|
55
|
+
scriptPubkey: string;
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Result of PSBT submission stage (submitPSBT)
|
|
61
|
+
*
|
|
62
|
+
* Contains the service-signed PSBT along with transaction details
|
|
63
|
+
* and the RGB consignment data.
|
|
64
|
+
*/
|
|
65
|
+
export interface PSBTSubmitResult {
|
|
66
|
+
/** Quote ID used */
|
|
67
|
+
quoteId: string;
|
|
68
|
+
/** Base64-encoded signed PSBT with service signatures */
|
|
69
|
+
signedPsbtBase64: string;
|
|
70
|
+
/** Transaction ID */
|
|
71
|
+
transactionId: string;
|
|
72
|
+
/** Estimated transaction size in vBytes */
|
|
73
|
+
estimatedTxSize: number;
|
|
74
|
+
/** Mining UTXO transaction ID */
|
|
75
|
+
miningUtxoTxid: string;
|
|
76
|
+
/** Mining UTXO output index */
|
|
77
|
+
miningUtxoVout: number;
|
|
78
|
+
/** Timestamp when signed */
|
|
79
|
+
signedAt: string;
|
|
80
|
+
/** Base64-encoded consignment data */
|
|
81
|
+
consignmentBase64: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Result of broadcast stage (broadcastTransfer)
|
|
86
|
+
*
|
|
87
|
+
* Contains the transaction ID from the successful broadcast and
|
|
88
|
+
* the fully-signed PSBT with both user and service signatures.
|
|
89
|
+
*/
|
|
90
|
+
export interface BroadcastResult {
|
|
91
|
+
/** Transaction ID from the broadcast */
|
|
92
|
+
txid: string;
|
|
93
|
+
/** Fully signed PSBT (user + service signatures) */
|
|
94
|
+
userSignedPsbt: string;
|
|
95
|
+
}
|
|
@@ -48,3 +48,11 @@ export {
|
|
|
48
48
|
isTransferSuccessful,
|
|
49
49
|
getTransferDuration,
|
|
50
50
|
} from './GasFreeResult';
|
|
51
|
+
|
|
52
|
+
// Stage result types (for advanced users)
|
|
53
|
+
export type {
|
|
54
|
+
TransferState,
|
|
55
|
+
PSBTBuildResult,
|
|
56
|
+
PSBTSubmitResult,
|
|
57
|
+
BroadcastResult,
|
|
58
|
+
} from './StageResults';
|
|
@@ -13,10 +13,13 @@ import type { IFeatureModule } from '../../types/IFeatureModule';
|
|
|
13
13
|
import type { Wallet } from '../../core/Wallet';
|
|
14
14
|
import type { Logger } from '../../utils/logger';
|
|
15
15
|
import type { WatchTowerConfig } from './types';
|
|
16
|
+
import type { AddToWatchTowerParams } from './types/WatchTowerRequest';
|
|
17
|
+
import type { AddToWatchTowerResponse } from './types/WatchTowerResponse';
|
|
16
18
|
import { getWatchTowerServiceUrl } from './types/WatchTowerConfig';
|
|
19
|
+
import { Feature } from '../../types/Feature';
|
|
17
20
|
|
|
18
21
|
export class WatchTowerModule implements IFeatureModule<WatchTowerConfig> {
|
|
19
|
-
readonly name =
|
|
22
|
+
readonly name = Feature.WATCH_TOWER;
|
|
20
23
|
readonly config: WatchTowerConfig;
|
|
21
24
|
|
|
22
25
|
private client: AxiosInstance | null = null;
|
|
@@ -75,12 +78,17 @@ export class WatchTowerModule implements IFeatureModule<WatchTowerConfig> {
|
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
/**
|
|
78
|
-
*
|
|
81
|
+
* Register an RGB invoice with the Watch Tower service.
|
|
79
82
|
*
|
|
80
|
-
* @param
|
|
81
|
-
* @returns
|
|
83
|
+
* @param params - Invoice string plus optional FCM token, email, or web push subscription
|
|
84
|
+
* @returns Successful response body (`status`, `message`, `data`). Errors throw.
|
|
82
85
|
*/
|
|
83
|
-
async addToWatchTower(
|
|
86
|
+
async addToWatchTower({
|
|
87
|
+
invoice,
|
|
88
|
+
fcmToken,
|
|
89
|
+
email,
|
|
90
|
+
webPushNotification,
|
|
91
|
+
}: AddToWatchTowerParams): Promise<AddToWatchTowerResponse> {
|
|
84
92
|
if (!this.isReady() || !this.client) {
|
|
85
93
|
throw new Error(
|
|
86
94
|
'Orbis1 SDK not initialized. Call initOrbis1({ apiKey }) first.'
|
|
@@ -91,13 +99,18 @@ export class WatchTowerModule implements IFeatureModule<WatchTowerConfig> {
|
|
|
91
99
|
invoicePrefix: invoice.slice(0, 20) + '...',
|
|
92
100
|
});
|
|
93
101
|
|
|
94
|
-
const payload:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
const payload: AddToWatchTowerParams = {
|
|
103
|
+
invoice,
|
|
104
|
+
fcmToken: fcmToken ?? this.fcmToken,
|
|
105
|
+
...(email && { email }),
|
|
106
|
+
...(webPushNotification && { webPushNotification }),
|
|
107
|
+
};
|
|
98
108
|
|
|
99
109
|
try {
|
|
100
|
-
const response = await this.client.post(
|
|
110
|
+
const response = await this.client.post<AddToWatchTowerResponse>(
|
|
111
|
+
'/addToWatchTower',
|
|
112
|
+
payload
|
|
113
|
+
);
|
|
101
114
|
this.logger?.debug('Invoice added successfully');
|
|
102
115
|
return response.data;
|
|
103
116
|
} catch (error) {
|
|
@@ -5,4 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export { WatchTowerModule } from './WatchTowerModule';
|
|
8
|
-
export type {
|
|
8
|
+
export type {
|
|
9
|
+
WatchTowerConfig,
|
|
10
|
+
AddToWatchTowerParams,
|
|
11
|
+
AddToWatchTowerResponse,
|
|
12
|
+
AddToWatchTowerResponseData,
|
|
13
|
+
AddToWatchTowerWebPushEcho,
|
|
14
|
+
WatchTowerWebPushKeys,
|
|
15
|
+
WatchTowerWebPushSubscription,
|
|
16
|
+
} from './types';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch Tower request types
|
|
3
|
+
*
|
|
4
|
+
* Parameters for Watch Tower service calls
|
|
5
|
+
*
|
|
6
|
+
* @module features/watch-tower/types/WatchTowerRequest
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Web Push subscription keys (from `PushSubscription.getKey()`)
|
|
11
|
+
*/
|
|
12
|
+
export interface WatchTowerWebPushKeys {
|
|
13
|
+
/** Base64 URL-safe P-256 ECDH public key */
|
|
14
|
+
p256dh: string;
|
|
15
|
+
|
|
16
|
+
/** Base64 URL-safe authentication secret */
|
|
17
|
+
auth: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Web Push subscription payload for the Watch Tower service
|
|
22
|
+
*/
|
|
23
|
+
export interface WatchTowerWebPushSubscription {
|
|
24
|
+
/** Push service endpoint URL */
|
|
25
|
+
endpoint: string;
|
|
26
|
+
|
|
27
|
+
/** Encryption keys from the browser push subscription */
|
|
28
|
+
keys: WatchTowerWebPushKeys;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Parameters for WatchTowerModule.addToWatchTower */
|
|
32
|
+
export interface AddToWatchTowerParams {
|
|
33
|
+
/** RGB invoice string to monitor */
|
|
34
|
+
invoice: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* FCM device token for mobile push notifications.
|
|
38
|
+
* If omitted, the default from WatchTowerModule.setFcmToken is used when set.
|
|
39
|
+
*/
|
|
40
|
+
fcmToken?: string;
|
|
41
|
+
|
|
42
|
+
/** Email address for notifications */
|
|
43
|
+
email?: string;
|
|
44
|
+
|
|
45
|
+
/** Web Push subscription for browser notifications */
|
|
46
|
+
webPushNotification?: WatchTowerWebPushSubscription;
|
|
47
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch Tower API response types
|
|
3
|
+
*
|
|
4
|
+
* @module features/watch-tower/types/WatchTowerResponse
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { WatchTowerWebPushKeys } from './WatchTowerRequest';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Web push subscription as returned by the service (`webPushSubscription` field).
|
|
11
|
+
* Mirrors the stored subscription shape (distinct request field name `webPushNotification`).
|
|
12
|
+
*/
|
|
13
|
+
export interface AddToWatchTowerWebPushEcho {
|
|
14
|
+
endpoint: string;
|
|
15
|
+
keys: WatchTowerWebPushKeys;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `data` payload on successful `POST /addToWatchTower`
|
|
20
|
+
*/
|
|
21
|
+
export interface AddToWatchTowerResponseData {
|
|
22
|
+
/** RGB invoice registered with Watch Tower */
|
|
23
|
+
invoice: string;
|
|
24
|
+
|
|
25
|
+
/** Parsed recipient / UTXO identifier from the invoice */
|
|
26
|
+
recipient_id: string;
|
|
27
|
+
|
|
28
|
+
/** RGB transport endpoint extracted from the invoice */
|
|
29
|
+
endpoint_url: string;
|
|
30
|
+
|
|
31
|
+
/** Present when an FCM token was registered */
|
|
32
|
+
fcmToken?: string;
|
|
33
|
+
|
|
34
|
+
/** Present when a web push subscription was registered */
|
|
35
|
+
webPushSubscription?: AddToWatchTowerWebPushEcho;
|
|
36
|
+
|
|
37
|
+
/** Present when an email was registered */
|
|
38
|
+
email?: string;
|
|
39
|
+
|
|
40
|
+
/** Watch Tower expiry for this registration (Unix seconds) */
|
|
41
|
+
expiry: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Successful JSON body returned by `addToWatchTower` (HTTP 2xx).
|
|
46
|
+
* Error responses are thrown as `Error` with optional `status` / `data`.
|
|
47
|
+
*/
|
|
48
|
+
export interface AddToWatchTowerResponse {
|
|
49
|
+
status: string;
|
|
50
|
+
message: string;
|
|
51
|
+
data: AddToWatchTowerResponseData;
|
|
52
|
+
}
|
|
@@ -1 +1,11 @@
|
|
|
1
1
|
export type { WatchTowerConfig } from './WatchTowerConfig';
|
|
2
|
+
export type {
|
|
3
|
+
AddToWatchTowerParams,
|
|
4
|
+
WatchTowerWebPushKeys,
|
|
5
|
+
WatchTowerWebPushSubscription,
|
|
6
|
+
} from './WatchTowerRequest';
|
|
7
|
+
export type {
|
|
8
|
+
AddToWatchTowerResponse,
|
|
9
|
+
AddToWatchTowerResponseData,
|
|
10
|
+
AddToWatchTowerWebPushEcho,
|
|
11
|
+
} from './WatchTowerResponse';
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
// Core exports
|
|
10
10
|
export * from './core/Interfaces';
|
|
11
11
|
export * from './core/KeyManager';
|
|
12
|
+
export type { Wallet } from './core/Wallet';
|
|
12
13
|
|
|
13
14
|
// SDK
|
|
14
15
|
export { Orbis1SDK } from './Orbis1SDK';
|
|
@@ -29,7 +30,15 @@ export { Logger, createLogger } from './utils/logger';
|
|
|
29
30
|
|
|
30
31
|
// Watch Tower feature
|
|
31
32
|
export { WatchTowerModule } from './features/watch-tower';
|
|
32
|
-
export type {
|
|
33
|
+
export type {
|
|
34
|
+
WatchTowerConfig,
|
|
35
|
+
AddToWatchTowerParams,
|
|
36
|
+
AddToWatchTowerResponse,
|
|
37
|
+
AddToWatchTowerResponseData,
|
|
38
|
+
AddToWatchTowerWebPushEcho,
|
|
39
|
+
WatchTowerWebPushKeys,
|
|
40
|
+
WatchTowerWebPushSubscription,
|
|
41
|
+
} from './features/watch-tower';
|
|
33
42
|
|
|
34
43
|
// Gas-Free feature
|
|
35
44
|
export { GasFreeModule, createGasFreeModule } from './features/gas-free';
|
|
@@ -38,5 +47,9 @@ export type {
|
|
|
38
47
|
GasFreeTransferRequest,
|
|
39
48
|
GasFreeTransferResult,
|
|
40
49
|
FeeQuote,
|
|
50
|
+
PSBTBuildResult,
|
|
51
|
+
PSBTSubmitResult,
|
|
52
|
+
BroadcastResult,
|
|
53
|
+
TransferState,
|
|
41
54
|
} from './features/gas-free/types';
|
|
42
55
|
export { GasFreeError, GasFreeErrorCode } from './features/gas-free/errors';
|
package/src/types/SDKConfig.ts
CHANGED
|
@@ -49,9 +49,11 @@ export enum LogLevel {
|
|
|
49
49
|
*/
|
|
50
50
|
export enum Environment {
|
|
51
51
|
/** Testnet4 environment */
|
|
52
|
-
|
|
52
|
+
TESTNET4 = 'TESTNET4',
|
|
53
|
+
/** Regtest environment */
|
|
54
|
+
REGTEST = 'REGTEST',
|
|
53
55
|
/** Mainnet environment (production) */
|
|
54
|
-
MAINNET = '
|
|
56
|
+
MAINNET = 'MAINNET',
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
/**
|
|
@@ -216,10 +218,13 @@ export function validateSDKConfig(config: SDKConfig): void {
|
|
|
216
218
|
const apiKey = config.apiKey;
|
|
217
219
|
const environment = config.environment ?? Environment.MAINNET;
|
|
218
220
|
|
|
219
|
-
if (
|
|
221
|
+
if (
|
|
222
|
+
environment === Environment.TESTNET4 ||
|
|
223
|
+
environment === Environment.REGTEST
|
|
224
|
+
) {
|
|
220
225
|
if (!apiKey.startsWith('pk_test')) {
|
|
221
226
|
throw new Error(
|
|
222
|
-
`API key mismatch:
|
|
227
|
+
`API key mismatch: ${environment} environment requires a testnet API key (prefix: pk_test), but got a key with prefix: ${apiKey.substring(
|
|
223
228
|
0,
|
|
224
229
|
7
|
|
225
230
|
)}`
|