@1sat/wallet-toolbox 0.0.73 → 0.0.75
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/api/balance/index.d.ts +1 -11
- package/dist/api/balance/index.js +1 -35
- package/dist/api/locks/index.js +10 -23
- package/dist/api/ordinals/index.js +8 -5
- package/dist/api/sweep/index.js +30 -27
- package/dist/api/tokens/index.js +10 -9
- package/dist/index.d.ts +1 -1
- package/dist/indexers/Bsv21Indexer.js +3 -3
- package/dist/indexers/types.d.ts +5 -6
- package/dist/services/OneSatServices.js +4 -6
- package/dist/services/client/Bsv21Client.d.ts +38 -11
- package/dist/services/client/Bsv21Client.js +54 -10
- package/dist/services/client/OverlayClient.d.ts +0 -17
- package/dist/services/client/OverlayClient.js +0 -33
- package/dist/services/types.d.ts +28 -19
- package/dist/sync/SyncManager.d.ts +3 -3
- package/dist/sync/SyncManager.js +22 -18
- package/dist/wallet/factory.js +2 -2
- package/package.json +1 -1
|
@@ -36,15 +36,5 @@ export type GetExchangeRateInput = Record<string, never>;
|
|
|
36
36
|
* Get current BSV/USD exchange rate.
|
|
37
37
|
*/
|
|
38
38
|
export declare const getExchangeRate: Skill<GetExchangeRateInput, number>;
|
|
39
|
-
/** Input for getChainInfo skill (no required params) */
|
|
40
|
-
export type GetChainInfoInput = Record<string, never>;
|
|
41
|
-
/** Output for getChainInfo skill */
|
|
42
|
-
export interface ChainInfo {
|
|
43
|
-
blocks: number;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Get chain info from WhatsOnChain.
|
|
47
|
-
*/
|
|
48
|
-
export declare const getChainInfo: Skill<GetChainInfoInput, ChainInfo | null>;
|
|
49
39
|
/** All balance skills for registry */
|
|
50
|
-
export declare const balanceSkills: (Skill<GetBalanceInput, Balance> | Skill<GetPaymentUtxosInput, PaymentUtxo[]> | Skill<GetExchangeRateInput, number>
|
|
40
|
+
export declare const balanceSkills: (Skill<GetBalanceInput, Balance> | Skill<GetPaymentUtxosInput, PaymentUtxo[]> | Skill<GetExchangeRateInput, number>)[];
|
|
@@ -103,42 +103,8 @@ export const getExchangeRate = {
|
|
|
103
103
|
return fetchExchangeRate(ctx.chain, ctx.wocApiKey);
|
|
104
104
|
},
|
|
105
105
|
};
|
|
106
|
-
/**
|
|
107
|
-
* Get chain info from WhatsOnChain.
|
|
108
|
-
*/
|
|
109
|
-
export const getChainInfo = {
|
|
110
|
-
meta: {
|
|
111
|
-
name: "getChainInfo",
|
|
112
|
-
description: "Get current chain info (block height) from WhatsOnChain",
|
|
113
|
-
category: "balance",
|
|
114
|
-
inputSchema: {
|
|
115
|
-
type: "object",
|
|
116
|
-
properties: {},
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
async execute(ctx) {
|
|
120
|
-
const baseUrl = ctx.chain === "main" ? WOC_MAINNET_URL : WOC_TESTNET_URL;
|
|
121
|
-
const headers = {};
|
|
122
|
-
if (ctx.wocApiKey)
|
|
123
|
-
headers["woc-api-key"] = ctx.wocApiKey;
|
|
124
|
-
try {
|
|
125
|
-
const response = await fetch(`${baseUrl}/chain/info`, { headers });
|
|
126
|
-
if (!response.ok)
|
|
127
|
-
return null;
|
|
128
|
-
return await response.json();
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
106
|
// ============================================================================
|
|
136
107
|
// Module exports
|
|
137
108
|
// ============================================================================
|
|
138
109
|
/** All balance skills for registry */
|
|
139
|
-
export const balanceSkills = [
|
|
140
|
-
getBalance,
|
|
141
|
-
getPaymentUtxos,
|
|
142
|
-
getExchangeRate,
|
|
143
|
-
getChainInfo,
|
|
144
|
-
];
|
|
110
|
+
export const balanceSkills = [getBalance, getPaymentUtxos, getExchangeRate];
|
package/dist/api/locks/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Skills for time-locking BSV.
|
|
5
5
|
*/
|
|
6
6
|
import { Hash, PublicKey, Script, Transaction, TransactionSignature, Utils, } from "@bsv/sdk";
|
|
7
|
-
import { LOCK_BASKET, LOCK_PREFIX, LOCK_SUFFIX, MIN_UNLOCK_SATS,
|
|
7
|
+
import { LOCK_BASKET, LOCK_PREFIX, LOCK_SUFFIX, MIN_UNLOCK_SATS, } from "../constants";
|
|
8
8
|
// ============================================================================
|
|
9
9
|
// Constants
|
|
10
10
|
// ============================================================================
|
|
@@ -21,21 +21,6 @@ function buildLockScript(address, until) {
|
|
|
21
21
|
.writeNumber(until)
|
|
22
22
|
.writeScript(Script.fromHex(LOCK_SUFFIX));
|
|
23
23
|
}
|
|
24
|
-
async function getChainInfoInternal(chain, wocApiKey) {
|
|
25
|
-
const baseUrl = chain === "main" ? WOC_MAINNET_URL : WOC_TESTNET_URL;
|
|
26
|
-
const headers = {};
|
|
27
|
-
if (wocApiKey)
|
|
28
|
-
headers["woc-api-key"] = wocApiKey;
|
|
29
|
-
try {
|
|
30
|
-
const response = await fetch(`${baseUrl}/chain/info`, { headers });
|
|
31
|
-
if (!response.ok)
|
|
32
|
-
return null;
|
|
33
|
-
return await response.json();
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
24
|
/**
|
|
40
25
|
* Get lock data summary.
|
|
41
26
|
*/
|
|
@@ -51,8 +36,9 @@ export const getLockData = {
|
|
|
51
36
|
},
|
|
52
37
|
async execute(ctx) {
|
|
53
38
|
const lockData = { totalLocked: 0, unlockable: 0, nextUnlock: 0 };
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
if (!ctx.services)
|
|
40
|
+
return lockData;
|
|
41
|
+
const currentHeight = await ctx.services.chaintracks.currentHeight();
|
|
56
42
|
const result = await ctx.wallet.listOutputs({
|
|
57
43
|
basket: LOCK_BASKET,
|
|
58
44
|
includeTags: true,
|
|
@@ -178,11 +164,9 @@ export const unlockBsv = {
|
|
|
178
164
|
},
|
|
179
165
|
async execute(ctx) {
|
|
180
166
|
try {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return { error: "could-not-get-block-height" };
|
|
185
|
-
}
|
|
167
|
+
if (!ctx.services)
|
|
168
|
+
return { error: "services-required" };
|
|
169
|
+
const currentHeight = await ctx.services.chaintracks.currentHeight();
|
|
186
170
|
const result = await ctx.wallet.listOutputs({
|
|
187
171
|
basket: LOCK_BASKET,
|
|
188
172
|
includeTags: true,
|
|
@@ -244,6 +228,9 @@ export const unlockBsv = {
|
|
|
244
228
|
for (let i = 0; i < maturedLocks.length; i++) {
|
|
245
229
|
const lock = maturedLocks[i];
|
|
246
230
|
const input = tx.inputs[i];
|
|
231
|
+
if (!lock.output.lockingScript || !input.sourceTXID) {
|
|
232
|
+
return { error: "missing-lock-data" };
|
|
233
|
+
}
|
|
247
234
|
const lockingScript = Script.fromHex(lock.output.lockingScript);
|
|
248
235
|
const preimage = TransactionSignature.format({
|
|
249
236
|
sourceTXID: input.sourceTXID,
|
|
@@ -175,9 +175,12 @@ export async function buildTransferOrdinals(ctx, request) {
|
|
|
175
175
|
});
|
|
176
176
|
recipientAddress = PublicKey.fromString(publicKey).toAddress();
|
|
177
177
|
}
|
|
178
|
-
else {
|
|
178
|
+
else if (address) {
|
|
179
179
|
recipientAddress = address;
|
|
180
180
|
}
|
|
181
|
+
else {
|
|
182
|
+
return { error: "must-provide-counterparty-or-address" };
|
|
183
|
+
}
|
|
181
184
|
// Preserve important tags from source output
|
|
182
185
|
const tags = [];
|
|
183
186
|
for (const tag of ordinal.tags ?? []) {
|
|
@@ -188,7 +191,7 @@ export async function buildTransferOrdinals(ctx, request) {
|
|
|
188
191
|
}
|
|
189
192
|
}
|
|
190
193
|
const sourceName = extractName(ordinal.customInstructions);
|
|
191
|
-
inputs
|
|
194
|
+
inputs?.push({
|
|
192
195
|
outpoint,
|
|
193
196
|
inputDescription: "Ordinal to transfer",
|
|
194
197
|
unlockingScriptLength: 108,
|
|
@@ -196,7 +199,7 @@ export async function buildTransferOrdinals(ctx, request) {
|
|
|
196
199
|
// Only track output in wallet when transferring to a counterparty (wallet can derive keys to spend it)
|
|
197
200
|
// External address transfers are NOT tracked since the wallet cannot spend them
|
|
198
201
|
if (counterparty) {
|
|
199
|
-
outputs
|
|
202
|
+
outputs?.push({
|
|
200
203
|
lockingScript: new P2PKH().lock(recipientAddress).toHex(),
|
|
201
204
|
satoshis: 1,
|
|
202
205
|
outputDescription: "Ordinal transfer",
|
|
@@ -211,7 +214,7 @@ export async function buildTransferOrdinals(ctx, request) {
|
|
|
211
214
|
}
|
|
212
215
|
else {
|
|
213
216
|
// External address - output is not tracked in wallet
|
|
214
|
-
outputs
|
|
217
|
+
outputs?.push({
|
|
215
218
|
lockingScript: new P2PKH().lock(recipientAddress).toHex(),
|
|
216
219
|
satoshis: 1,
|
|
217
220
|
outputDescription: "Ordinal transfer to external address",
|
|
@@ -396,7 +399,7 @@ export const transferOrdinals = {
|
|
|
396
399
|
inputs: params.inputs,
|
|
397
400
|
outputs: params.outputs?.map((o) => ({
|
|
398
401
|
...o,
|
|
399
|
-
lockingScript: o.lockingScript?.slice(0, 20)
|
|
402
|
+
lockingScript: `${o.lockingScript?.slice(0, 20)}...`,
|
|
400
403
|
})),
|
|
401
404
|
}, null, 2));
|
|
402
405
|
// Debug: Check if BEEF contains the source transactions
|
package/dist/api/sweep/index.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { BSV21 } from "@bopen-io/templates";
|
|
7
7
|
import { P2PKH, PrivateKey, PublicKey, Transaction, Utils, } from "@bsv/sdk";
|
|
8
|
-
import {
|
|
9
|
-
import { BSV21_BASKET, BSV21_FEE_SATS, BSV21_PROTOCOL, ONESAT_PROTOCOL, } from "../constants";
|
|
8
|
+
import { BSV21_BASKET, BSV21_PROTOCOL, ONESAT_PROTOCOL } from "../constants";
|
|
10
9
|
export * from "./types";
|
|
11
10
|
/**
|
|
12
11
|
* Prepare sweep inputs from IndexedOutput objects by fetching locking scripts.
|
|
@@ -359,19 +358,19 @@ export const sweepOrdinals = {
|
|
|
359
358
|
outputs,
|
|
360
359
|
options: { signAndProcess: false, randomizeOutputs: false },
|
|
361
360
|
};
|
|
362
|
-
console.log(
|
|
361
|
+
console.log("[sweepOrdinals] === CREATE ACTION ARGS ===");
|
|
363
362
|
console.log(`[sweepOrdinals] description: ${createActionArgs.description}`);
|
|
364
363
|
console.log(`[sweepOrdinals] inputBEEF length: ${beefData.length} bytes`);
|
|
365
364
|
console.log(`[sweepOrdinals] inputs count: ${inputDescriptors.length}`);
|
|
366
365
|
console.log(`[sweepOrdinals] outputs count: ${outputs.length}`);
|
|
367
|
-
console.log(
|
|
368
|
-
console.log(
|
|
369
|
-
console.log(
|
|
370
|
-
console.log(
|
|
366
|
+
console.log("[sweepOrdinals] inputs:", JSON.stringify(inputDescriptors, null, 2));
|
|
367
|
+
console.log("[sweepOrdinals] outputs:", JSON.stringify(outputs, null, 2));
|
|
368
|
+
console.log("[sweepOrdinals] options:", JSON.stringify(createActionArgs.options));
|
|
369
|
+
console.log("[sweepOrdinals] Calling createAction...");
|
|
371
370
|
let createResult;
|
|
372
371
|
try {
|
|
373
372
|
createResult = await ctx.wallet.createAction(createActionArgs);
|
|
374
|
-
console.log(
|
|
373
|
+
console.log("[sweepOrdinals] createAction returned:", JSON.stringify(createResult, (key, value) => {
|
|
375
374
|
// Don't stringify large binary data
|
|
376
375
|
if (key === "tx" && value instanceof Uint8Array)
|
|
377
376
|
return `<Uint8Array ${value.length} bytes>`;
|
|
@@ -381,12 +380,12 @@ export const sweepOrdinals = {
|
|
|
381
380
|
}, 2));
|
|
382
381
|
}
|
|
383
382
|
catch (createError) {
|
|
384
|
-
console.error(
|
|
383
|
+
console.error("[sweepOrdinals] createAction threw:", createError);
|
|
385
384
|
const errorMsg = createError instanceof Error
|
|
386
385
|
? createError.message
|
|
387
386
|
: String(createError);
|
|
388
387
|
const errorStack = createError instanceof Error ? createError.stack : undefined;
|
|
389
|
-
console.error(
|
|
388
|
+
console.error("[sweepOrdinals] Stack:", errorStack);
|
|
390
389
|
return { error: `createAction failed: ${errorMsg}` };
|
|
391
390
|
}
|
|
392
391
|
if ("error" in createResult && createResult.error) {
|
|
@@ -398,7 +397,7 @@ export const sweepOrdinals = {
|
|
|
398
397
|
// Sign each input with our external key
|
|
399
398
|
const tx = Transaction.fromBEEF(createResult.signableTransaction.tx);
|
|
400
399
|
// Log transaction structure for debugging
|
|
401
|
-
console.log(
|
|
400
|
+
console.log("[sweepOrdinals] === Transaction Structure ===");
|
|
402
401
|
console.log(`[sweepOrdinals] Inputs (${tx.inputs.length}):`);
|
|
403
402
|
let totalInputSats = 0;
|
|
404
403
|
for (let i = 0; i < tx.inputs.length; i++) {
|
|
@@ -417,7 +416,7 @@ export const sweepOrdinals = {
|
|
|
417
416
|
}
|
|
418
417
|
console.log(`[sweepOrdinals] Total in: ${totalInputSats}, Total out: ${totalOutputSats}, Fee: ${totalInputSats - totalOutputSats}`);
|
|
419
418
|
console.log(`[sweepOrdinals] Signable tx hex: ${Utils.toHex(createResult.signableTransaction.tx)}`);
|
|
420
|
-
console.log(
|
|
419
|
+
console.log("[sweepOrdinals] ==============================");
|
|
421
420
|
// Build a set of outpoints we control
|
|
422
421
|
const ourOutpoints = new Set(inputs.map((input) => {
|
|
423
422
|
const [txid, vout] = input.outpoint.split("_");
|
|
@@ -435,12 +434,12 @@ export const sweepOrdinals = {
|
|
|
435
434
|
await tx.sign();
|
|
436
435
|
// Log signed transaction details for debugging
|
|
437
436
|
const localTxid = tx.id("hex");
|
|
438
|
-
console.log(
|
|
437
|
+
console.log("[sweepOrdinals] === LOCAL SIGNED TX ===");
|
|
439
438
|
console.log(`[sweepOrdinals] Local txid: ${localTxid}`);
|
|
440
439
|
console.log(`[sweepOrdinals] Signed tx hex: ${tx.toHex()}`);
|
|
441
440
|
// Extract unlocking scripts for signAction
|
|
442
441
|
const spends = {};
|
|
443
|
-
console.log(
|
|
442
|
+
console.log("[sweepOrdinals] === UNLOCKING SCRIPTS FOR SIGNACTION ===");
|
|
444
443
|
for (let i = 0; i < tx.inputs.length; i++) {
|
|
445
444
|
const txInput = tx.inputs[i];
|
|
446
445
|
const inputOutpoint = `${txInput.sourceTXID}.${txInput.sourceOutputIndex}`;
|
|
@@ -463,18 +462,18 @@ export const sweepOrdinals = {
|
|
|
463
462
|
return { error: String(signResult.error) };
|
|
464
463
|
}
|
|
465
464
|
// Debug: compare local vs signAction result
|
|
466
|
-
console.log(
|
|
465
|
+
console.log("[sweepOrdinals] === SIGN ACTION RESULT ===");
|
|
467
466
|
console.log(`[sweepOrdinals] signAction txid: ${signResult.txid}`);
|
|
468
467
|
// Log broadcast results if available
|
|
469
468
|
if ("sendWithResults" in signResult) {
|
|
470
|
-
console.log(
|
|
469
|
+
console.log("[sweepOrdinals] sendWithResults:", JSON.stringify(signResult.sendWithResults));
|
|
471
470
|
}
|
|
472
471
|
console.log(`[sweepOrdinals] Local txid (partial): ${localTxid}`);
|
|
473
|
-
console.log(
|
|
472
|
+
console.log("[sweepOrdinals] Note: TXIDs differ because local is partial (wallet input unsigned)");
|
|
474
473
|
if (signResult.tx) {
|
|
475
474
|
// Parse returned BEEF to show final transaction structure
|
|
476
475
|
const returnedTx = Transaction.fromBEEF(signResult.tx);
|
|
477
|
-
console.log(
|
|
476
|
+
console.log("[sweepOrdinals] === FINAL TX STRUCTURE (broadcast) ===");
|
|
478
477
|
console.log(`[sweepOrdinals] Final inputs (${returnedTx.inputs.length}):`);
|
|
479
478
|
let returnedInputSats = 0;
|
|
480
479
|
for (let i = 0; i < returnedTx.inputs.length; i++) {
|
|
@@ -501,7 +500,7 @@ export const sweepOrdinals = {
|
|
|
501
500
|
const satPerByte = finalFee / txSize;
|
|
502
501
|
console.log(`[sweepOrdinals] Tx size: ${txSize} bytes, Fee rate: ${satPerByte.toFixed(2)} sat/byte`);
|
|
503
502
|
if (satPerByte < 0.5) {
|
|
504
|
-
console.warn(
|
|
503
|
+
console.warn("[sweepOrdinals] WARNING: Fee rate seems very low!");
|
|
505
504
|
}
|
|
506
505
|
}
|
|
507
506
|
return {
|
|
@@ -583,6 +582,12 @@ export const sweepBsv21 = {
|
|
|
583
582
|
if (!inputs.every((i) => i.tokenId === tokenId)) {
|
|
584
583
|
return { error: "mixed-token-ids" };
|
|
585
584
|
}
|
|
585
|
+
// Lookup token details to verify it's active and get fee info
|
|
586
|
+
const tokenDetails = await ctx.services.bsv21.getTokenDetails(tokenId);
|
|
587
|
+
if (!tokenDetails.status.is_active) {
|
|
588
|
+
return { error: "token-not-active" };
|
|
589
|
+
}
|
|
590
|
+
const { fee_address, fee_per_output } = tokenDetails.status;
|
|
586
591
|
// Parse WIF
|
|
587
592
|
const privateKey = PrivateKey.fromWif(wif);
|
|
588
593
|
// Sum all input amounts
|
|
@@ -636,11 +641,10 @@ export const sweepBsv21 = {
|
|
|
636
641
|
keyID,
|
|
637
642
|
}),
|
|
638
643
|
});
|
|
639
|
-
// 2. Fee output
|
|
640
|
-
const fundAddress = deriveFundAddress(tokenId);
|
|
644
|
+
// 2. Fee output to overlay fund address
|
|
641
645
|
outputs.push({
|
|
642
|
-
lockingScript: p2pkh.lock(
|
|
643
|
-
satoshis:
|
|
646
|
+
lockingScript: p2pkh.lock(fee_address).toHex(),
|
|
647
|
+
satoshis: fee_per_output,
|
|
644
648
|
outputDescription: "Overlay processing fee",
|
|
645
649
|
tags: [],
|
|
646
650
|
});
|
|
@@ -698,13 +702,12 @@ export const sweepBsv21 = {
|
|
|
698
702
|
// Submit to overlay service for indexing
|
|
699
703
|
if (signResult.tx) {
|
|
700
704
|
try {
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
console.log(`[sweepBsv21] Overlay submission result:`, overlayResult);
|
|
705
|
+
const overlayResult = await ctx.services.overlay.submitBsv21(signResult.tx, tokenId);
|
|
706
|
+
console.log("[sweepBsv21] Overlay submission result:", overlayResult);
|
|
704
707
|
}
|
|
705
708
|
catch (overlayError) {
|
|
706
709
|
// Log but don't fail the sweep - tx is already broadcast
|
|
707
|
-
console.warn(
|
|
710
|
+
console.warn("[sweepBsv21] Overlay submission failed:", overlayError);
|
|
708
711
|
}
|
|
709
712
|
}
|
|
710
713
|
return {
|
package/dist/api/tokens/index.js
CHANGED
|
@@ -252,9 +252,12 @@ export const sendBsv21 = {
|
|
|
252
252
|
else if (paymail) {
|
|
253
253
|
return { error: "paymail-not-yet-implemented" };
|
|
254
254
|
}
|
|
255
|
-
else {
|
|
255
|
+
else if (address) {
|
|
256
256
|
recipientAddress = address;
|
|
257
257
|
}
|
|
258
|
+
else {
|
|
259
|
+
return { error: "must-provide-counterparty-or-address" };
|
|
260
|
+
}
|
|
258
261
|
const outputs = [];
|
|
259
262
|
const p2pkh = new P2PKH();
|
|
260
263
|
const destinationLockingScript = p2pkh.lock(recipientAddress);
|
|
@@ -324,12 +327,11 @@ export const sendBsv21 = {
|
|
|
324
327
|
// Submit to overlay service for indexing
|
|
325
328
|
if (signResult.tx && ctx.services) {
|
|
326
329
|
try {
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
console.log(`[sendBsv21] Overlay submission result:`, overlayResult);
|
|
330
|
+
const overlayResult = await ctx.services.overlay.submitBsv21(signResult.tx, tokenId);
|
|
331
|
+
console.log("[sendBsv21] Overlay submission result:", overlayResult);
|
|
330
332
|
}
|
|
331
333
|
catch (overlayError) {
|
|
332
|
-
console.warn(
|
|
334
|
+
console.warn("[sendBsv21] Overlay submission failed:", overlayError);
|
|
333
335
|
}
|
|
334
336
|
}
|
|
335
337
|
return {
|
|
@@ -488,12 +490,11 @@ export const purchaseBsv21 = {
|
|
|
488
490
|
// Submit to overlay service for indexing
|
|
489
491
|
if (signResult.tx && ctx.services) {
|
|
490
492
|
try {
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
console.log(`[purchaseBsv21] Overlay submission result:`, overlayResult);
|
|
493
|
+
const overlayResult = await ctx.services.overlay.submitBsv21(signResult.tx, tokenId);
|
|
494
|
+
console.log("[purchaseBsv21] Overlay submission result:", overlayResult);
|
|
494
495
|
}
|
|
495
496
|
catch (overlayError) {
|
|
496
|
-
console.warn(
|
|
497
|
+
console.warn("[purchaseBsv21] Overlay submission failed:", overlayError);
|
|
497
498
|
}
|
|
498
499
|
}
|
|
499
500
|
return {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./api";
|
|
2
2
|
export { OneSatServices, type SyncOutput } from "./services/OneSatServices";
|
|
3
|
-
export type { IndexedOutput, OrdfsMetadata, OrdfsContentOptions, OrdfsContentResponse, OrdfsResponseHeaders, Capability, } from "./services/types";
|
|
3
|
+
export type { IndexedOutput, OrdfsMetadata, OrdfsContentOptions, OrdfsContentResponse, OrdfsResponseHeaders, Capability, TokenDetailResponse, TokenStatus, Bsv21TokenData, Bsv21OutputData, Bsv21TransactionData, } from "./services/types";
|
|
4
4
|
export * from "./services/client";
|
|
5
5
|
export { ReadOnlySigner } from "./signers/ReadOnlySigner";
|
|
6
6
|
export * from "./indexers";
|
|
@@ -56,9 +56,9 @@ export class Bsv21Indexer extends Indexer {
|
|
|
56
56
|
if (!isDeploy) {
|
|
57
57
|
try {
|
|
58
58
|
const details = await this.services.bsv21.getTokenDetails(tokenId);
|
|
59
|
-
bsv21.sym = details.sym;
|
|
60
|
-
bsv21.icon = resolveIcon(details.icon, tokenId);
|
|
61
|
-
bsv21.dec = details.dec;
|
|
59
|
+
bsv21.sym = details.token.sym;
|
|
60
|
+
bsv21.icon = resolveIcon(details.token.icon, tokenId);
|
|
61
|
+
bsv21.dec = Number(details.token.dec) || 0;
|
|
62
62
|
}
|
|
63
63
|
catch (e) {
|
|
64
64
|
// Token not found on server - could be unconfirmed or invalid
|
package/dist/indexers/types.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface Bsv21TokenData {
|
|
|
8
8
|
op: string;
|
|
9
9
|
amt: string;
|
|
10
10
|
sym?: string;
|
|
11
|
-
dec?:
|
|
11
|
+
dec?: string;
|
|
12
12
|
icon?: string;
|
|
13
13
|
address?: string;
|
|
14
14
|
}
|
|
@@ -16,15 +16,13 @@ export interface Bsv21TokenData {
|
|
|
16
16
|
* BSV21 output data from overlay API
|
|
17
17
|
*/
|
|
18
18
|
export interface Bsv21OutputData {
|
|
19
|
-
txid
|
|
19
|
+
txid?: string;
|
|
20
20
|
vout: number;
|
|
21
21
|
data: {
|
|
22
22
|
bsv21: Bsv21TokenData;
|
|
23
23
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
spend: string | null;
|
|
27
|
-
score: number;
|
|
24
|
+
spend?: string | null;
|
|
25
|
+
score?: number;
|
|
28
26
|
}
|
|
29
27
|
/**
|
|
30
28
|
* BSV21 transaction data from overlay API
|
|
@@ -34,6 +32,7 @@ export interface Bsv21TransactionData {
|
|
|
34
32
|
inputs: Bsv21OutputData[];
|
|
35
33
|
outputs: Bsv21OutputData[];
|
|
36
34
|
beef?: string;
|
|
35
|
+
block_height?: number;
|
|
37
36
|
}
|
|
38
37
|
/**
|
|
39
38
|
* IndexData contains the parsed data and tags from an indexer
|
|
@@ -139,7 +139,7 @@ export class OneSatServices {
|
|
|
139
139
|
}
|
|
140
140
|
async postBeef(beef, txids) {
|
|
141
141
|
console.log("[OneSatServices] postBeef called with txids:", txids);
|
|
142
|
-
console.log(
|
|
142
|
+
console.log(`[OneSatServices] BEEF structure:\n${beef.toLogString()}`);
|
|
143
143
|
const results = [];
|
|
144
144
|
for (const txid of txids) {
|
|
145
145
|
try {
|
|
@@ -149,7 +149,7 @@ export class OneSatServices {
|
|
|
149
149
|
console.log("[OneSatServices] AtomicBEEF length:", atomicBeef.length, "bytes");
|
|
150
150
|
// Parse back to verify structure
|
|
151
151
|
const verifyBeef = Beef.fromBinary(atomicBeef);
|
|
152
|
-
console.log(
|
|
152
|
+
console.log(`[OneSatServices] AtomicBEEF parsed back:\n${verifyBeef.toLogString()}`);
|
|
153
153
|
// TODO: Remove hardcoded callback headers after server testing
|
|
154
154
|
const status = await this.arcade.submitTransaction(atomicBeef, {
|
|
155
155
|
callbackUrl: `${this.baseUrl}/1sat/arc/callback`,
|
|
@@ -292,10 +292,8 @@ export class OneSatServices {
|
|
|
292
292
|
const depth = currentHeight - tx.merklePath.blockHeight + 1;
|
|
293
293
|
return { txid, status: "mined", depth };
|
|
294
294
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return { txid, status: "known", depth: 0 };
|
|
298
|
-
}
|
|
295
|
+
// No merkle path = known but not yet mined
|
|
296
|
+
return { txid, status: "known", depth: 0 };
|
|
299
297
|
}
|
|
300
298
|
catch {
|
|
301
299
|
// 404 or error from Beef = unknown
|
|
@@ -1,36 +1,45 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Bsv21TransactionData, ClientOptions, IndexedOutput, TokenDetailResponse } from "../types";
|
|
2
2
|
import { BaseClient } from "./BaseClient";
|
|
3
3
|
/**
|
|
4
4
|
* Client for /1sat/bsv21/* routes.
|
|
5
5
|
* Provides BSV21 token queries.
|
|
6
6
|
*
|
|
7
7
|
* Routes:
|
|
8
|
-
* -
|
|
9
|
-
* - GET /:tokenId
|
|
10
|
-
* - GET /:tokenId/tx/:txid - Get token data
|
|
8
|
+
* - POST /lookup - Bulk lookup token details with funding status
|
|
9
|
+
* - GET /:tokenId - Get token details with funding status
|
|
10
|
+
* - GET /:tokenId/tx/:txid - Get token transaction data
|
|
11
11
|
* - GET /:tokenId/:lockType/:address/balance - Get token balance
|
|
12
12
|
* - GET /:tokenId/:lockType/:address/unspent - Get unspent token UTXOs
|
|
13
13
|
* - GET /:tokenId/:lockType/:address/history - Get token transaction history
|
|
14
|
+
* - POST /:tokenId/:lockType/balance - Multi-address token balance
|
|
15
|
+
* - POST /:tokenId/:lockType/unspent - Multi-address unspent token UTXOs
|
|
16
|
+
* - POST /:tokenId/:lockType/history - Multi-address token transaction history
|
|
14
17
|
*/
|
|
15
18
|
export declare class Bsv21Client extends BaseClient {
|
|
16
19
|
private cache;
|
|
17
20
|
constructor(baseUrl: string, options?: ClientOptions);
|
|
18
21
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
22
|
+
* Bulk lookup token details with funding status.
|
|
23
|
+
* Returns details and active status for multiple tokens in one request.
|
|
24
|
+
* @param tokenIds - Array of token IDs (max 100)
|
|
21
25
|
*/
|
|
22
|
-
|
|
26
|
+
lookupTokens(tokenIds: string[]): Promise<TokenDetailResponse[]>;
|
|
27
|
+
/**
|
|
28
|
+
* Get token details with funding status.
|
|
29
|
+
* Results are cached since token deploy data is immutable.
|
|
30
|
+
*/
|
|
31
|
+
getTokenDetails(tokenId: string): Promise<TokenDetailResponse>;
|
|
23
32
|
/**
|
|
24
33
|
* Get token transaction data for a specific txid
|
|
25
34
|
*/
|
|
26
35
|
getTokenByTxid(tokenId: string, txid: string): Promise<Bsv21TransactionData>;
|
|
27
36
|
/**
|
|
28
37
|
* Get token balance for an address
|
|
29
|
-
* @param tokenId - Token ID (outpoint of deploy tx)
|
|
30
|
-
* @param lockType - Lock type (e.g., 'p2pkh', 'ordlock')
|
|
31
|
-
* @param address - Address to check
|
|
32
38
|
*/
|
|
33
|
-
getBalance(tokenId: string, lockType: string, address: string): Promise<
|
|
39
|
+
getBalance(tokenId: string, lockType: string, address: string): Promise<{
|
|
40
|
+
balance: number;
|
|
41
|
+
utxoCount: number;
|
|
42
|
+
}>;
|
|
34
43
|
/**
|
|
35
44
|
* Get unspent token UTXOs for an address
|
|
36
45
|
*/
|
|
@@ -39,6 +48,24 @@ export declare class Bsv21Client extends BaseClient {
|
|
|
39
48
|
* Get token transaction history for an address
|
|
40
49
|
*/
|
|
41
50
|
getHistory(tokenId: string, lockType: string, address: string): Promise<IndexedOutput[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Get token balance for multiple addresses
|
|
53
|
+
* @param addresses - Array of addresses (max 100)
|
|
54
|
+
*/
|
|
55
|
+
getBalanceMulti(tokenId: string, lockType: string, addresses: string[]): Promise<{
|
|
56
|
+
balance: number;
|
|
57
|
+
utxoCount: number;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Get unspent token UTXOs for multiple addresses
|
|
61
|
+
* @param addresses - Array of addresses (max 100)
|
|
62
|
+
*/
|
|
63
|
+
getUnspentMulti(tokenId: string, lockType: string, addresses: string[]): Promise<IndexedOutput[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Get token transaction history for multiple addresses
|
|
66
|
+
* @param addresses - Array of addresses (max 100)
|
|
67
|
+
*/
|
|
68
|
+
getHistoryMulti(tokenId: string, lockType: string, addresses: string[]): Promise<IndexedOutput[]>;
|
|
42
69
|
/**
|
|
43
70
|
* Clear the token details cache
|
|
44
71
|
*/
|
|
@@ -4,12 +4,15 @@ import { BaseClient } from "./BaseClient";
|
|
|
4
4
|
* Provides BSV21 token queries.
|
|
5
5
|
*
|
|
6
6
|
* Routes:
|
|
7
|
-
* -
|
|
8
|
-
* - GET /:tokenId
|
|
9
|
-
* - GET /:tokenId/tx/:txid - Get token data
|
|
7
|
+
* - POST /lookup - Bulk lookup token details with funding status
|
|
8
|
+
* - GET /:tokenId - Get token details with funding status
|
|
9
|
+
* - GET /:tokenId/tx/:txid - Get token transaction data
|
|
10
10
|
* - GET /:tokenId/:lockType/:address/balance - Get token balance
|
|
11
11
|
* - GET /:tokenId/:lockType/:address/unspent - Get unspent token UTXOs
|
|
12
12
|
* - GET /:tokenId/:lockType/:address/history - Get token transaction history
|
|
13
|
+
* - POST /:tokenId/:lockType/balance - Multi-address token balance
|
|
14
|
+
* - POST /:tokenId/:lockType/unspent - Multi-address unspent token UTXOs
|
|
15
|
+
* - POST /:tokenId/:lockType/history - Multi-address token transaction history
|
|
13
16
|
*/
|
|
14
17
|
export class Bsv21Client extends BaseClient {
|
|
15
18
|
cache = new Map();
|
|
@@ -17,8 +20,20 @@ export class Bsv21Client extends BaseClient {
|
|
|
17
20
|
super(`${baseUrl}/1sat/bsv21`, options);
|
|
18
21
|
}
|
|
19
22
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
23
|
+
* Bulk lookup token details with funding status.
|
|
24
|
+
* Returns details and active status for multiple tokens in one request.
|
|
25
|
+
* @param tokenIds - Array of token IDs (max 100)
|
|
26
|
+
*/
|
|
27
|
+
async lookupTokens(tokenIds) {
|
|
28
|
+
return this.request("/lookup", {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: { "Content-Type": "application/json" },
|
|
31
|
+
body: JSON.stringify(tokenIds),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get token details with funding status.
|
|
36
|
+
* Results are cached since token deploy data is immutable.
|
|
22
37
|
*/
|
|
23
38
|
async getTokenDetails(tokenId) {
|
|
24
39
|
const cached = this.cache.get(tokenId);
|
|
@@ -36,13 +51,9 @@ export class Bsv21Client extends BaseClient {
|
|
|
36
51
|
}
|
|
37
52
|
/**
|
|
38
53
|
* Get token balance for an address
|
|
39
|
-
* @param tokenId - Token ID (outpoint of deploy tx)
|
|
40
|
-
* @param lockType - Lock type (e.g., 'p2pkh', 'ordlock')
|
|
41
|
-
* @param address - Address to check
|
|
42
54
|
*/
|
|
43
55
|
async getBalance(tokenId, lockType, address) {
|
|
44
|
-
|
|
45
|
-
return BigInt(data.balance);
|
|
56
|
+
return this.request(`/${tokenId}/${lockType}/${address}/balance`);
|
|
46
57
|
}
|
|
47
58
|
/**
|
|
48
59
|
* Get unspent token UTXOs for an address
|
|
@@ -56,6 +67,39 @@ export class Bsv21Client extends BaseClient {
|
|
|
56
67
|
async getHistory(tokenId, lockType, address) {
|
|
57
68
|
return this.request(`/${tokenId}/${lockType}/${address}/history`);
|
|
58
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Get token balance for multiple addresses
|
|
72
|
+
* @param addresses - Array of addresses (max 100)
|
|
73
|
+
*/
|
|
74
|
+
async getBalanceMulti(tokenId, lockType, addresses) {
|
|
75
|
+
return this.request(`/${tokenId}/${lockType}/balance`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: { "Content-Type": "application/json" },
|
|
78
|
+
body: JSON.stringify(addresses),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get unspent token UTXOs for multiple addresses
|
|
83
|
+
* @param addresses - Array of addresses (max 100)
|
|
84
|
+
*/
|
|
85
|
+
async getUnspentMulti(tokenId, lockType, addresses) {
|
|
86
|
+
return this.request(`/${tokenId}/${lockType}/unspent`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: { "Content-Type": "application/json" },
|
|
89
|
+
body: JSON.stringify(addresses),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get token transaction history for multiple addresses
|
|
94
|
+
* @param addresses - Array of addresses (max 100)
|
|
95
|
+
*/
|
|
96
|
+
async getHistoryMulti(tokenId, lockType, addresses) {
|
|
97
|
+
return this.request(`/${tokenId}/${lockType}/history`, {
|
|
98
|
+
method: "POST",
|
|
99
|
+
headers: { "Content-Type": "application/json" },
|
|
100
|
+
body: JSON.stringify(addresses),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
59
103
|
/**
|
|
60
104
|
* Clear the token details cache
|
|
61
105
|
*/
|
|
@@ -11,12 +11,6 @@ export interface TopicManagerInfo {
|
|
|
11
11
|
export interface LookupServiceInfo {
|
|
12
12
|
[key: string]: unknown;
|
|
13
13
|
}
|
|
14
|
-
/** BSV-21 token info extracted from topic managers */
|
|
15
|
-
export interface Bsv21TokenInfo {
|
|
16
|
-
tokenId: string;
|
|
17
|
-
symbol?: string;
|
|
18
|
-
icon?: string;
|
|
19
|
-
}
|
|
20
14
|
/**
|
|
21
15
|
* Client for overlay service routes.
|
|
22
16
|
* Handles topic manager queries and overlay lookups.
|
|
@@ -25,23 +19,12 @@ export declare class OverlayClient extends BaseClient {
|
|
|
25
19
|
constructor(baseUrl: string, options?: ClientOptions);
|
|
26
20
|
/**
|
|
27
21
|
* List all registered topic managers.
|
|
28
|
-
* BSV-21 tokens have topic managers named `tm_{tokenId}`.
|
|
29
22
|
*/
|
|
30
23
|
listTopicManagers(): Promise<Record<string, TopicManagerInfo>>;
|
|
31
24
|
/**
|
|
32
25
|
* List all registered lookup service providers.
|
|
33
26
|
*/
|
|
34
27
|
listLookupServiceProviders(): Promise<Record<string, LookupServiceInfo>>;
|
|
35
|
-
/**
|
|
36
|
-
* Get list of active BSV-21 token IDs from topic managers.
|
|
37
|
-
* Extracts tokenIds from topics matching the `tm_{tokenId}` pattern.
|
|
38
|
-
*/
|
|
39
|
-
getActiveBsv21TokenIds(): Promise<string[]>;
|
|
40
|
-
/**
|
|
41
|
-
* Get active BSV-21 tokens with metadata from topic managers.
|
|
42
|
-
* Returns tokenId, symbol (from name), and icon for each active token.
|
|
43
|
-
*/
|
|
44
|
-
getActiveBsv21Tokens(): Promise<Bsv21TokenInfo[]>;
|
|
45
28
|
/**
|
|
46
29
|
* Submit a transaction to the overlay service for indexing.
|
|
47
30
|
* @param beef - BEEF data as Uint8Array or number[]
|
|
@@ -9,7 +9,6 @@ export class OverlayClient extends BaseClient {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* List all registered topic managers.
|
|
12
|
-
* BSV-21 tokens have topic managers named `tm_{tokenId}`.
|
|
13
12
|
*/
|
|
14
13
|
async listTopicManagers() {
|
|
15
14
|
return this.request("/1sat/overlay/listTopicManagers");
|
|
@@ -20,38 +19,6 @@ export class OverlayClient extends BaseClient {
|
|
|
20
19
|
async listLookupServiceProviders() {
|
|
21
20
|
return this.request("/1sat/overlay/listLookupServiceProviders");
|
|
22
21
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Get list of active BSV-21 token IDs from topic managers.
|
|
25
|
-
* Extracts tokenIds from topics matching the `tm_{tokenId}` pattern.
|
|
26
|
-
*/
|
|
27
|
-
async getActiveBsv21TokenIds() {
|
|
28
|
-
const topicManagers = await this.listTopicManagers();
|
|
29
|
-
const tokenIds = [];
|
|
30
|
-
for (const topic of Object.keys(topicManagers)) {
|
|
31
|
-
if (topic.startsWith("tm_")) {
|
|
32
|
-
tokenIds.push(topic.slice(3));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return tokenIds;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get active BSV-21 tokens with metadata from topic managers.
|
|
39
|
-
* Returns tokenId, symbol (from name), and icon for each active token.
|
|
40
|
-
*/
|
|
41
|
-
async getActiveBsv21Tokens() {
|
|
42
|
-
const topicManagers = await this.listTopicManagers();
|
|
43
|
-
const tokens = [];
|
|
44
|
-
for (const [topic, info] of Object.entries(topicManagers)) {
|
|
45
|
-
if (topic.startsWith("tm_")) {
|
|
46
|
-
tokens.push({
|
|
47
|
-
tokenId: topic.slice(3),
|
|
48
|
-
symbol: info.name,
|
|
49
|
-
icon: info.icon,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return tokens;
|
|
54
|
-
}
|
|
55
22
|
/**
|
|
56
23
|
* Submit a transaction to the overlay service for indexing.
|
|
57
24
|
* @param beef - BEEF data as Uint8Array or number[]
|
package/dist/services/types.d.ts
CHANGED
|
@@ -195,19 +195,6 @@ export interface OrdfsContentResponse {
|
|
|
195
195
|
data: Uint8Array;
|
|
196
196
|
headers: OrdfsResponseHeaders;
|
|
197
197
|
}
|
|
198
|
-
/**
|
|
199
|
-
* BSV21 token details (deploy data)
|
|
200
|
-
*/
|
|
201
|
-
export interface Bsv21TokenDetails {
|
|
202
|
-
id: string;
|
|
203
|
-
txid: string;
|
|
204
|
-
vout: number;
|
|
205
|
-
op: string;
|
|
206
|
-
amt: string;
|
|
207
|
-
sym?: string;
|
|
208
|
-
dec: number;
|
|
209
|
-
icon?: string;
|
|
210
|
-
}
|
|
211
198
|
/**
|
|
212
199
|
* BSV21 token data structure from overlay API
|
|
213
200
|
*/
|
|
@@ -216,23 +203,44 @@ export interface Bsv21TokenData {
|
|
|
216
203
|
op: string;
|
|
217
204
|
amt: string;
|
|
218
205
|
sym?: string;
|
|
219
|
-
dec?:
|
|
206
|
+
dec?: string;
|
|
220
207
|
icon?: string;
|
|
221
208
|
address?: string;
|
|
222
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* BSV21 token detail response from GET /bsv21/:tokenId and POST /bsv21/lookup
|
|
212
|
+
*/
|
|
213
|
+
export interface TokenDetailResponse {
|
|
214
|
+
tokenId: string;
|
|
215
|
+
token: Bsv21TokenData;
|
|
216
|
+
status: TokenStatus;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* BSV21 token funding/activity status
|
|
220
|
+
*/
|
|
221
|
+
export interface TokenStatus {
|
|
222
|
+
token_id: string;
|
|
223
|
+
is_active: boolean;
|
|
224
|
+
balance: number;
|
|
225
|
+
credits: number;
|
|
226
|
+
debits: number;
|
|
227
|
+
output_count: number;
|
|
228
|
+
fee_per_output: number;
|
|
229
|
+
fee_address: string;
|
|
230
|
+
is_whitelisted: boolean;
|
|
231
|
+
is_blacklisted: boolean;
|
|
232
|
+
}
|
|
223
233
|
/**
|
|
224
234
|
* BSV21 output data from overlay API
|
|
225
235
|
*/
|
|
226
236
|
export interface Bsv21OutputData {
|
|
227
|
-
txid
|
|
237
|
+
txid?: string;
|
|
228
238
|
vout: number;
|
|
229
239
|
data: {
|
|
230
240
|
bsv21: Bsv21TokenData;
|
|
231
241
|
};
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
spend: string | null;
|
|
235
|
-
score: number;
|
|
242
|
+
spend?: string | null;
|
|
243
|
+
score?: number;
|
|
236
244
|
}
|
|
237
245
|
/**
|
|
238
246
|
* BSV21 transaction data from overlay API
|
|
@@ -242,6 +250,7 @@ export interface Bsv21TransactionData {
|
|
|
242
250
|
inputs: Bsv21OutputData[];
|
|
243
251
|
outputs: Bsv21OutputData[];
|
|
244
252
|
beef?: string;
|
|
253
|
+
block_height?: number;
|
|
245
254
|
}
|
|
246
255
|
/**
|
|
247
256
|
* Event from SSE subscription
|
|
@@ -81,13 +81,13 @@ export interface SyncProcessorOptions {
|
|
|
81
81
|
indexers?: Indexer[];
|
|
82
82
|
}
|
|
83
83
|
export interface SyncProcessorEvents {
|
|
84
|
-
"process:start":
|
|
84
|
+
"process:start": Record<string, never>;
|
|
85
85
|
"process:progress": {
|
|
86
86
|
pending: number;
|
|
87
87
|
done: number;
|
|
88
88
|
failed: number;
|
|
89
89
|
};
|
|
90
|
-
"process:complete":
|
|
90
|
+
"process:complete": Record<string, never>;
|
|
91
91
|
"process:error": {
|
|
92
92
|
message: string;
|
|
93
93
|
};
|
|
@@ -161,7 +161,7 @@ export interface SyncEvents {
|
|
|
161
161
|
done: number;
|
|
162
162
|
failed: number;
|
|
163
163
|
};
|
|
164
|
-
"sync:complete":
|
|
164
|
+
"sync:complete": Record<string, never>;
|
|
165
165
|
"sync:error": {
|
|
166
166
|
message: string;
|
|
167
167
|
};
|
package/dist/sync/SyncManager.js
CHANGED
|
@@ -44,7 +44,7 @@ export class SyncFetcher {
|
|
|
44
44
|
}
|
|
45
45
|
this.listeners
|
|
46
46
|
.get(event)
|
|
47
|
-
|
|
47
|
+
?.add(listener);
|
|
48
48
|
}
|
|
49
49
|
off(event, listener) {
|
|
50
50
|
this.listeners
|
|
@@ -52,7 +52,9 @@ export class SyncFetcher {
|
|
|
52
52
|
?.delete(listener);
|
|
53
53
|
}
|
|
54
54
|
emit(event, data) {
|
|
55
|
-
this.listeners.get(event)
|
|
55
|
+
for (const listener of this.listeners.get(event) ?? []) {
|
|
56
|
+
listener(data);
|
|
57
|
+
}
|
|
56
58
|
}
|
|
57
59
|
/**
|
|
58
60
|
* Fetch new outputs via SSE and enqueue them.
|
|
@@ -161,7 +163,7 @@ export class SyncProcessor {
|
|
|
161
163
|
}
|
|
162
164
|
this.listeners
|
|
163
165
|
.get(event)
|
|
164
|
-
|
|
166
|
+
?.add(listener);
|
|
165
167
|
}
|
|
166
168
|
off(event, listener) {
|
|
167
169
|
this.listeners
|
|
@@ -169,7 +171,9 @@ export class SyncProcessor {
|
|
|
169
171
|
?.delete(listener);
|
|
170
172
|
}
|
|
171
173
|
emit(event, data) {
|
|
172
|
-
this.listeners.get(event)
|
|
174
|
+
for (const listener of this.listeners.get(event) ?? []) {
|
|
175
|
+
listener(data);
|
|
176
|
+
}
|
|
173
177
|
}
|
|
174
178
|
/**
|
|
175
179
|
* Start processing the queue.
|
|
@@ -379,18 +383,16 @@ export class SyncProcessor {
|
|
|
379
383
|
},
|
|
380
384
|
};
|
|
381
385
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
};
|
|
393
|
-
}
|
|
386
|
+
// P2PKH-based output - use wallet payment for auto-signing
|
|
387
|
+
return {
|
|
388
|
+
outputIndex: vout,
|
|
389
|
+
protocol: "wallet payment",
|
|
390
|
+
paymentRemittance: {
|
|
391
|
+
derivationPrefix: derivation.derivationPrefix,
|
|
392
|
+
derivationSuffix: derivation.derivationSuffix,
|
|
393
|
+
senderIdentityKey: derivation.senderIdentityKey,
|
|
394
|
+
},
|
|
395
|
+
};
|
|
394
396
|
}
|
|
395
397
|
collectTags(txo) {
|
|
396
398
|
const tags = [];
|
|
@@ -467,7 +469,7 @@ export class SyncManager {
|
|
|
467
469
|
}
|
|
468
470
|
this.listeners
|
|
469
471
|
.get(event)
|
|
470
|
-
|
|
472
|
+
?.add(listener);
|
|
471
473
|
}
|
|
472
474
|
off(event, listener) {
|
|
473
475
|
this.listeners
|
|
@@ -475,7 +477,9 @@ export class SyncManager {
|
|
|
475
477
|
?.delete(listener);
|
|
476
478
|
}
|
|
477
479
|
emit(event, data) {
|
|
478
|
-
this.listeners.get(event)
|
|
480
|
+
for (const listener of this.listeners.get(event) ?? []) {
|
|
481
|
+
listener(data);
|
|
482
|
+
}
|
|
479
483
|
}
|
|
480
484
|
// ===== Sync Control =====
|
|
481
485
|
/**
|
package/dist/wallet/factory.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function createWebWallet(config) {
|
|
|
73
73
|
const localStorage = new StorageIdb(storageOptions);
|
|
74
74
|
await localStorage.migrate(DEFAULT_DATABASE_NAME, config.storageIdentityKey);
|
|
75
75
|
// 4. Create storage manager with local-only storage initially (empty backups)
|
|
76
|
-
|
|
76
|
+
const storage = new WalletStorageManager(identityPubKey, localStorage, []);
|
|
77
77
|
await storage.makeAvailable();
|
|
78
78
|
// 5. Create the underlying Wallet FIRST (needed for StorageClient signing)
|
|
79
79
|
const underlyingWallet = new Wallet({
|
|
@@ -175,7 +175,7 @@ export async function createWebWallet(config) {
|
|
|
175
175
|
unprovenAttemptsLimitMain: 144,
|
|
176
176
|
});
|
|
177
177
|
monitor.addDefaultTasks();
|
|
178
|
-
console.log("[createWebWallet] Monitor created with tasks:", monitor
|
|
178
|
+
console.log("[createWebWallet] Monitor created with tasks:", monitor._tasks.map((t) => t.name));
|
|
179
179
|
// 11. Wire up monitor callbacks - sync to remote first, then call user callbacks
|
|
180
180
|
// Note: For delayed broadcasts, the monitor triggers these. For immediate broadcasts,
|
|
181
181
|
// the interception in step 8 handles the sync, but these still fire for the user callback.
|