@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.
@@ -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;AAkB1C,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,+BAqkBf"}
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';
@@ -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
- return outputs.map((output) => {
290
- const owner = getOwner(output);
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 ${output.outpoint} (owner: ${owner})`);
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 { wallet, keys, funding, ordinals, amount, onProgress } = params;
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
- result.errors.push(`BSV: ${bsvResult.error}`);
324
- else if (bsvResult.txid)
325
- result.bsvTxid = bsvResult.txid;
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
- result.errors.push(`Ordinals batch ${b + 1}/${batches.length}: ${ordResult.error}`);
345
- break;
346
- }
347
- if (ordResult.txid)
348
- result.ordinalTxids.push(ordResult.txid);
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
- if (result.errors.length > 0)
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
- return result.bsvTxid ?? "";
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,
@@ -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"}
@@ -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;CACxB;AA2BD;;;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,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC,GAAG,OAAO,CAAC,WAAW,CAAC,CAiEvB;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"}
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.92",
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.208",
33
- "@1sat/client": "0.0.51",
34
- "@1sat/connect": "0.0.91",
35
- "@1sat/types": "0.0.41",
36
- "@1sat/utils": "0.0.34",
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.1.9",
45
+ "@bsv/sdk": "^2.5.0",
46
46
  "react": "^18.0.0 || ^19.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@bsv/sdk": "^2.1.9",
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
- if (result.errors.length > 0) throw new Error(result.errors[0])
262
- return result.bsvTxid ?? ''
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
@@ -9,6 +9,7 @@ export {
9
9
  OrdinalsSection,
10
10
  Bsv21Section,
11
11
  Bsv20Section,
12
+ ListingsSection,
12
13
  LockedSection,
13
14
  RunSection,
14
15
  } from './components/asset-preview'
@@ -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,
@@ -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
- return outputs.map((output) => {
34
- const owner = getOwner(output)
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 { wallet, keys, funding, ordinals, amount, onProgress } = params
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) result.errors.push(`BSV: ${bsvResult.error}`)
82
- else if (bsvResult.txid) result.bsvTxid = bsvResult.txid
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
- result.errors.push(
107
- `Ordinals batch ${b + 1}/${batches.length}: ${ordResult.error}`,
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(