@1sat/sweep-ui 0.0.92 → 0.0.94
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/components/SweepApp.d.ts.map +1 -1
- package/dist/components/asset-preview.d.ts +5 -0
- package/dist/components/asset-preview.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +150 -21
- package/dist/lib/scanner.d.ts +1 -0
- package/dist/lib/scanner.d.ts.map +1 -1
- package/dist/lib/sweeper.d.ts +5 -0
- package/dist/lib/sweeper.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/components/SweepApp.tsx +50 -2
- package/src/components/asset-preview.tsx +36 -0
- package/src/index.ts +1 -0
- package/src/lib/scanner.ts +2 -0
- package/src/lib/sweeper.ts +61 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SweepApp.d.ts","sourceRoot":"","sources":["../../src/components/SweepApp.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAgB3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"SweepApp.d.ts","sourceRoot":"","sources":["../../src/components/SweepApp.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAgB3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAmB1C,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,wBAAgB,QAAQ,CAAC,EACxB,UAAU,EAAE,WAAW,EACvB,MAAM,EAAE,cAAc,EACtB,SAAS,GACT,EAAE,aAAa,+BAonBf"}
|
|
@@ -29,6 +29,11 @@ export declare function Bsv21Section({ tokens, onSweep, walletConnected, }: {
|
|
|
29
29
|
export declare function Bsv20Section({ tokens }: {
|
|
30
30
|
tokens: IndexedOutput[];
|
|
31
31
|
}): import("react").JSX.Element | null;
|
|
32
|
+
export declare function ListingsSection({ listings, walletConnected, onCancel, }: {
|
|
33
|
+
listings: EnrichedOrdinal[];
|
|
34
|
+
walletConnected?: boolean;
|
|
35
|
+
onCancel?: () => void;
|
|
36
|
+
}): import("react").JSX.Element | null;
|
|
32
37
|
export declare function LockedSection({ locked }: {
|
|
33
38
|
locked: IndexedOutput[];
|
|
34
39
|
}): import("react").JSX.Element | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset-preview.d.ts","sourceRoot":"","sources":["../../src/components/asset-preview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAuFnE,wBAAgB,cAAc,CAAC,EAC9B,OAAO,EACP,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,OAAO,EACP,MAAM,EACN,eAAe,GACf,EAAE;IACF,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACpD,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,eAAe,EAAE,OAAO,CAAA;CACxB,sCA0FA;AAED,wBAAgB,eAAe,CAAC,EAC/B,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,eAAe,GACf,EAAE;IACF,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IAC3C,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,eAAe,EAAE,OAAO,CAAA;CACxB,sCAgKA;AAgED,wBAAgB,YAAY,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,eAAe,GACf,EAAE;IACF,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,eAAe,EAAE,OAAO,CAAA;CACxB,sCAuCA;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,sCAkCnE;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,sCAgBpE;AAED,wBAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,aAAa,EAAE,CAAA;CAAE,sCAkB3D"}
|
|
1
|
+
{"version":3,"file":"asset-preview.d.ts","sourceRoot":"","sources":["../../src/components/asset-preview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAuFnE,wBAAgB,cAAc,CAAC,EAC9B,OAAO,EACP,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,OAAO,EACP,MAAM,EACN,eAAe,GACf,EAAE;IACF,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACpD,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,eAAe,EAAE,OAAO,CAAA;CACxB,sCA0FA;AAED,wBAAgB,eAAe,CAAC,EAC/B,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,eAAe,GACf,EAAE;IACF,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IAC3C,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,eAAe,EAAE,OAAO,CAAA;CACxB,sCAgKA;AAgED,wBAAgB,YAAY,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,eAAe,GACf,EAAE;IACF,MAAM,EAAE,YAAY,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,eAAe,EAAE,OAAO,CAAA;CACxB,sCAuCA;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,sCAkCnE;AAED,wBAAgB,eAAe,CAAC,EAC/B,QAAQ,EACR,eAAe,EACf,QAAQ,GACR,EAAE;IACF,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,sCA0BA;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,sCAgBpE;AAED,wBAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,aAAa,EAAE,CAAA;CAAE,sCAkB3D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { SweepApp, type SweepAppProps } from './components/SweepApp';
|
|
2
2
|
export { ConnectWallet } from './components/connect-wallet';
|
|
3
3
|
export { WifInput } from './components/wif-input';
|
|
4
|
-
export { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, LockedSection, RunSection, } from './components/asset-preview';
|
|
4
|
+
export { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, ListingsSection, LockedSection, RunSection, } from './components/asset-preview';
|
|
5
5
|
export { OpnsSection } from './components/opns-section';
|
|
6
6
|
export { TxHistory, type TxRecord } from './components/tx-history';
|
|
7
7
|
export { SweepProgress } from './components/sweep-progress';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAGpE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EACN,cAAc,EACd,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,UAAU,GACV,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EACN,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACX,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAG/E,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EACN,aAAa,EACb,SAAS,EACT,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,GACX,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,aAAa,EACb,WAAW,EACX,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,YAAY,EACZ,gBAAgB,EAChB,KAAK,WAAW,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,gBAAgB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGzE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAGpE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACjD,OAAO,EACN,cAAc,EACd,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,UAAU,GACV,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,EACN,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACX,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAG/E,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EACN,aAAa,EACb,SAAS,EACT,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,GACX,MAAM,cAAc,CAAA;AACrB,OAAO,EACN,aAAa,EACb,WAAW,EACX,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,YAAY,EACZ,gBAAgB,EAChB,KAAK,WAAW,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,gBAAgB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGzE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -84,6 +84,7 @@ function toScannedAssets(result) {
|
|
|
84
84
|
funding: result.funding,
|
|
85
85
|
ordinals: result.ordinals.map(enrichOrdinal),
|
|
86
86
|
opnsNames: result.opnsNames.map(enrichOrdinal),
|
|
87
|
+
listings: result.listings.map(enrichOrdinal),
|
|
87
88
|
bsv21Tokens: enrichTokenBalances(result.bsv21Tokens),
|
|
88
89
|
bsv20Tokens: result.bsv20Tokens,
|
|
89
90
|
locked: result.locked,
|
|
@@ -285,12 +286,13 @@ var SWEEP_BATCH_SIZE = 25;
|
|
|
285
286
|
function getOwner(output) {
|
|
286
287
|
return output.events?.find((e) => e.startsWith("own:"))?.slice(4);
|
|
287
288
|
}
|
|
288
|
-
function buildKeys(outputs, keyMap) {
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
function buildKeys(outputs, keyMap, inputs = outputs) {
|
|
290
|
+
const owners = new Map(outputs.map((output) => [output.outpoint, getOwner(output)]));
|
|
291
|
+
return inputs.map(({ outpoint }) => {
|
|
292
|
+
const owner = owners.get(outpoint);
|
|
291
293
|
const key = owner ? keyMap.get(owner) : undefined;
|
|
292
294
|
if (!key)
|
|
293
|
-
throw new Error(`No key for output ${
|
|
295
|
+
throw new Error(`No key for output ${outpoint} (owner: ${owner})`);
|
|
294
296
|
return key;
|
|
295
297
|
});
|
|
296
298
|
}
|
|
@@ -302,27 +304,64 @@ function chunk(items, size) {
|
|
|
302
304
|
return batches;
|
|
303
305
|
}
|
|
304
306
|
async function executeSweep(params) {
|
|
305
|
-
const {
|
|
307
|
+
const {
|
|
308
|
+
wallet,
|
|
309
|
+
keys,
|
|
310
|
+
funding,
|
|
311
|
+
ordinals,
|
|
312
|
+
listings = [],
|
|
313
|
+
amount,
|
|
314
|
+
onProgress
|
|
315
|
+
} = params;
|
|
306
316
|
const ctx = createContext(wallet, { services: getServices(), chain: "main" });
|
|
307
317
|
const result = {
|
|
308
318
|
ordinalTxids: [],
|
|
319
|
+
listingTxids: [],
|
|
309
320
|
bsv21Txids: [],
|
|
310
321
|
errors: [],
|
|
311
|
-
sweptOutpoints: []
|
|
322
|
+
sweptOutpoints: [],
|
|
323
|
+
cancelledListings: []
|
|
312
324
|
};
|
|
325
|
+
if (listings.length > 0) {
|
|
326
|
+
const batches = chunk(listings, SWEEP_BATCH_SIZE);
|
|
327
|
+
for (let b = 0;b < batches.length; b++) {
|
|
328
|
+
const batch = batches[b];
|
|
329
|
+
onProgress(`Cancelling ${batch.length} OrdLock listing${batch.length !== 1 ? "s" : ""} into wallet...`);
|
|
330
|
+
try {
|
|
331
|
+
const inputs = await prepareSweepInputs(ctx, batch);
|
|
332
|
+
const cancelResult = await sweepOrdinals.execute(ctx, {
|
|
333
|
+
inputs,
|
|
334
|
+
keys: buildKeys(batch, keys, inputs)
|
|
335
|
+
});
|
|
336
|
+
if (cancelResult.error)
|
|
337
|
+
throw new Error(cancelResult.error);
|
|
338
|
+
const txid = cancelResult.txid?.trim();
|
|
339
|
+
if (!txid)
|
|
340
|
+
throw new Error("Cancellation returned no transaction ID");
|
|
341
|
+
result.listingTxids.push(txid);
|
|
342
|
+
result.cancelledListings.push(...batch.map((o) => o.outpoint));
|
|
343
|
+
} catch (e) {
|
|
344
|
+
result.errors.push(`Listings batch ${b + 1}: ${e instanceof Error ? e.message : String(e)}`);
|
|
345
|
+
onProgress("Sweep stopped with errors");
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
313
350
|
if (funding.length > 0) {
|
|
314
351
|
onProgress(`Sweeping ${funding.length} BSV UTXOs...`);
|
|
315
352
|
try {
|
|
316
353
|
const inputs = await prepareSweepInputs(ctx, funding);
|
|
317
354
|
const bsvResult = await sweepBsv.execute(ctx, {
|
|
318
355
|
inputs,
|
|
319
|
-
keys: buildKeys(funding, keys),
|
|
356
|
+
keys: buildKeys(funding, keys, inputs),
|
|
320
357
|
amount
|
|
321
358
|
});
|
|
322
359
|
if (bsvResult.error)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
360
|
+
throw new Error(bsvResult.error);
|
|
361
|
+
const txid = bsvResult.txid?.trim();
|
|
362
|
+
if (!txid)
|
|
363
|
+
throw new Error("Sweep returned no transaction ID");
|
|
364
|
+
result.bsvTxid = txid;
|
|
326
365
|
} catch (e) {
|
|
327
366
|
result.errors.push(`BSV: ${e instanceof Error ? e.message : String(e)}`);
|
|
328
367
|
}
|
|
@@ -338,14 +377,14 @@ async function executeSweep(params) {
|
|
|
338
377
|
const inputs = await prepareSweepInputs(ctx, batch);
|
|
339
378
|
const ordResult = await sweepOrdinals.execute(ctx, {
|
|
340
379
|
inputs,
|
|
341
|
-
keys: buildKeys(batch, keys)
|
|
380
|
+
keys: buildKeys(batch, keys, inputs)
|
|
342
381
|
});
|
|
343
|
-
if (ordResult.error)
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
382
|
+
if (ordResult.error)
|
|
383
|
+
throw new Error(ordResult.error);
|
|
384
|
+
const txid = ordResult.txid?.trim();
|
|
385
|
+
if (!txid)
|
|
386
|
+
throw new Error("Sweep returned no transaction ID");
|
|
387
|
+
result.ordinalTxids.push(txid);
|
|
349
388
|
result.sweptOutpoints.push(...batch.map((o) => o.outpoint));
|
|
350
389
|
} catch (e) {
|
|
351
390
|
result.errors.push(`Ordinals batch ${b + 1}/${batches.length}: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -1089,6 +1128,47 @@ function Bsv20Section({ tokens }) {
|
|
|
1089
1128
|
]
|
|
1090
1129
|
});
|
|
1091
1130
|
}
|
|
1131
|
+
function ListingsSection({
|
|
1132
|
+
listings,
|
|
1133
|
+
walletConnected,
|
|
1134
|
+
onCancel
|
|
1135
|
+
}) {
|
|
1136
|
+
if (listings.length === 0)
|
|
1137
|
+
return null;
|
|
1138
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1139
|
+
className: "border border-primary/20 bg-primary/5 p-4 rounded-lg space-y-3",
|
|
1140
|
+
children: [
|
|
1141
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1142
|
+
className: "flex items-center gap-2",
|
|
1143
|
+
children: [
|
|
1144
|
+
/* @__PURE__ */ jsx4("span", {
|
|
1145
|
+
className: "h-2 w-2 rounded-full bg-primary"
|
|
1146
|
+
}),
|
|
1147
|
+
/* @__PURE__ */ jsx4("span", {
|
|
1148
|
+
className: "text-sm font-semibold text-primary",
|
|
1149
|
+
children: "OrdLock Listings"
|
|
1150
|
+
})
|
|
1151
|
+
]
|
|
1152
|
+
}),
|
|
1153
|
+
/* @__PURE__ */ jsxs("p", {
|
|
1154
|
+
className: "text-xs text-muted-foreground",
|
|
1155
|
+
children: [
|
|
1156
|
+
listings.length,
|
|
1157
|
+
" listed UTXO",
|
|
1158
|
+
listings.length !== 1 ? "s" : "",
|
|
1159
|
+
". These are cancelled into your BRC-100 wallet on BSV sweep."
|
|
1160
|
+
]
|
|
1161
|
+
}),
|
|
1162
|
+
onCancel && /* @__PURE__ */ jsx4(Button, {
|
|
1163
|
+
size: "sm",
|
|
1164
|
+
disabled: !walletConnected,
|
|
1165
|
+
onClick: onCancel,
|
|
1166
|
+
className: "w-full",
|
|
1167
|
+
children: "Cancel listings into wallet"
|
|
1168
|
+
})
|
|
1169
|
+
]
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1092
1172
|
function LockedSection({ locked }) {
|
|
1093
1173
|
if (locked.length === 0)
|
|
1094
1174
|
return null;
|
|
@@ -2320,7 +2400,7 @@ function SweepApp({
|
|
|
2320
2400
|
];
|
|
2321
2401
|
const result = await scanAddresses(addresses, (p) => setScanProgress(p.detail ?? p.phase));
|
|
2322
2402
|
setAssets(result);
|
|
2323
|
-
const total = result.funding.length + result.ordinals.length + result.opnsNames.length + result.bsv21Tokens.reduce((n, t) => n + t.outputs.length, 0) + result.bsv20Tokens.length + result.locked.length + result.run.length;
|
|
2403
|
+
const total = result.funding.length + result.ordinals.length + result.opnsNames.length + result.bsv21Tokens.reduce((n, t) => n + t.outputs.length, 0) + result.bsv20Tokens.length + result.listings.length + result.locked.length + result.run.length;
|
|
2324
2404
|
if (total === 0)
|
|
2325
2405
|
toast.info("No assets found at legacy addresses");
|
|
2326
2406
|
if (result.ordinals.length > 0)
|
|
@@ -2385,12 +2465,18 @@ function SweepApp({
|
|
|
2385
2465
|
keys: keyMap,
|
|
2386
2466
|
funding: getSelectedFunding(),
|
|
2387
2467
|
ordinals: [],
|
|
2468
|
+
listings: assets.listings,
|
|
2388
2469
|
amount: sweepAmount ?? undefined,
|
|
2389
2470
|
onProgress: setSweepProgress
|
|
2390
2471
|
});
|
|
2391
|
-
|
|
2472
|
+
for (const txid of result.listingTxids)
|
|
2473
|
+
addTx("Cancel listings", txid);
|
|
2474
|
+
if (result.errors.length > 0) {
|
|
2475
|
+
if (result.cancelledListings.length > 0)
|
|
2476
|
+
await refreshAssets();
|
|
2392
2477
|
throw new Error(result.errors[0]);
|
|
2393
|
-
|
|
2478
|
+
}
|
|
2479
|
+
return result.bsvTxid ?? result.listingTxids[0] ?? "";
|
|
2394
2480
|
});
|
|
2395
2481
|
}, [
|
|
2396
2482
|
resolveWallet,
|
|
@@ -2398,7 +2484,44 @@ function SweepApp({
|
|
|
2398
2484
|
assets,
|
|
2399
2485
|
sweepAmount,
|
|
2400
2486
|
getSelectedFunding,
|
|
2401
|
-
runOperation
|
|
2487
|
+
runOperation,
|
|
2488
|
+
keyMap,
|
|
2489
|
+
addTx,
|
|
2490
|
+
refreshAssets
|
|
2491
|
+
]);
|
|
2492
|
+
const handleCancelListings = useCallback2(async () => {
|
|
2493
|
+
const wallet = resolveWallet();
|
|
2494
|
+
if (!wallet || !legacyKeys || !assets || assets.listings.length === 0)
|
|
2495
|
+
return;
|
|
2496
|
+
await runOperation("Cancel listings", async () => {
|
|
2497
|
+
const result = await executeSweep({
|
|
2498
|
+
wallet,
|
|
2499
|
+
keys: keyMap,
|
|
2500
|
+
funding: [],
|
|
2501
|
+
ordinals: [],
|
|
2502
|
+
listings: assets.listings,
|
|
2503
|
+
onProgress: setSweepProgress
|
|
2504
|
+
});
|
|
2505
|
+
if (result.errors.length > 0) {
|
|
2506
|
+
for (const txid of result.listingTxids)
|
|
2507
|
+
addTx("Cancel listings", txid);
|
|
2508
|
+
if (result.cancelledListings.length > 0)
|
|
2509
|
+
await refreshAssets();
|
|
2510
|
+
throw new Error(result.errors[0]);
|
|
2511
|
+
}
|
|
2512
|
+
for (let i = 0;i < result.listingTxids.length - 1; i++) {
|
|
2513
|
+
addTx("Cancel listings", result.listingTxids[i]);
|
|
2514
|
+
}
|
|
2515
|
+
return result.listingTxids[result.listingTxids.length - 1] ?? "";
|
|
2516
|
+
});
|
|
2517
|
+
}, [
|
|
2518
|
+
resolveWallet,
|
|
2519
|
+
legacyKeys,
|
|
2520
|
+
assets,
|
|
2521
|
+
keyMap,
|
|
2522
|
+
runOperation,
|
|
2523
|
+
addTx,
|
|
2524
|
+
refreshAssets
|
|
2402
2525
|
]);
|
|
2403
2526
|
const handleSendBsv = useCallback2(async (destination) => {
|
|
2404
2527
|
if (!legacyKeys || !assets)
|
|
@@ -2634,6 +2757,11 @@ function SweepApp({
|
|
|
2634
2757
|
onSend: sweepOnly ? undefined : handleSendBsv,
|
|
2635
2758
|
walletConnected
|
|
2636
2759
|
}),
|
|
2760
|
+
/* @__PURE__ */ jsx11(ListingsSection, {
|
|
2761
|
+
listings: assets.listings,
|
|
2762
|
+
walletConnected,
|
|
2763
|
+
onCancel: handleCancelListings
|
|
2764
|
+
}),
|
|
2637
2765
|
tabs.length > 0 && /* @__PURE__ */ jsxs6(Tabs, {
|
|
2638
2766
|
value: activeTab,
|
|
2639
2767
|
onValueChange: (v) => setActiveTab(v),
|
|
@@ -2841,6 +2969,7 @@ export {
|
|
|
2841
2969
|
ConnectWallet,
|
|
2842
2970
|
FundingSection,
|
|
2843
2971
|
Input,
|
|
2972
|
+
ListingsSection,
|
|
2844
2973
|
LockedSection,
|
|
2845
2974
|
OpnsSection,
|
|
2846
2975
|
OrdinalsSection,
|
package/dist/lib/scanner.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface EnrichedOrdinal extends IndexedOutput {
|
|
|
10
10
|
export interface ScannedAssets extends Omit<ScanResult, 'ordinals' | 'opnsNames'> {
|
|
11
11
|
ordinals: EnrichedOrdinal[];
|
|
12
12
|
opnsNames: EnrichedOrdinal[];
|
|
13
|
+
listings: EnrichedOrdinal[];
|
|
13
14
|
bsv21Tokens: TokenBalance[];
|
|
14
15
|
totalBsv: number;
|
|
15
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EAEjB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,CAAA;AAEtD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAChB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,WAAW,CAAC;IAClD,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,SAAS,EAAE,eAAe,EAAE,CAAA;IAC5B,WAAW,EAAE,YAAY,EAAE,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AA2CD,wBAAsB,WAAW,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CAGxB;AAED,wBAAsB,aAAa,CAClC,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CAIxB"}
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,YAAY,EAEjB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,CAAA;AAEtD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAChB,SAAQ,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,WAAW,CAAC;IAClD,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,SAAS,EAAE,eAAe,EAAE,CAAA;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,WAAW,EAAE,YAAY,EAAE,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AA2CD,wBAAsB,WAAW,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CAGxB;AAED,wBAAsB,aAAa,CAClC,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CAIxB"}
|
package/dist/lib/sweeper.d.ts
CHANGED
|
@@ -6,10 +6,13 @@ export declare const SWEEP_BATCH_SIZE = 25;
|
|
|
6
6
|
export interface SweepResult {
|
|
7
7
|
bsvTxid?: string;
|
|
8
8
|
ordinalTxids: string[];
|
|
9
|
+
listingTxids: string[];
|
|
9
10
|
bsv21Txids: string[];
|
|
10
11
|
errors: string[];
|
|
11
12
|
/** Outpoints successfully swept (ordinals/OpNS). */
|
|
12
13
|
sweptOutpoints: string[];
|
|
14
|
+
/** Listing outpoints cancelled into the BRC-100 wallet. */
|
|
15
|
+
cancelledListings: string[];
|
|
13
16
|
}
|
|
14
17
|
/**
|
|
15
18
|
* Sweep BSV funding and ordinals into the connected wallet.
|
|
@@ -20,6 +23,8 @@ export declare function executeSweep(params: {
|
|
|
20
23
|
keys: Map<string, PrivateKey>;
|
|
21
24
|
funding: IndexedOutput[];
|
|
22
25
|
ordinals: IndexedOutput[];
|
|
26
|
+
/** OPL-4696: listed OrdLock UTXOs — cancelled into BRC-100 via sweepOrdinals. */
|
|
27
|
+
listings?: IndexedOutput[];
|
|
23
28
|
amount?: number;
|
|
24
29
|
onProgress: (stage: string) => void;
|
|
25
30
|
}): Promise<SweepResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sweeper.d.ts","sourceRoot":"","sources":["../../src/lib/sweeper.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAG7C,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,MAAM,WAAW,WAAW;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,oDAAoD;IACpD,cAAc,EAAE,MAAM,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"sweeper.d.ts","sourceRoot":"","sources":["../../src/lib/sweeper.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAG7C,wFAAwF;AACxF,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,MAAM,WAAW,WAAW;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,oDAAoD;IACpD,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC3B;AA8BD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE;IAC1C,MAAM,EAAE,eAAe,CAAA;IACvB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAC7B,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC,GAAG,OAAO,CAAC,WAAW,CAAC,CAsGvB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC7C,MAAM,EAAE,eAAe,CAAA;IACvB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAC7B,KAAK,EAAE,YAAY,CAAA;IACnB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC,GAAG,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA4B7C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1sat/sweep-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.94",
|
|
4
4
|
"description": "Sweep UI components for migrating legacy BSV assets",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
],
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@1sat/actions": "0.0.
|
|
33
|
-
"@1sat/client": "0.0.
|
|
34
|
-
"@1sat/connect": "0.0.
|
|
35
|
-
"@1sat/types": "0.0.
|
|
36
|
-
"@1sat/utils": "0.0.
|
|
32
|
+
"@1sat/actions": "0.0.214",
|
|
33
|
+
"@1sat/client": "0.0.52",
|
|
34
|
+
"@1sat/connect": "0.0.92",
|
|
35
|
+
"@1sat/types": "0.0.44",
|
|
36
|
+
"@1sat/utils": "0.0.35",
|
|
37
37
|
"bitcoin-backup": "^0.0.11",
|
|
38
38
|
"class-variance-authority": "^0.7.1",
|
|
39
39
|
"clsx": "^2.1.1",
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
"tailwind-merge": "^3.5.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@bsv/sdk": "^2.
|
|
45
|
+
"@bsv/sdk": "^2.5.0",
|
|
46
46
|
"react": "^18.0.0 || ^19.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@bsv/sdk": "^2.
|
|
49
|
+
"@bsv/sdk": "^2.5.0",
|
|
50
50
|
"@types/react": "^19.0.0",
|
|
51
51
|
"react": "^19.0.0",
|
|
52
52
|
"typescript": "~5.7.0"
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
Bsv20Section,
|
|
20
20
|
Bsv21Section,
|
|
21
21
|
FundingSection,
|
|
22
|
+
ListingsSection,
|
|
22
23
|
LockedSection,
|
|
23
24
|
OrdinalsSection,
|
|
24
25
|
RunSection,
|
|
@@ -192,6 +193,7 @@ export function SweepApp({
|
|
|
192
193
|
result.opnsNames.length +
|
|
193
194
|
result.bsv21Tokens.reduce((n, t) => n + t.outputs.length, 0) +
|
|
194
195
|
result.bsv20Tokens.length +
|
|
196
|
+
result.listings.length +
|
|
195
197
|
result.locked.length +
|
|
196
198
|
result.run.length
|
|
197
199
|
if (total === 0) toast.info('No assets found at legacy addresses')
|
|
@@ -255,11 +257,16 @@ export function SweepApp({
|
|
|
255
257
|
keys: keyMap,
|
|
256
258
|
funding: getSelectedFunding(),
|
|
257
259
|
ordinals: [],
|
|
260
|
+
listings: assets.listings,
|
|
258
261
|
amount: sweepAmount ?? undefined,
|
|
259
262
|
onProgress: setSweepProgress,
|
|
260
263
|
})
|
|
261
|
-
|
|
262
|
-
|
|
264
|
+
for (const txid of result.listingTxids) addTx('Cancel listings', txid)
|
|
265
|
+
if (result.errors.length > 0) {
|
|
266
|
+
if (result.cancelledListings.length > 0) await refreshAssets()
|
|
267
|
+
throw new Error(result.errors[0])
|
|
268
|
+
}
|
|
269
|
+
return result.bsvTxid ?? result.listingTxids[0] ?? ''
|
|
263
270
|
})
|
|
264
271
|
}, [
|
|
265
272
|
resolveWallet,
|
|
@@ -268,6 +275,42 @@ export function SweepApp({
|
|
|
268
275
|
sweepAmount,
|
|
269
276
|
getSelectedFunding,
|
|
270
277
|
runOperation,
|
|
278
|
+
keyMap,
|
|
279
|
+
addTx,
|
|
280
|
+
refreshAssets,
|
|
281
|
+
])
|
|
282
|
+
|
|
283
|
+
const handleCancelListings = useCallback(async () => {
|
|
284
|
+
const wallet = resolveWallet()
|
|
285
|
+
if (!wallet || !legacyKeys || !assets || assets.listings.length === 0)
|
|
286
|
+
return
|
|
287
|
+
await runOperation('Cancel listings', async () => {
|
|
288
|
+
const result = await executeSweep({
|
|
289
|
+
wallet,
|
|
290
|
+
keys: keyMap,
|
|
291
|
+
funding: [],
|
|
292
|
+
ordinals: [],
|
|
293
|
+
listings: assets.listings,
|
|
294
|
+
onProgress: setSweepProgress,
|
|
295
|
+
})
|
|
296
|
+
if (result.errors.length > 0) {
|
|
297
|
+
for (const txid of result.listingTxids) addTx('Cancel listings', txid)
|
|
298
|
+
if (result.cancelledListings.length > 0) await refreshAssets()
|
|
299
|
+
throw new Error(result.errors[0])
|
|
300
|
+
}
|
|
301
|
+
for (let i = 0; i < result.listingTxids.length - 1; i++) {
|
|
302
|
+
addTx('Cancel listings', result.listingTxids[i])
|
|
303
|
+
}
|
|
304
|
+
return result.listingTxids[result.listingTxids.length - 1] ?? ''
|
|
305
|
+
})
|
|
306
|
+
}, [
|
|
307
|
+
resolveWallet,
|
|
308
|
+
legacyKeys,
|
|
309
|
+
assets,
|
|
310
|
+
keyMap,
|
|
311
|
+
runOperation,
|
|
312
|
+
addTx,
|
|
313
|
+
refreshAssets,
|
|
271
314
|
])
|
|
272
315
|
|
|
273
316
|
const handleSendBsv = useCallback(
|
|
@@ -543,6 +586,11 @@ export function SweepApp({
|
|
|
543
586
|
onSend={sweepOnly ? undefined : handleSendBsv}
|
|
544
587
|
walletConnected={walletConnected}
|
|
545
588
|
/>
|
|
589
|
+
<ListingsSection
|
|
590
|
+
listings={assets.listings}
|
|
591
|
+
walletConnected={walletConnected}
|
|
592
|
+
onCancel={handleCancelListings}
|
|
593
|
+
/>
|
|
546
594
|
|
|
547
595
|
{tabs.length > 0 && (
|
|
548
596
|
<Tabs
|
|
@@ -526,6 +526,42 @@ export function Bsv20Section({ tokens }: { tokens: IndexedOutput[] }) {
|
|
|
526
526
|
)
|
|
527
527
|
}
|
|
528
528
|
|
|
529
|
+
export function ListingsSection({
|
|
530
|
+
listings,
|
|
531
|
+
walletConnected,
|
|
532
|
+
onCancel,
|
|
533
|
+
}: {
|
|
534
|
+
listings: EnrichedOrdinal[]
|
|
535
|
+
walletConnected?: boolean
|
|
536
|
+
onCancel?: () => void
|
|
537
|
+
}) {
|
|
538
|
+
if (listings.length === 0) return null
|
|
539
|
+
return (
|
|
540
|
+
<div className="border border-primary/20 bg-primary/5 p-4 rounded-lg space-y-3">
|
|
541
|
+
<div className="flex items-center gap-2">
|
|
542
|
+
<span className="h-2 w-2 rounded-full bg-primary" />
|
|
543
|
+
<span className="text-sm font-semibold text-primary">
|
|
544
|
+
OrdLock Listings
|
|
545
|
+
</span>
|
|
546
|
+
</div>
|
|
547
|
+
<p className="text-xs text-muted-foreground">
|
|
548
|
+
{listings.length} listed UTXO{listings.length !== 1 ? 's' : ''}. These
|
|
549
|
+
are cancelled into your BRC-100 wallet on BSV sweep.
|
|
550
|
+
</p>
|
|
551
|
+
{onCancel && (
|
|
552
|
+
<Button
|
|
553
|
+
size="sm"
|
|
554
|
+
disabled={!walletConnected}
|
|
555
|
+
onClick={onCancel}
|
|
556
|
+
className="w-full"
|
|
557
|
+
>
|
|
558
|
+
Cancel listings into wallet
|
|
559
|
+
</Button>
|
|
560
|
+
)}
|
|
561
|
+
</div>
|
|
562
|
+
)
|
|
563
|
+
}
|
|
564
|
+
|
|
529
565
|
export function LockedSection({ locked }: { locked: IndexedOutput[] }) {
|
|
530
566
|
if (locked.length === 0) return null
|
|
531
567
|
return (
|
package/src/index.ts
CHANGED
package/src/lib/scanner.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface ScannedAssets
|
|
|
21
21
|
extends Omit<ScanResult, 'ordinals' | 'opnsNames'> {
|
|
22
22
|
ordinals: EnrichedOrdinal[]
|
|
23
23
|
opnsNames: EnrichedOrdinal[]
|
|
24
|
+
listings: EnrichedOrdinal[]
|
|
24
25
|
bsv21Tokens: TokenBalance[]
|
|
25
26
|
totalBsv: number
|
|
26
27
|
}
|
|
@@ -92,6 +93,7 @@ function toScannedAssets(result: ScanResult): ScannedAssets {
|
|
|
92
93
|
funding: result.funding,
|
|
93
94
|
ordinals: result.ordinals.map(enrichOrdinal),
|
|
94
95
|
opnsNames: result.opnsNames.map(enrichOrdinal),
|
|
96
|
+
listings: result.listings.map(enrichOrdinal),
|
|
95
97
|
bsv21Tokens: enrichTokenBalances(result.bsv21Tokens),
|
|
96
98
|
bsv20Tokens: result.bsv20Tokens,
|
|
97
99
|
locked: result.locked,
|
package/src/lib/sweeper.ts
CHANGED
|
@@ -16,10 +16,13 @@ export const SWEEP_BATCH_SIZE = 25
|
|
|
16
16
|
export interface SweepResult {
|
|
17
17
|
bsvTxid?: string
|
|
18
18
|
ordinalTxids: string[]
|
|
19
|
+
listingTxids: string[]
|
|
19
20
|
bsv21Txids: string[]
|
|
20
21
|
errors: string[]
|
|
21
22
|
/** Outpoints successfully swept (ordinals/OpNS). */
|
|
22
23
|
sweptOutpoints: string[]
|
|
24
|
+
/** Listing outpoints cancelled into the BRC-100 wallet. */
|
|
25
|
+
cancelledListings: string[]
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
function getOwner(output: IndexedOutput): string | undefined {
|
|
@@ -29,12 +32,15 @@ function getOwner(output: IndexedOutput): string | undefined {
|
|
|
29
32
|
function buildKeys(
|
|
30
33
|
outputs: IndexedOutput[],
|
|
31
34
|
keyMap: Map<string, PrivateKey>,
|
|
35
|
+
inputs: Pick<IndexedOutput, 'outpoint'>[] = outputs,
|
|
32
36
|
): PrivateKey[] {
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
const owners = new Map(
|
|
38
|
+
outputs.map((output) => [output.outpoint, getOwner(output)]),
|
|
39
|
+
)
|
|
40
|
+
return inputs.map(({ outpoint }) => {
|
|
41
|
+
const owner = owners.get(outpoint)
|
|
35
42
|
const key = owner ? keyMap.get(owner) : undefined
|
|
36
|
-
if (!key)
|
|
37
|
-
throw new Error(`No key for output ${output.outpoint} (owner: ${owner})`)
|
|
43
|
+
if (!key) throw new Error(`No key for output ${outpoint} (owner: ${owner})`)
|
|
38
44
|
return key
|
|
39
45
|
})
|
|
40
46
|
}
|
|
@@ -56,17 +62,57 @@ export async function executeSweep(params: {
|
|
|
56
62
|
keys: Map<string, PrivateKey>
|
|
57
63
|
funding: IndexedOutput[]
|
|
58
64
|
ordinals: IndexedOutput[]
|
|
65
|
+
/** OPL-4696: listed OrdLock UTXOs — cancelled into BRC-100 via sweepOrdinals. */
|
|
66
|
+
listings?: IndexedOutput[]
|
|
59
67
|
amount?: number
|
|
60
68
|
onProgress: (stage: string) => void
|
|
61
69
|
}): Promise<SweepResult> {
|
|
62
|
-
const {
|
|
70
|
+
const {
|
|
71
|
+
wallet,
|
|
72
|
+
keys,
|
|
73
|
+
funding,
|
|
74
|
+
ordinals,
|
|
75
|
+
listings = [],
|
|
76
|
+
amount,
|
|
77
|
+
onProgress,
|
|
78
|
+
} = params
|
|
63
79
|
const ctx = createContext(wallet, { services: getServices(), chain: 'main' })
|
|
64
80
|
|
|
65
81
|
const result: SweepResult = {
|
|
66
82
|
ordinalTxids: [],
|
|
83
|
+
listingTxids: [],
|
|
67
84
|
bsv21Txids: [],
|
|
68
85
|
errors: [],
|
|
69
86
|
sweptOutpoints: [],
|
|
87
|
+
cancelledListings: [],
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (listings.length > 0) {
|
|
91
|
+
const batches = chunk(listings, SWEEP_BATCH_SIZE)
|
|
92
|
+
for (let b = 0; b < batches.length; b++) {
|
|
93
|
+
const batch = batches[b]
|
|
94
|
+
onProgress(
|
|
95
|
+
`Cancelling ${batch.length} OrdLock listing${batch.length !== 1 ? 's' : ''} into wallet...`,
|
|
96
|
+
)
|
|
97
|
+
try {
|
|
98
|
+
const inputs = await prepareSweepInputs(ctx, batch)
|
|
99
|
+
const cancelResult = await sweepOrdinals.execute(ctx, {
|
|
100
|
+
inputs,
|
|
101
|
+
keys: buildKeys(batch, keys, inputs),
|
|
102
|
+
})
|
|
103
|
+
if (cancelResult.error) throw new Error(cancelResult.error)
|
|
104
|
+
const txid = cancelResult.txid?.trim()
|
|
105
|
+
if (!txid) throw new Error('Cancellation returned no transaction ID')
|
|
106
|
+
result.listingTxids.push(txid)
|
|
107
|
+
result.cancelledListings.push(...batch.map((o) => o.outpoint))
|
|
108
|
+
} catch (e) {
|
|
109
|
+
result.errors.push(
|
|
110
|
+
`Listings batch ${b + 1}: ${e instanceof Error ? e.message : String(e)}`,
|
|
111
|
+
)
|
|
112
|
+
onProgress('Sweep stopped with errors')
|
|
113
|
+
return result
|
|
114
|
+
}
|
|
115
|
+
}
|
|
70
116
|
}
|
|
71
117
|
|
|
72
118
|
if (funding.length > 0) {
|
|
@@ -75,11 +121,13 @@ export async function executeSweep(params: {
|
|
|
75
121
|
const inputs = await prepareSweepInputs(ctx, funding)
|
|
76
122
|
const bsvResult = await sweepBsv.execute(ctx, {
|
|
77
123
|
inputs,
|
|
78
|
-
keys: buildKeys(funding, keys),
|
|
124
|
+
keys: buildKeys(funding, keys, inputs),
|
|
79
125
|
amount,
|
|
80
126
|
})
|
|
81
|
-
if (bsvResult.error)
|
|
82
|
-
|
|
127
|
+
if (bsvResult.error) throw new Error(bsvResult.error)
|
|
128
|
+
const txid = bsvResult.txid?.trim()
|
|
129
|
+
if (!txid) throw new Error('Sweep returned no transaction ID')
|
|
130
|
+
result.bsvTxid = txid
|
|
83
131
|
} catch (e) {
|
|
84
132
|
result.errors.push(`BSV: ${e instanceof Error ? e.message : String(e)}`)
|
|
85
133
|
}
|
|
@@ -100,15 +148,12 @@ export async function executeSweep(params: {
|
|
|
100
148
|
const inputs = await prepareSweepInputs(ctx, batch)
|
|
101
149
|
const ordResult = await sweepOrdinals.execute(ctx, {
|
|
102
150
|
inputs,
|
|
103
|
-
keys: buildKeys(batch, keys),
|
|
151
|
+
keys: buildKeys(batch, keys, inputs),
|
|
104
152
|
})
|
|
105
|
-
if (ordResult.error)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
break
|
|
110
|
-
}
|
|
111
|
-
if (ordResult.txid) result.ordinalTxids.push(ordResult.txid)
|
|
153
|
+
if (ordResult.error) throw new Error(ordResult.error)
|
|
154
|
+
const txid = ordResult.txid?.trim()
|
|
155
|
+
if (!txid) throw new Error('Sweep returned no transaction ID')
|
|
156
|
+
result.ordinalTxids.push(txid)
|
|
112
157
|
result.sweptOutpoints.push(...batch.map((o) => o.outpoint))
|
|
113
158
|
} catch (e) {
|
|
114
159
|
result.errors.push(
|