@1sat/sweep-ui 0.0.94 → 0.0.96

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/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/components/SweepApp.tsx
2
+ import { groupBsv20Tokens as groupBsv20Tokens2 } from "@1sat/actions";
2
3
  import { PrivateKey as PrivateKey3 } from "@bsv/sdk";
3
4
  import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState5 } from "react";
4
5
  import { Toaster, toast } from "sonner";
@@ -84,7 +85,6 @@ function toScannedAssets(result) {
84
85
  funding: result.funding,
85
86
  ordinals: result.ordinals.map(enrichOrdinal),
86
87
  opnsNames: result.opnsNames.map(enrichOrdinal),
87
- listings: result.listings.map(enrichOrdinal),
88
88
  bsv21Tokens: enrichTokenBalances(result.bsv21Tokens),
89
89
  bsv20Tokens: result.bsv20Tokens,
90
90
  locked: result.locked,
@@ -276,13 +276,16 @@ async function legacyBurnOrdinals(params) {
276
276
 
277
277
  // src/lib/sweeper.ts
278
278
  import {
279
+ SWEEP_BATCH_SIZE,
280
+ bsv21SweepBatches,
279
281
  createContext,
282
+ groupBsv20Tokens,
280
283
  prepareSweepInputs,
281
284
  sweepBsv,
285
+ sweepBsv20,
282
286
  sweepBsv21,
283
287
  sweepOrdinals
284
288
  } from "@1sat/actions";
285
- var SWEEP_BATCH_SIZE = 25;
286
289
  function getOwner(output) {
287
290
  return output.events?.find((e) => e.startsWith("own:"))?.slice(4);
288
291
  }
@@ -304,49 +307,15 @@ function chunk(items, size) {
304
307
  return batches;
305
308
  }
306
309
  async function executeSweep(params) {
307
- const {
308
- wallet,
309
- keys,
310
- funding,
311
- ordinals,
312
- listings = [],
313
- amount,
314
- onProgress
315
- } = params;
310
+ const { wallet, keys, funding, ordinals, amount, onProgress } = params;
316
311
  const ctx = createContext(wallet, { services: getServices(), chain: "main" });
317
312
  const result = {
318
313
  ordinalTxids: [],
319
- listingTxids: [],
314
+ bsv20Txids: [],
320
315
  bsv21Txids: [],
321
316
  errors: [],
322
- sweptOutpoints: [],
323
- cancelledListings: []
317
+ sweptOutpoints: []
324
318
  };
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
- }
350
319
  if (funding.length > 0) {
351
320
  onProgress(`Sweeping ${funding.length} BSV UTXOs...`);
352
321
  try {
@@ -398,7 +367,46 @@ async function executeSweep(params) {
398
367
  async function sweepBsv21Token(params) {
399
368
  const { wallet, keys, token, onProgress } = params;
400
369
  const ctx = createContext(wallet, { services: getServices(), chain: "main" });
401
- onProgress(`Sweeping ${token.symbol ?? token.tokenId.slice(0, 8)}...`);
370
+ const txids = [];
371
+ const errors = [];
372
+ const name = token.symbol ?? token.tokenId.slice(0, 8);
373
+ for (const batch of bsv21SweepBatches(token.outputs)) {
374
+ onProgress(`Sweeping ${name}...`);
375
+ try {
376
+ const sweepInputs = await prepareSweepInputs(ctx, batch);
377
+ const sweepInputMap = new Map(sweepInputs.map((s) => [s.outpoint, s]));
378
+ const inputs = batch.map((out) => {
379
+ const base = sweepInputMap.get(out.outpoint);
380
+ if (!base)
381
+ throw new Error(`Missing sweep input for ${out.outpoint}`);
382
+ return {
383
+ ...base,
384
+ tokenId: token.tokenId,
385
+ amount: token.amounts.get(out.outpoint) ?? "0"
386
+ };
387
+ });
388
+ const result = await sweepBsv21.execute(ctx, {
389
+ inputs,
390
+ keys: buildKeys(batch, keys)
391
+ });
392
+ if (result.error)
393
+ errors.push(result.error);
394
+ else if (result.txid)
395
+ txids.push(result.txid);
396
+ } catch (e) {
397
+ errors.push(e instanceof Error ? e.message : String(e));
398
+ }
399
+ }
400
+ return {
401
+ txid: txids.at(-1),
402
+ txids,
403
+ error: errors[0]
404
+ };
405
+ }
406
+ async function sweepBsv20Token(params) {
407
+ const { wallet, keys, token, onProgress } = params;
408
+ const ctx = createContext(wallet, { services: getServices(), chain: "main" });
409
+ onProgress(`Sweeping ${token.tick}...`);
402
410
  try {
403
411
  const sweepInputs = await prepareSweepInputs(ctx, token.outputs);
404
412
  const sweepInputMap = new Map(sweepInputs.map((s) => [s.outpoint, s]));
@@ -408,12 +416,14 @@ async function sweepBsv21Token(params) {
408
416
  throw new Error(`Missing sweep input for ${out.outpoint}`);
409
417
  return {
410
418
  ...base,
411
- tokenId: token.tokenId,
419
+ tick: token.tick,
412
420
  amount: token.amounts.get(out.outpoint) ?? "0"
413
421
  };
414
422
  });
415
- const tokenKeys = buildKeys(token.outputs, keys);
416
- const result = await sweepBsv21.execute(ctx, { inputs, keys: tokenKeys });
423
+ const result = await sweepBsv20.execute(ctx, {
424
+ inputs,
425
+ keys: buildKeys(token.outputs, keys)
426
+ });
417
427
  if (result.error)
418
428
  return { error: result.error };
419
429
  return { txid: result.txid };
@@ -421,6 +431,68 @@ async function sweepBsv21Token(params) {
421
431
  return { error: e instanceof Error ? e.message : String(e) };
422
432
  }
423
433
  }
434
+ async function sweepAllClasses(params) {
435
+ const { wallet, keys, assets, amount, onProgress } = params;
436
+ const result = {
437
+ ordinalTxids: [],
438
+ bsv20Txids: [],
439
+ bsv21Txids: [],
440
+ errors: [],
441
+ sweptOutpoints: []
442
+ };
443
+ const first = await executeSweep({
444
+ wallet,
445
+ keys,
446
+ funding: assets.funding,
447
+ ordinals: assets.ordinals,
448
+ amount,
449
+ onProgress
450
+ });
451
+ result.bsvTxid = first.bsvTxid;
452
+ result.ordinalTxids.push(...first.ordinalTxids);
453
+ result.sweptOutpoints.push(...first.sweptOutpoints);
454
+ result.errors.push(...first.errors);
455
+ if (assets.opnsNames.length > 0) {
456
+ const opns = await executeSweep({
457
+ wallet,
458
+ keys,
459
+ funding: [],
460
+ ordinals: assets.opnsNames,
461
+ onProgress
462
+ });
463
+ result.ordinalTxids.push(...opns.ordinalTxids);
464
+ result.sweptOutpoints.push(...opns.sweptOutpoints);
465
+ result.errors.push(...opns.errors);
466
+ }
467
+ for (const token of groupBsv20Tokens(assets.bsv20Tokens)) {
468
+ const swept = await sweepBsv20Token({
469
+ wallet,
470
+ keys,
471
+ token,
472
+ onProgress
473
+ });
474
+ if (swept.error)
475
+ result.errors.push(`BSV-20 ${token.tick}: ${swept.error}`);
476
+ else if (swept.txid)
477
+ result.bsv20Txids.push(swept.txid);
478
+ }
479
+ for (const token of assets.bsv21Tokens) {
480
+ if (token.outputs.length === 0)
481
+ continue;
482
+ const swept = await sweepBsv21Token({
483
+ wallet,
484
+ keys,
485
+ token,
486
+ onProgress
487
+ });
488
+ result.bsv21Txids.push(...swept.txids);
489
+ if (swept.error) {
490
+ result.errors.push(`BSV-21 ${token.symbol ?? token.tokenId.slice(0, 8)}: ${swept.error}`);
491
+ }
492
+ }
493
+ onProgress(result.errors.length > 0 ? "Sweep stopped with errors" : "Sweep complete");
494
+ return result;
495
+ }
424
496
 
425
497
  // src/lib/wallet.ts
426
498
  import {
@@ -452,6 +524,7 @@ function isConnected() {
452
524
  }
453
525
 
454
526
  // src/components/asset-preview.tsx
527
+ import { isListedOutput } from "@1sat/actions";
455
528
  import { useState } from "react";
456
529
 
457
530
  // src/lib/utils.ts
@@ -608,6 +681,13 @@ function OrdinalCard({
608
681
  /* @__PURE__ */ jsxs("div", {
609
682
  className: "min-h-[2rem] flex flex-col justify-end",
610
683
  children: [
684
+ isListedOutput(ordinal) && /* @__PURE__ */ jsx4("div", {
685
+ className: "mb-1",
686
+ children: /* @__PURE__ */ jsx4("span", {
687
+ className: "inline-block px-1 py-0.5 text-[9px] rounded bg-amber-500/20 text-amber-400",
688
+ children: "listed"
689
+ })
690
+ }),
611
691
  subtype && /* @__PURE__ */ jsx4("div", {
612
692
  className: "mb-1",
613
693
  children: /* @__PURE__ */ jsx4("span", {
@@ -966,6 +1046,7 @@ function TokenRow({
966
1046
  onSweep,
967
1047
  walletConnected
968
1048
  }) {
1049
+ const listed = tb.outputs.filter(isListedOutput).length;
969
1050
  return /* @__PURE__ */ jsxs("div", {
970
1051
  className: `flex items-center justify-between p-3 rounded-lg border ${tb.isActive ? "bg-muted/30 border-purple-500/10" : "bg-muted/20 border-muted/20 opacity-60"}`,
971
1052
  children: [
@@ -987,7 +1068,7 @@ function TokenRow({
987
1068
  children: [
988
1069
  /* @__PURE__ */ jsx4("span", {
989
1070
  className: "font-medium text-foreground",
990
- children: tb.symbol || tb.tokenId.slice(0, 8) + "..."
1071
+ children: tb.symbol || `${tb.tokenId.slice(0, 8)}...`
991
1072
  }),
992
1073
  tb.isActive ? /* @__PURE__ */ jsx4("span", {
993
1074
  className: "px-1.5 py-0.5 text-[9px] rounded bg-green-600/20 text-green-700 dark:text-green-400",
@@ -1011,6 +1092,7 @@ function TokenRow({
1011
1092
  tb.outputs.length,
1012
1093
  " output",
1013
1094
  tb.outputs.length !== 1 ? "s" : "",
1095
+ listed ? `, ${listed} listed` : "",
1014
1096
  ")"
1015
1097
  ]
1016
1098
  })
@@ -1020,7 +1102,7 @@ function TokenRow({
1020
1102
  })
1021
1103
  ]
1022
1104
  }),
1023
- tb.isActive && onSweep && /* @__PURE__ */ jsx4(Button, {
1105
+ onSweep && /* @__PURE__ */ jsx4(Button, {
1024
1106
  size: "sm",
1025
1107
  onClick: () => onSweep(tb.tokenId),
1026
1108
  disabled: !walletConnected,
@@ -1082,89 +1164,80 @@ function Bsv21Section({
1082
1164
  ]
1083
1165
  });
1084
1166
  }
1085
- function Bsv20Section({ tokens }) {
1086
- if (tokens.length === 0)
1087
- return null;
1088
- return /* @__PURE__ */ jsxs("div", {
1089
- className: "border border-muted/30 bg-muted/10 p-4 rounded-lg",
1090
- children: [
1091
- /* @__PURE__ */ jsxs("div", {
1092
- className: "flex items-center gap-2 mb-2",
1093
- children: [
1094
- /* @__PURE__ */ jsx4("span", {
1095
- className: "h-2 w-2 rounded-full bg-muted-foreground"
1096
- }),
1097
- /* @__PURE__ */ jsx4("span", {
1098
- className: "text-sm font-semibold text-muted-foreground",
1099
- children: "BSV-20 Tokens"
1100
- })
1101
- ]
1102
- }),
1103
- /* @__PURE__ */ jsx4("p", {
1104
- className: "text-xs text-muted-foreground mb-2",
1105
- children: "Cannot be swept automatically."
1106
- }),
1107
- /* @__PURE__ */ jsxs("div", {
1108
- className: "flex flex-wrap gap-2",
1109
- children: [
1110
- tokens.slice(0, 10).map((o) => {
1111
- const tickEvent = o.events?.find((e) => e.startsWith("tick:"));
1112
- const tick = tickEvent ? tickEvent.slice(5) : "Token";
1113
- return /* @__PURE__ */ jsx4("span", {
1114
- className: "px-2 py-1 text-xs rounded bg-muted/30 text-muted-foreground",
1115
- children: tick
1116
- }, o.outpoint);
1117
- }),
1118
- tokens.length > 10 && /* @__PURE__ */ jsxs("span", {
1119
- className: "text-xs text-muted-foreground",
1120
- children: [
1121
- "+",
1122
- tokens.length - 10,
1123
- " more"
1124
- ]
1125
- })
1126
- ]
1127
- })
1128
- ]
1129
- });
1130
- }
1131
- function ListingsSection({
1132
- listings,
1133
- walletConnected,
1134
- onCancel
1167
+ function Bsv20Section({
1168
+ tokens,
1169
+ unparsedCount = 0,
1170
+ onSweep,
1171
+ walletConnected
1135
1172
  }) {
1136
- if (listings.length === 0)
1173
+ if (tokens.length === 0 && unparsedCount === 0)
1137
1174
  return null;
1138
1175
  return /* @__PURE__ */ jsxs("div", {
1139
- className: "border border-primary/20 bg-primary/5 p-4 rounded-lg space-y-3",
1176
+ className: "border border-teal-500/20 bg-teal-500/5 p-4 rounded-lg",
1140
1177
  children: [
1141
1178
  /* @__PURE__ */ jsxs("div", {
1142
- className: "flex items-center gap-2",
1179
+ className: "flex items-center gap-2 mb-3",
1143
1180
  children: [
1144
1181
  /* @__PURE__ */ jsx4("span", {
1145
- className: "h-2 w-2 rounded-full bg-primary"
1182
+ className: "h-2 w-2 rounded-full bg-teal-500"
1146
1183
  }),
1147
1184
  /* @__PURE__ */ jsx4("span", {
1148
- className: "text-sm font-semibold text-primary",
1149
- children: "OrdLock Listings"
1185
+ className: "text-sm font-semibold text-teal-500",
1186
+ children: "BSV-20 Tokens"
1150
1187
  })
1151
1188
  ]
1152
1189
  }),
1153
- /* @__PURE__ */ jsxs("p", {
1154
- className: "text-xs text-muted-foreground",
1190
+ unparsedCount > 0 && /* @__PURE__ */ jsxs("p", {
1191
+ className: "text-xs text-muted-foreground mb-3",
1155
1192
  children: [
1156
- listings.length,
1157
- " listed UTXO",
1158
- listings.length !== 1 ? "s" : "",
1159
- ". These are cancelled into your BRC-100 wallet on BSV sweep."
1193
+ unparsedCount,
1194
+ " UTXO",
1195
+ unparsedCount !== 1 ? "s" : "",
1196
+ " with no parseable tick/amt — leftover, not swept."
1160
1197
  ]
1161
1198
  }),
1162
- onCancel && /* @__PURE__ */ jsx4(Button, {
1163
- size: "sm",
1164
- disabled: !walletConnected,
1165
- onClick: onCancel,
1166
- className: "w-full",
1167
- children: "Cancel listings into wallet"
1199
+ /* @__PURE__ */ jsx4("div", {
1200
+ className: "space-y-3",
1201
+ children: tokens.map((tb) => {
1202
+ const listed = tb.outputs.filter(isListedOutput).length;
1203
+ return /* @__PURE__ */ jsxs("div", {
1204
+ className: "flex items-center justify-between p-3 rounded-lg border bg-muted/30 border-teal-500/10",
1205
+ children: [
1206
+ /* @__PURE__ */ jsxs("div", {
1207
+ children: [
1208
+ /* @__PURE__ */ jsx4("div", {
1209
+ className: "font-medium text-foreground",
1210
+ children: tb.tick
1211
+ }),
1212
+ /* @__PURE__ */ jsxs("div", {
1213
+ className: "text-xs text-muted-foreground",
1214
+ children: [
1215
+ tb.totalAmount.toString(),
1216
+ /* @__PURE__ */ jsxs("span", {
1217
+ className: "ml-2",
1218
+ children: [
1219
+ "(",
1220
+ tb.outputs.length,
1221
+ " output",
1222
+ tb.outputs.length !== 1 ? "s" : "",
1223
+ listed ? `, ${listed} listed` : "",
1224
+ ")"
1225
+ ]
1226
+ })
1227
+ ]
1228
+ })
1229
+ ]
1230
+ }),
1231
+ onSweep && /* @__PURE__ */ jsx4(Button, {
1232
+ size: "sm",
1233
+ onClick: () => onSweep(tb.tick),
1234
+ disabled: !walletConnected,
1235
+ title: walletConnected ? undefined : "Connect BRC-100 wallet to sweep",
1236
+ children: "Sweep to Wallet"
1237
+ })
1238
+ ]
1239
+ }, tb.tick);
1240
+ })
1168
1241
  })
1169
1242
  ]
1170
1243
  });
@@ -1321,6 +1394,7 @@ function ConnectWallet({
1321
1394
  }
1322
1395
 
1323
1396
  // src/components/opns-section.tsx
1397
+ import { isListedOutput as isListedOutput2 } from "@1sat/actions";
1324
1398
  import { useEffect, useState as useState3 } from "react";
1325
1399
  import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
1326
1400
  function OpnsSection({
@@ -1482,6 +1556,10 @@ function OpnsSection({
1482
1556
  className: "text-sm text-foreground truncate",
1483
1557
  children: displayName
1484
1558
  }),
1559
+ isListedOutput2(item) && /* @__PURE__ */ jsx6("span", {
1560
+ className: "shrink-0 text-[10px] font-medium px-1.5 py-0.5 rounded bg-amber-500/20 text-amber-400",
1561
+ children: "listed"
1562
+ }),
1485
1563
  !validating && overlayValid.has(item.outpoint) && (overlayValid.get(item.outpoint) ? /* @__PURE__ */ jsx6("span", {
1486
1564
  className: "shrink-0 text-[10px] font-medium px-1.5 py-0.5 rounded bg-green-500/20 text-green-400",
1487
1565
  children: "valid"
@@ -2317,6 +2395,8 @@ function SweepApp({
2317
2395
  { label, txid, timestamp: new Date, error }
2318
2396
  ]);
2319
2397
  }, []);
2398
+ const groupedBsv20 = useMemo(() => assets ? groupBsv20Tokens2(assets.bsv20Tokens) : [], [assets]);
2399
+ const unparsedBsv20 = assets ? assets.bsv20Tokens.length - groupedBsv20.reduce((n, t) => n + t.outputs.length, 0) : 0;
2320
2400
  const tabs = useMemo(() => {
2321
2401
  if (!assets)
2322
2402
  return [];
@@ -2329,16 +2409,24 @@ function SweepApp({
2329
2409
  });
2330
2410
  if (assets.opnsNames.length > 0)
2331
2411
  t.push({ id: "opns", label: "OpNS", count: assets.opnsNames.length });
2412
+ if (groupedBsv20.length > 0 || unparsedBsv20 > 0)
2413
+ t.push({
2414
+ id: "bsv20",
2415
+ label: "BSV-20",
2416
+ count: groupedBsv20.reduce((n, tok) => n + tok.outputs.length, 0)
2417
+ });
2332
2418
  if (assets.bsv21Tokens.length > 0)
2333
- t.push({ id: "bsv21", label: "BSV-21", count: assets.bsv21Tokens.length });
2334
- if (assets.bsv20Tokens.length > 0)
2335
- t.push({ id: "bsv20", label: "BSV-20", count: assets.bsv20Tokens.length });
2419
+ t.push({
2420
+ id: "bsv21",
2421
+ label: "BSV-21",
2422
+ count: assets.bsv21Tokens.reduce((n, tok) => n + tok.outputs.length, 0)
2423
+ });
2336
2424
  if (assets.locked.length > 0)
2337
2425
  t.push({ id: "locks", label: "Locks", count: assets.locked.length });
2338
2426
  if (assets.run.length > 0)
2339
2427
  t.push({ id: "run", label: "RUN", count: assets.run.length });
2340
2428
  return t;
2341
- }, [assets]);
2429
+ }, [assets, groupedBsv20, unparsedBsv20]);
2342
2430
  const handleToggleOrdinal = useCallback2((outpoint) => {
2343
2431
  setSelectedOrdinals((prev) => {
2344
2432
  const next = new Set(prev);
@@ -2400,17 +2488,18 @@ function SweepApp({
2400
2488
  ];
2401
2489
  const result = await scanAddresses(addresses, (p) => setScanProgress(p.detail ?? p.phase));
2402
2490
  setAssets(result);
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;
2491
+ const grouped = groupBsv20Tokens2(result.bsv20Tokens);
2492
+ const total = result.funding.length + result.ordinals.length + result.opnsNames.length + result.bsv21Tokens.reduce((n, t) => n + t.outputs.length, 0) + grouped.reduce((n, t) => n + t.outputs.length, 0) + result.locked.length + result.run.length;
2404
2493
  if (total === 0)
2405
2494
  toast.info("No assets found at legacy addresses");
2406
2495
  if (result.ordinals.length > 0)
2407
2496
  setActiveTab("ordinals");
2408
2497
  else if (result.opnsNames.length > 0)
2409
2498
  setActiveTab("opns");
2499
+ else if (grouped.length > 0)
2500
+ setActiveTab("bsv20");
2410
2501
  else if (result.bsv21Tokens.length > 0)
2411
2502
  setActiveTab("bsv21");
2412
- else if (result.bsv20Tokens.length > 0)
2413
- setActiveTab("bsv20");
2414
2503
  else if (result.locked.length > 0)
2415
2504
  setActiveTab("locks");
2416
2505
  } catch (e) {
@@ -2426,10 +2515,11 @@ function SweepApp({
2426
2515
  }, [initialKeys, handleScan]);
2427
2516
  const runOperation = useCallback2(async (label, op) => {
2428
2517
  setSweeping(true);
2429
- setSweepProgress(label + "...");
2518
+ setSweepProgress(`${label}...`);
2430
2519
  try {
2431
2520
  const txid = await op();
2432
- addTx(label, txid);
2521
+ if (txid)
2522
+ addTx(label, txid);
2433
2523
  toast.success(label);
2434
2524
  await refreshAssets();
2435
2525
  } catch (e) {
@@ -2465,18 +2555,12 @@ function SweepApp({
2465
2555
  keys: keyMap,
2466
2556
  funding: getSelectedFunding(),
2467
2557
  ordinals: [],
2468
- listings: assets.listings,
2469
2558
  amount: sweepAmount ?? undefined,
2470
2559
  onProgress: setSweepProgress
2471
2560
  });
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();
2561
+ if (result.errors.length > 0)
2477
2562
  throw new Error(result.errors[0]);
2478
- }
2479
- return result.bsvTxid ?? result.listingTxids[0] ?? "";
2563
+ return result.bsvTxid ?? "";
2480
2564
  });
2481
2565
  }, [
2482
2566
  resolveWallet,
@@ -2485,43 +2569,7 @@ function SweepApp({
2485
2569
  sweepAmount,
2486
2570
  getSelectedFunding,
2487
2571
  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
2572
+ keyMap
2525
2573
  ]);
2526
2574
  const handleSendBsv = useCallback2(async (destination) => {
2527
2575
  if (!legacyKeys || !assets)
@@ -2704,11 +2752,65 @@ function SweepApp({
2704
2752
  token,
2705
2753
  onProgress: setSweepProgress
2706
2754
  });
2755
+ for (const txid of result.txids.slice(0, -1))
2756
+ addTx("BSV-21", txid);
2707
2757
  if (result.error)
2708
2758
  throw new Error(result.error);
2709
2759
  return result.txid ?? "";
2710
2760
  });
2711
- }, [resolveWallet, assets, keyMap, runOperation]);
2761
+ }, [resolveWallet, assets, keyMap, runOperation, addTx]);
2762
+ const handleSweepBsv20Token = useCallback2(async (tick) => {
2763
+ const wallet = resolveWallet();
2764
+ if (!wallet || !assets)
2765
+ return;
2766
+ const token = groupedBsv20.find((t) => t.tick === tick);
2767
+ if (!token)
2768
+ return;
2769
+ await runOperation(`Sweep ${token.tick}`, async () => {
2770
+ const result = await sweepBsv20Token({
2771
+ wallet,
2772
+ keys: keyMap,
2773
+ token,
2774
+ onProgress: setSweepProgress
2775
+ });
2776
+ if (result.error)
2777
+ throw new Error(result.error);
2778
+ return result.txid ?? "";
2779
+ });
2780
+ }, [resolveWallet, assets, groupedBsv20, keyMap, runOperation]);
2781
+ const handleSweepAll = useCallback2(async () => {
2782
+ const wallet = resolveWallet();
2783
+ if (!wallet || !legacyKeys || !assets)
2784
+ return;
2785
+ await runOperation("Sweep all", async () => {
2786
+ const result = await sweepAllClasses({
2787
+ wallet,
2788
+ keys: keyMap,
2789
+ assets,
2790
+ amount: sweepAmount ?? undefined,
2791
+ onProgress: setSweepProgress
2792
+ });
2793
+ if (result.bsvTxid)
2794
+ addTx("BSV", result.bsvTxid);
2795
+ for (const txid of result.ordinalTxids)
2796
+ addTx("Ordinals", txid);
2797
+ for (const txid of result.bsv20Txids)
2798
+ addTx("BSV-20", txid);
2799
+ for (const txid of result.bsv21Txids)
2800
+ addTx("BSV-21", txid);
2801
+ if (result.errors.length > 0)
2802
+ throw new Error(result.errors[0]);
2803
+ return result.bsvTxid ?? result.ordinalTxids.at(-1) ?? result.bsv20Txids.at(-1) ?? result.bsv21Txids.at(-1) ?? "";
2804
+ });
2805
+ }, [
2806
+ resolveWallet,
2807
+ legacyKeys,
2808
+ assets,
2809
+ keyMap,
2810
+ sweepAmount,
2811
+ runOperation,
2812
+ addTx
2813
+ ]);
2712
2814
  return /* @__PURE__ */ jsxs6("div", {
2713
2815
  className: "min-h-screen bg-background text-foreground",
2714
2816
  children: [
@@ -2748,6 +2850,13 @@ function SweepApp({
2748
2850
  assets && !sweeping && /* @__PURE__ */ jsxs6("div", {
2749
2851
  className: "space-y-3",
2750
2852
  children: [
2853
+ /* @__PURE__ */ jsx11(Button, {
2854
+ className: "w-full",
2855
+ disabled: !walletConnected,
2856
+ onClick: handleSweepAll,
2857
+ title: walletConnected ? undefined : "Connect BRC-100 wallet to sweep",
2858
+ children: "Sweep all to wallet"
2859
+ }),
2751
2860
  /* @__PURE__ */ jsx11(FundingSection, {
2752
2861
  funding: assets.funding,
2753
2862
  totalBsv: assets.totalBsv,
@@ -2757,11 +2866,6 @@ function SweepApp({
2757
2866
  onSend: sweepOnly ? undefined : handleSendBsv,
2758
2867
  walletConnected
2759
2868
  }),
2760
- /* @__PURE__ */ jsx11(ListingsSection, {
2761
- listings: assets.listings,
2762
- walletConnected,
2763
- onCancel: handleCancelListings
2764
- }),
2765
2869
  tabs.length > 0 && /* @__PURE__ */ jsxs6(Tabs, {
2766
2870
  value: activeTab,
2767
2871
  onValueChange: (v) => setActiveTab(v),
@@ -2811,6 +2915,15 @@ function SweepApp({
2811
2915
  walletConnected
2812
2916
  })
2813
2917
  }),
2918
+ /* @__PURE__ */ jsx11(TabsContent, {
2919
+ value: "bsv20",
2920
+ children: /* @__PURE__ */ jsx11(Bsv20Section, {
2921
+ tokens: groupedBsv20,
2922
+ unparsedCount: unparsedBsv20,
2923
+ onSweep: handleSweepBsv20Token,
2924
+ walletConnected
2925
+ })
2926
+ }),
2814
2927
  /* @__PURE__ */ jsx11(TabsContent, {
2815
2928
  value: "bsv21",
2816
2929
  children: /* @__PURE__ */ jsx11(Bsv21Section, {
@@ -2819,12 +2932,6 @@ function SweepApp({
2819
2932
  walletConnected
2820
2933
  })
2821
2934
  }),
2822
- /* @__PURE__ */ jsx11(TabsContent, {
2823
- value: "bsv20",
2824
- children: /* @__PURE__ */ jsx11(Bsv20Section, {
2825
- tokens: assets.bsv20Tokens
2826
- })
2827
- }),
2828
2935
  /* @__PURE__ */ jsx11(TabsContent, {
2829
2936
  value: "locks",
2830
2937
  children: /* @__PURE__ */ jsx11(LockedSection, {
@@ -2969,7 +3076,6 @@ export {
2969
3076
  ConnectWallet,
2970
3077
  FundingSection,
2971
3078
  Input,
2972
- ListingsSection,
2973
3079
  LockedSection,
2974
3080
  OpnsSection,
2975
3081
  OrdinalsSection,
@@ -3003,5 +3109,6 @@ export {
3003
3109
  legacySendOrdinals,
3004
3110
  scanAddress,
3005
3111
  scanAddresses,
3112
+ sweepAllClasses,
3006
3113
  truncate
3007
3114
  };