@1sat/sweep-ui 0.0.10 → 0.0.12

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,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAI5D,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,aAAa,2CA4QrG"}
1
+ {"version":3,"file":"SweepApp.d.ts","sourceRoot":"","sources":["../../src/components/SweepApp.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAI5D,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE,aAAa,2CA8QrG"}
@@ -29,4 +29,7 @@ export declare function Bsv20Section({ tokens }: {
29
29
  export declare function LockedSection({ locked }: {
30
30
  locked: IndexedOutput[];
31
31
  }): import("react/jsx-runtime").JSX.Element | null;
32
+ export declare function RunSection({ run }: {
33
+ run: IndexedOutput[];
34
+ }): import("react/jsx-runtime").JSX.Element | null;
32
35
  //# sourceMappingURL=asset-preview.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"asset-preview.d.ts","sourceRoot":"","sources":["../../src/components/asset-preview.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA8CjD,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE;IACzH,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,eAAe,EAAE,OAAO,CAAC;CACpN,kDAqCA;AAED,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE;IAC/I,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,eAAe,EAAE,OAAO,CAAC;CACjQ,kDAsDA;AA0BD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,kDAsBlE;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,kDAmBnE;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,kDAapE"}
1
+ {"version":3,"file":"asset-preview.d.ts","sourceRoot":"","sources":["../../src/components/asset-preview.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA8CjD,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE;IACzH,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,eAAe,EAAE,OAAO,CAAC;CACpN,kDAqCA;AAED,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE;IAC/I,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAAC,eAAe,EAAE,OAAO,CAAC;CACjQ,kDAsDA;AA0BD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,kDAsBlE;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,kDAmBnE;AAED,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,EAAE,CAAA;CAAE,kDAapE;AAED,wBAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,aAAa,EAAE,CAAA;CAAE,kDAc3D"}
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 } from "./components/asset-preview";
4
+ export { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, 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,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AACxH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAG5D,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzH,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACpH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC1J,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjH,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG1E,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACpI,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAG5D,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACzH,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACpH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC1J,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACjH,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG1E,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -341,6 +341,7 @@ import {
341
341
 
342
342
  // src/lib/scanner.ts
343
343
  import { PrivateKey } from "@bsv/sdk";
344
+ import { parseOutpoint } from "@1sat/utils";
344
345
 
345
346
  // src/lib/services.ts
346
347
  import { OneSatServices } from "@1sat/client";
@@ -361,6 +362,7 @@ function getServices() {
361
362
  }
362
363
 
363
364
  // src/lib/scanner.ts
365
+ var RUN_PREFIX = Uint8Array.from([0, 106, 3, 114, 117, 110]);
364
366
  function deriveAddress(wif) {
365
367
  return PrivateKey.fromWif(wif.trim()).toPublicKey().toAddress();
366
368
  }
@@ -465,14 +467,28 @@ async function categorizeOutputs(outputs) {
465
467
  funding.push(out);
466
468
  }
467
469
  }
470
+ const run = [];
471
+ const cleanFunding = [];
472
+ if (funding.length > 0) {
473
+ const runTxids = await detectRunTransactions(funding);
474
+ for (const f of funding) {
475
+ const { txid } = parseOutpoint(f.outpoint);
476
+ if (runTxids.has(txid)) {
477
+ run.push(f);
478
+ } else {
479
+ cleanFunding.push(f);
480
+ }
481
+ }
482
+ }
468
483
  return {
469
- funding,
484
+ funding: cleanFunding,
470
485
  ordinals: rawOrdinals.map(enrichOrdinal),
471
486
  opnsNames: opnsRaw.map(enrichOrdinal),
472
487
  bsv21Tokens: await groupBsv21Tokens(bsv21Raw),
473
488
  bsv20Tokens,
474
489
  locked,
475
- totalBsv: funding.reduce((sum, o) => sum + (o.satoshis ?? 0), 0)
490
+ run,
491
+ totalBsv: cleanFunding.reduce((sum, o) => sum + (o.satoshis ?? 0), 0)
476
492
  };
477
493
  }
478
494
  async function scanAddress(address, onProgress) {
@@ -513,9 +529,40 @@ async function scanAddresses(addresses, onProgress) {
513
529
  bsv21Tokens: allResults.flatMap((r) => r.bsv21Tokens),
514
530
  bsv20Tokens: allResults.flatMap((r) => r.bsv20Tokens),
515
531
  locked: allResults.flatMap((r) => r.locked),
532
+ run: allResults.flatMap((r) => r.run),
516
533
  totalBsv: allResults.reduce((sum, r) => sum + r.totalBsv, 0)
517
534
  };
518
535
  }
536
+ async function detectRunTransactions(funding) {
537
+ const services = getServices();
538
+ const txids = [...new Set(funding.map((f) => parseOutpoint(f.outpoint).txid))];
539
+ const runTxids = new Set;
540
+ for (const txid of txids) {
541
+ try {
542
+ const beef = await services.getBeefForTxid(txid);
543
+ const beefTx = beef.findTxid(txid);
544
+ if (!beefTx?.tx)
545
+ continue;
546
+ for (const output of beefTx.tx.outputs) {
547
+ const script = output.lockingScript?.toBinary();
548
+ if (script && hasRunPrefix(script)) {
549
+ runTxids.add(txid);
550
+ break;
551
+ }
552
+ }
553
+ } catch {}
554
+ }
555
+ return runTxids;
556
+ }
557
+ function hasRunPrefix(script) {
558
+ if (script.length < RUN_PREFIX.length)
559
+ return false;
560
+ for (let i = 0;i < RUN_PREFIX.length; i++) {
561
+ if (script[i] !== RUN_PREFIX[i])
562
+ return false;
563
+ }
564
+ return true;
565
+ }
519
566
 
520
567
  // src/components/wif-input.tsx
521
568
  import { deriveIdentityKey } from "@1sat/utils";
@@ -1514,6 +1561,39 @@ function LockedSection({ locked }) {
1514
1561
  ]
1515
1562
  });
1516
1563
  }
1564
+ function RunSection({ run }) {
1565
+ if (run.length === 0)
1566
+ return null;
1567
+ const totalSats = run.reduce((sum, o) => sum + (o.satoshis ?? 0), 0);
1568
+ return /* @__PURE__ */ jsxs3("div", {
1569
+ className: "border border-orange-500/20 bg-orange-500/5 p-4 rounded-lg",
1570
+ children: [
1571
+ /* @__PURE__ */ jsxs3("div", {
1572
+ className: "flex items-center gap-2 mb-2",
1573
+ children: [
1574
+ /* @__PURE__ */ jsx8("span", {
1575
+ className: "h-2 w-2 rounded-full bg-orange-500"
1576
+ }),
1577
+ /* @__PURE__ */ jsx8("span", {
1578
+ className: "text-sm font-semibold text-orange-500",
1579
+ children: "RUN Protocol Tokens"
1580
+ })
1581
+ ]
1582
+ }),
1583
+ /* @__PURE__ */ jsxs3("p", {
1584
+ className: "text-xs text-muted-foreground",
1585
+ children: [
1586
+ run.length,
1587
+ " output",
1588
+ run.length !== 1 ? "s" : "",
1589
+ " (",
1590
+ totalSats.toLocaleString(),
1591
+ " sats). These are RUN protocol token outputs and cannot be swept as BSV."
1592
+ ]
1593
+ })
1594
+ ]
1595
+ });
1596
+ }
1517
1597
 
1518
1598
  // src/components/opns-section.tsx
1519
1599
  import { useState as useState4, useEffect } from "react";
@@ -1881,7 +1961,7 @@ async function executeSweep(params) {
1881
1961
  }
1882
1962
 
1883
1963
  // src/lib/legacy-send.ts
1884
- import { parseOutpoint } from "@1sat/utils";
1964
+ import { parseOutpoint as parseOutpoint2 } from "@1sat/utils";
1885
1965
  import { MAP_PREFIX } from "@1sat/types";
1886
1966
  import { OP, P2PKH, PrivateKey as PrivateKey2, Script, Transaction, Utils } from "@bsv/sdk";
1887
1967
  async function fetchSourceTx(txid) {
@@ -1928,7 +2008,7 @@ async function legacySendBsv(params) {
1928
2008
  const p2pkh = new P2PKH;
1929
2009
  const tx = new Transaction;
1930
2010
  for (const utxo of funding) {
1931
- const { txid, vout } = parseOutpoint(utxo.outpoint);
2011
+ const { txid, vout } = parseOutpoint2(utxo.outpoint);
1932
2012
  const key = keyForOutput(utxo, keyMap, payKey);
1933
2013
  tx.addInput({
1934
2014
  sourceTXID: txid,
@@ -1976,7 +2056,7 @@ async function legacySendOrdinals(params) {
1976
2056
  const p2pkh = new P2PKH;
1977
2057
  const tx = new Transaction;
1978
2058
  for (const ord of ordinals) {
1979
- const { txid, vout } = parseOutpoint(ord.outpoint);
2059
+ const { txid, vout } = parseOutpoint2(ord.outpoint);
1980
2060
  const key = keyForOutput(ord, keyMap, payKey);
1981
2061
  tx.addInput({
1982
2062
  sourceTXID: txid,
@@ -1993,7 +2073,7 @@ async function legacySendOrdinals(params) {
1993
2073
  });
1994
2074
  }
1995
2075
  for (const utxo of funding) {
1996
- const { txid, vout } = parseOutpoint(utxo.outpoint);
2076
+ const { txid, vout } = parseOutpoint2(utxo.outpoint);
1997
2077
  const key = keyForOutput(utxo, keyMap, payKey);
1998
2078
  tx.addInput({
1999
2079
  sourceTXID: txid,
@@ -2026,7 +2106,7 @@ async function legacyBurnOrdinals(params) {
2026
2106
  const p2pkh = new P2PKH;
2027
2107
  const tx = new Transaction;
2028
2108
  for (const ord of ordinals) {
2029
- const { txid, vout } = parseOutpoint(ord.outpoint);
2109
+ const { txid, vout } = parseOutpoint2(ord.outpoint);
2030
2110
  const key = keyForOutput(ord, keyMap, payKey);
2031
2111
  tx.addInput({
2032
2112
  sourceTXID: txid,
@@ -2037,7 +2117,7 @@ async function legacyBurnOrdinals(params) {
2037
2117
  });
2038
2118
  }
2039
2119
  for (const utxo of funding) {
2040
- const { txid, vout } = parseOutpoint(utxo.outpoint);
2120
+ const { txid, vout } = parseOutpoint2(utxo.outpoint);
2041
2121
  const key = keyForOutput(utxo, keyMap, payKey);
2042
2122
  tx.addInput({
2043
2123
  sourceTXID: txid,
@@ -2113,6 +2193,8 @@ function SweepApp({ legacyKeys: initialKeys, wallet: externalWallet, sweepOnly }
2113
2193
  t.push({ id: "bsv20", label: "BSV-20", count: assets.bsv20Tokens.length });
2114
2194
  if (assets.locked.length > 0)
2115
2195
  t.push({ id: "locks", label: "Locks", count: assets.locked.length });
2196
+ if (assets.run.length > 0)
2197
+ t.push({ id: "run", label: "RUN", count: assets.run.length });
2116
2198
  return t;
2117
2199
  }, [assets]);
2118
2200
  const handleToggleOrdinal = useCallback2((outpoint) => {
@@ -2166,7 +2248,7 @@ function SweepApp({ legacyKeys: initialKeys, wallet: externalWallet, sweepOnly }
2166
2248
  const addresses = [...new Set([deriveAddress(keys.payPk), deriveAddress(keys.ordPk), ...keys.identityPk ? [deriveAddress(keys.identityPk)] : []])];
2167
2249
  const result = await scanAddresses(addresses, (p) => setScanProgress(p.detail ?? p.phase));
2168
2250
  setAssets(result);
2169
- 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;
2251
+ 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;
2170
2252
  if (total === 0)
2171
2253
  toast.info("No assets found at legacy addresses");
2172
2254
  if (result.ordinals.length > 0)
@@ -2424,6 +2506,12 @@ function SweepApp({ legacyKeys: initialKeys, wallet: externalWallet, sweepOnly }
2424
2506
  children: /* @__PURE__ */ jsx11(LockedSection, {
2425
2507
  locked: assets.locked
2426
2508
  })
2509
+ }),
2510
+ /* @__PURE__ */ jsx11(TabsContent, {
2511
+ value: "run",
2512
+ children: /* @__PURE__ */ jsx11(RunSection, {
2513
+ run: assets.run
2514
+ })
2427
2515
  })
2428
2516
  ]
2429
2517
  })
@@ -2567,6 +2655,7 @@ export {
2567
2655
  Tabs,
2568
2656
  SweepProgress,
2569
2657
  SweepApp,
2658
+ RunSection,
2570
2659
  OrdinalsSection,
2571
2660
  OpnsSection,
2572
2661
  LockedSection,
@@ -21,6 +21,7 @@ export interface ScannedAssets {
21
21
  bsv21Tokens: TokenBalance[];
22
22
  bsv20Tokens: IndexedOutput[];
23
23
  locked: IndexedOutput[];
24
+ run: IndexedOutput[];
24
25
  totalBsv: number;
25
26
  }
26
27
  export interface ScanProgress {
@@ -1 +1 @@
1
- {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAuID,wBAAsB,WAAW,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CA0BxB;AAED,wBAAsB,aAAa,CAClC,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CAkBxB"}
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/lib/scanner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAOjD,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,GAAG,EAAE,aAAa,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAwJD,wBAAsB,WAAW,CAChC,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CA0BxB;AAED,wBAAsB,aAAa,CAClC,SAAS,EAAE,MAAM,EAAE,EACnB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,GACpC,OAAO,CAAC,aAAa,CAAC,CAmBxB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/sweep-ui",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "Sweep UI components for migrating legacy BSV assets",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -19,10 +19,10 @@
19
19
  "keywords": ["1sat", "bsv", "ordinals", "sweep", "migration", "react"],
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@1sat/actions": "0.0.69",
23
- "@1sat/client": "0.0.17",
22
+ "@1sat/actions": "0.0.73",
23
+ "@1sat/client": "0.0.18",
24
24
  "@1sat/connect": "0.0.27",
25
- "@1sat/sweep-ui": "0.0.10",
25
+ "@1sat/sweep-ui": "0.0.12",
26
26
  "@1sat/types": "0.0.14",
27
27
  "@1sat/utils": "0.0.12",
28
28
  "bitcoin-backup": "^0.0.11",
@@ -4,7 +4,7 @@ import { Badge } from "./ui/badge";
4
4
  import { Tabs, TabsList, TabsTrigger, TabsContent } from "./ui/tabs";
5
5
  import { ConnectWallet } from "./connect-wallet";
6
6
  import { WifInput } from "./wif-input";
7
- import { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, LockedSection } from "./asset-preview";
7
+ import { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, LockedSection, RunSection } from "./asset-preview";
8
8
  import { OpnsSection } from "./opns-section";
9
9
  import { TxHistory, type TxRecord } from "./tx-history";
10
10
  import { deriveAddress, scanAddresses, type ScannedAssets } from "../lib/scanner";
@@ -14,7 +14,7 @@ import { getWallet } from "../lib/wallet";
14
14
  import type { LegacyKeys } from "../types";
15
15
  import { PrivateKey, type WalletInterface } from "@bsv/sdk";
16
16
 
17
- type TabId = "ordinals" | "opns" | "bsv21" | "bsv20" | "locks";
17
+ type TabId = "ordinals" | "opns" | "bsv21" | "bsv20" | "locks" | "run";
18
18
 
19
19
  export interface SweepAppProps {
20
20
  legacyKeys?: LegacyKeys;
@@ -67,6 +67,7 @@ export function SweepApp({ legacyKeys: initialKeys, wallet: externalWallet, swee
67
67
  if (assets.bsv21Tokens.length > 0) t.push({ id: "bsv21", label: "BSV-21", count: assets.bsv21Tokens.length });
68
68
  if (assets.bsv20Tokens.length > 0) t.push({ id: "bsv20", label: "BSV-20", count: assets.bsv20Tokens.length });
69
69
  if (assets.locked.length > 0) t.push({ id: "locks", label: "Locks", count: assets.locked.length });
70
+ if (assets.run.length > 0) t.push({ id: "run", label: "RUN", count: assets.run.length });
70
71
  return t;
71
72
  }, [assets]);
72
73
 
@@ -105,7 +106,7 @@ export function SweepApp({ legacyKeys: initialKeys, wallet: externalWallet, swee
105
106
  const result = await scanAddresses(addresses, (p) => setScanProgress(p.detail ?? p.phase));
106
107
  setAssets(result);
107
108
 
108
- 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;
109
+ 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;
109
110
  if (total === 0) toast.info("No assets found at legacy addresses");
110
111
 
111
112
  if (result.ordinals.length > 0) setActiveTab("ordinals");
@@ -281,6 +282,7 @@ export function SweepApp({ legacyKeys: initialKeys, wallet: externalWallet, swee
281
282
  <TabsContent value="bsv21"><Bsv21Section tokens={assets.bsv21Tokens} /></TabsContent>
282
283
  <TabsContent value="bsv20"><Bsv20Section tokens={assets.bsv20Tokens} /></TabsContent>
283
284
  <TabsContent value="locks"><LockedSection locked={assets.locked} /></TabsContent>
285
+ <TabsContent value="run"><RunSection run={assets.run} /></TabsContent>
284
286
  </Tabs>
285
287
  )}
286
288
  </div>
@@ -232,3 +232,19 @@ export function LockedSection({ locked }: { locked: IndexedOutput[] }) {
232
232
  </div>
233
233
  );
234
234
  }
235
+
236
+ export function RunSection({ run }: { run: IndexedOutput[] }) {
237
+ if (run.length === 0) return null;
238
+ const totalSats = run.reduce((sum, o) => sum + (o.satoshis ?? 0), 0);
239
+ return (
240
+ <div className="border border-orange-500/20 bg-orange-500/5 p-4 rounded-lg">
241
+ <div className="flex items-center gap-2 mb-2">
242
+ <span className="h-2 w-2 rounded-full bg-orange-500" />
243
+ <span className="text-sm font-semibold text-orange-500">RUN Protocol Tokens</span>
244
+ </div>
245
+ <p className="text-xs text-muted-foreground">
246
+ {run.length} output{run.length !== 1 ? "s" : ""} ({totalSats.toLocaleString()} sats). These are RUN protocol token outputs and cannot be swept as BSV.
247
+ </p>
248
+ </div>
249
+ );
250
+ }
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ export { SweepApp, type SweepAppProps } from "./components/SweepApp";
4
4
  // Feature components
5
5
  export { ConnectWallet } from "./components/connect-wallet";
6
6
  export { WifInput } from "./components/wif-input";
7
- export { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, LockedSection } from "./components/asset-preview";
7
+ export { FundingSection, OrdinalsSection, Bsv21Section, Bsv20Section, LockedSection, RunSection } from "./components/asset-preview";
8
8
  export { OpnsSection } from "./components/opns-section";
9
9
  export { TxHistory, type TxRecord } from "./components/tx-history";
10
10
  export { SweepProgress } from "./components/sweep-progress";
@@ -1,7 +1,11 @@
1
1
  import { PrivateKey } from "@bsv/sdk";
2
2
  import type { IndexedOutput } from "@1sat/types";
3
+ import { parseOutpoint } from "@1sat/utils";
3
4
  import { getServices } from "./services";
4
5
 
6
+ /** RUN protocol OP_RETURN prefix: OP_FALSE OP_RETURN OP_PUSH3 "run" */
7
+ const RUN_PREFIX = Uint8Array.from([0x00, 0x6a, 0x03, 0x72, 0x75, 0x6e]);
8
+
5
9
  export interface EnrichedOrdinal extends IndexedOutput {
6
10
  origin?: string;
7
11
  contentType?: string;
@@ -26,6 +30,7 @@ export interface ScannedAssets {
26
30
  bsv21Tokens: TokenBalance[];
27
31
  bsv20Tokens: IndexedOutput[];
28
32
  locked: IndexedOutput[];
33
+ run: IndexedOutput[];
29
34
  totalBsv: number;
30
35
  }
31
36
 
@@ -160,14 +165,31 @@ async function categorizeOutputs(outputs: IndexedOutput[]): Promise<ScannedAsset
160
165
  }
161
166
  }
162
167
 
168
+ // Check funding outputs for RUN token transactions
169
+ const run: IndexedOutput[] = [];
170
+ const cleanFunding: IndexedOutput[] = [];
171
+
172
+ if (funding.length > 0) {
173
+ const runTxids = await detectRunTransactions(funding);
174
+ for (const f of funding) {
175
+ const { txid } = parseOutpoint(f.outpoint);
176
+ if (runTxids.has(txid)) {
177
+ run.push(f);
178
+ } else {
179
+ cleanFunding.push(f);
180
+ }
181
+ }
182
+ }
183
+
163
184
  return {
164
- funding,
185
+ funding: cleanFunding,
165
186
  ordinals: rawOrdinals.map(enrichOrdinal),
166
187
  opnsNames: opnsRaw.map(enrichOrdinal),
167
188
  bsv21Tokens: await groupBsv21Tokens(bsv21Raw),
168
189
  bsv20Tokens,
169
190
  locked,
170
- totalBsv: funding.reduce((sum, o) => sum + (o.satoshis ?? 0), 0),
191
+ run,
192
+ totalBsv: cleanFunding.reduce((sum, o) => sum + (o.satoshis ?? 0), 0),
171
193
  };
172
194
  }
173
195
 
@@ -221,6 +243,45 @@ export async function scanAddresses(
221
243
  bsv21Tokens: allResults.flatMap((r) => r.bsv21Tokens),
222
244
  bsv20Tokens: allResults.flatMap((r) => r.bsv20Tokens),
223
245
  locked: allResults.flatMap((r) => r.locked),
246
+ run: allResults.flatMap((r) => r.run),
224
247
  totalBsv: allResults.reduce((sum, r) => sum + r.totalBsv, 0),
225
248
  };
226
249
  }
250
+
251
+ /**
252
+ * Check source transactions for the RUN protocol OP_RETURN pattern.
253
+ * Returns the set of txids that contain a RUN OP_RETURN output.
254
+ */
255
+ async function detectRunTransactions(funding: IndexedOutput[]): Promise<Set<string>> {
256
+ const services = getServices();
257
+ const txids = [...new Set(funding.map((f) => parseOutpoint(f.outpoint).txid))];
258
+ const runTxids = new Set<string>();
259
+
260
+ for (const txid of txids) {
261
+ try {
262
+ const beef = await services.getBeefForTxid(txid);
263
+ const beefTx = beef.findTxid(txid);
264
+ if (!beefTx?.tx) continue;
265
+
266
+ for (const output of beefTx.tx.outputs) {
267
+ const script = output.lockingScript?.toBinary();
268
+ if (script && hasRunPrefix(script)) {
269
+ runTxids.add(txid);
270
+ break;
271
+ }
272
+ }
273
+ } catch {
274
+ // If we can't fetch the tx, leave the output in funding
275
+ }
276
+ }
277
+
278
+ return runTxids;
279
+ }
280
+
281
+ function hasRunPrefix(script: number[]): boolean {
282
+ if (script.length < RUN_PREFIX.length) return false;
283
+ for (let i = 0; i < RUN_PREFIX.length; i++) {
284
+ if (script[i] !== RUN_PREFIX[i]) return false;
285
+ }
286
+ return true;
287
+ }