@1sat/sweep-ui 0.0.10 → 0.0.11
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 +3 -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 +98 -9
- package/dist/lib/scanner.d.ts +1 -0
- package/dist/lib/scanner.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/components/SweepApp.tsx +5 -3
- package/src/components/asset-preview.tsx +16 -0
- package/src/index.ts +1 -1
- package/src/lib/scanner.ts +63 -2
|
@@ -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,
|
|
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";
|
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,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;
|
|
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
|
-
|
|
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 } =
|
|
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 } =
|
|
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 } =
|
|
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 } =
|
|
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 } =
|
|
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,
|
package/dist/lib/scanner.d.ts
CHANGED
|
@@ -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;
|
|
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.
|
|
3
|
+
"version": "0.0.11",
|
|
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.
|
|
22
|
+
"@1sat/actions": "0.0.70",
|
|
23
23
|
"@1sat/client": "0.0.17",
|
|
24
24
|
"@1sat/connect": "0.0.27",
|
|
25
|
-
"@1sat/sweep-ui": "0.0.
|
|
25
|
+
"@1sat/sweep-ui": "0.0.11",
|
|
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";
|
package/src/lib/scanner.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|