@1sat/sweep-ui 0.0.19 → 0.0.21
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 +3 -3
- package/dist/components/SweepApp.d.ts.map +1 -1
- package/dist/components/asset-preview.d.ts +5 -5
- package/dist/components/asset-preview.d.ts.map +1 -1
- package/dist/components/connect-wallet.d.ts +1 -1
- package/dist/components/connect-wallet.d.ts.map +1 -1
- package/dist/components/opns-section.d.ts +2 -2
- package/dist/components/opns-section.d.ts.map +1 -1
- package/dist/components/sweep-progress.d.ts +1 -1
- package/dist/components/sweep-progress.d.ts.map +1 -1
- package/dist/components/tx-history.d.ts.map +1 -1
- package/dist/components/ui/badge.d.ts +3 -3
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/button.d.ts +3 -3
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts +9 -9
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/input.d.ts +2 -2
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/tabs.d.ts +5 -5
- package/dist/components/ui/tabs.d.ts.map +1 -1
- package/dist/components/wif-input.d.ts +1 -1
- package/dist/components/wif-input.d.ts.map +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1911 -1757
- package/dist/lib/legacy-send.d.ts +2 -2
- package/dist/lib/legacy-send.d.ts.map +1 -1
- package/dist/lib/scanner.d.ts +3 -3
- package/dist/lib/scanner.d.ts.map +1 -1
- package/dist/lib/services.d.ts +1 -1
- package/dist/lib/services.d.ts.map +1 -1
- package/dist/lib/sweeper.d.ts +3 -3
- package/dist/lib/sweeper.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/wallet.d.ts +2 -2
- package/dist/lib/wallet.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +53 -44
- package/src/components/SweepApp.tsx +480 -222
- package/src/components/asset-preview.tsx +380 -97
- package/src/components/connect-wallet.tsx +50 -25
- package/src/components/opns-section.tsx +167 -60
- package/src/components/sweep-progress.tsx +40 -17
- package/src/components/tx-history.tsx +30 -17
- package/src/components/ui/badge.tsx +17 -14
- package/src/components/ui/button.tsx +26 -22
- package/src/components/ui/card.tsx +76 -17
- package/src/components/ui/input.tsx +7 -7
- package/src/components/ui/tabs.tsx +51 -12
- package/src/components/wif-input.tsx +243 -135
- package/src/index.ts +54 -19
- package/src/lib/legacy-send.ts +110 -106
- package/src/lib/scanner.ts +45 -40
- package/src/lib/services.ts +11 -9
- package/src/lib/sweeper.ts +67 -54
- package/src/lib/utils.ts +11 -11
- package/src/lib/wallet.ts +16 -13
- package/src/types.ts +3 -3
package/src/lib/sweeper.ts
CHANGED
|
@@ -2,80 +2,93 @@ import {
|
|
|
2
2
|
createContext,
|
|
3
3
|
prepareSweepInputs,
|
|
4
4
|
sweepBsv,
|
|
5
|
-
sweepOrdinals,
|
|
6
5
|
sweepBsv21,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import type {
|
|
11
|
-
import {
|
|
6
|
+
sweepOrdinals,
|
|
7
|
+
} from '@1sat/actions'
|
|
8
|
+
import type { IndexedOutput } from '@1sat/types'
|
|
9
|
+
import type { PrivateKey, WalletInterface } from '@bsv/sdk'
|
|
10
|
+
import type { TokenBalance } from './scanner'
|
|
11
|
+
import { getServices } from './services'
|
|
12
12
|
|
|
13
13
|
export interface SweepResult {
|
|
14
|
-
bsvTxid?: string
|
|
15
|
-
ordinalTxids: string[]
|
|
16
|
-
bsv21Txids: string[]
|
|
17
|
-
errors: string[]
|
|
14
|
+
bsvTxid?: string
|
|
15
|
+
ordinalTxids: string[]
|
|
16
|
+
bsv21Txids: string[]
|
|
17
|
+
errors: string[]
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function getOwner(output: IndexedOutput): string | undefined {
|
|
21
|
-
return output.events?.find((e) => e.startsWith(
|
|
21
|
+
return output.events?.find((e) => e.startsWith('own:'))?.slice(4)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
function buildKeys(
|
|
24
|
+
function buildKeys(
|
|
25
|
+
outputs: IndexedOutput[],
|
|
26
|
+
keyMap: Map<string, PrivateKey>,
|
|
27
|
+
): PrivateKey[] {
|
|
25
28
|
return outputs.map((output) => {
|
|
26
|
-
const owner = getOwner(output)
|
|
27
|
-
const key = owner ? keyMap.get(owner) : undefined
|
|
28
|
-
if (!key)
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const owner = getOwner(output)
|
|
30
|
+
const key = owner ? keyMap.get(owner) : undefined
|
|
31
|
+
if (!key)
|
|
32
|
+
throw new Error(`No key for output ${output.outpoint} (owner: ${owner})`)
|
|
33
|
+
return key
|
|
34
|
+
})
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
/**
|
|
34
38
|
* Sweep BSV funding and ordinals into the connected wallet.
|
|
35
39
|
*/
|
|
36
40
|
export async function executeSweep(params: {
|
|
37
|
-
wallet: WalletInterface
|
|
38
|
-
keys: Map<string, PrivateKey
|
|
39
|
-
funding: IndexedOutput[]
|
|
40
|
-
ordinals: IndexedOutput[]
|
|
41
|
-
amount?: number
|
|
42
|
-
onProgress: (stage: string) => void
|
|
41
|
+
wallet: WalletInterface
|
|
42
|
+
keys: Map<string, PrivateKey>
|
|
43
|
+
funding: IndexedOutput[]
|
|
44
|
+
ordinals: IndexedOutput[]
|
|
45
|
+
amount?: number
|
|
46
|
+
onProgress: (stage: string) => void
|
|
43
47
|
}): Promise<SweepResult> {
|
|
44
|
-
const { wallet, keys, funding, ordinals, amount, onProgress } = params
|
|
45
|
-
const ctx = createContext(wallet, { services: getServices(), chain:
|
|
48
|
+
const { wallet, keys, funding, ordinals, amount, onProgress } = params
|
|
49
|
+
const ctx = createContext(wallet, { services: getServices(), chain: 'main' })
|
|
46
50
|
|
|
47
51
|
const result: SweepResult = {
|
|
48
52
|
ordinalTxids: [],
|
|
49
53
|
bsv21Txids: [],
|
|
50
54
|
errors: [],
|
|
51
|
-
}
|
|
55
|
+
}
|
|
52
56
|
|
|
53
57
|
if (funding.length > 0) {
|
|
54
|
-
onProgress(`Sweeping ${funding.length} BSV UTXOs...`)
|
|
58
|
+
onProgress(`Sweeping ${funding.length} BSV UTXOs...`)
|
|
55
59
|
try {
|
|
56
|
-
const inputs = await prepareSweepInputs(ctx, funding)
|
|
57
|
-
const bsvResult = await sweepBsv.execute(ctx, {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
const inputs = await prepareSweepInputs(ctx, funding)
|
|
61
|
+
const bsvResult = await sweepBsv.execute(ctx, {
|
|
62
|
+
inputs,
|
|
63
|
+
keys: buildKeys(funding, keys),
|
|
64
|
+
amount,
|
|
65
|
+
})
|
|
66
|
+
if (bsvResult.error) result.errors.push(`BSV: ${bsvResult.error}`)
|
|
67
|
+
else if (bsvResult.txid) result.bsvTxid = bsvResult.txid
|
|
60
68
|
} catch (e) {
|
|
61
|
-
result.errors.push(`BSV: ${e instanceof Error ? e.message : String(e)}`)
|
|
69
|
+
result.errors.push(`BSV: ${e instanceof Error ? e.message : String(e)}`)
|
|
62
70
|
}
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
if (ordinals.length > 0) {
|
|
66
|
-
onProgress(`Sweeping ${ordinals.length} ordinals...`)
|
|
74
|
+
onProgress(`Sweeping ${ordinals.length} ordinals...`)
|
|
67
75
|
try {
|
|
68
|
-
const inputs = await prepareSweepInputs(ctx, ordinals)
|
|
69
|
-
const ordResult = await sweepOrdinals.execute(ctx, {
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
const inputs = await prepareSweepInputs(ctx, ordinals)
|
|
77
|
+
const ordResult = await sweepOrdinals.execute(ctx, {
|
|
78
|
+
inputs,
|
|
79
|
+
keys: buildKeys(ordinals, keys),
|
|
80
|
+
})
|
|
81
|
+
if (ordResult.error) result.errors.push(`Ordinals: ${ordResult.error}`)
|
|
82
|
+
else if (ordResult.txid) result.ordinalTxids.push(ordResult.txid)
|
|
72
83
|
} catch (e) {
|
|
73
|
-
result.errors.push(
|
|
84
|
+
result.errors.push(
|
|
85
|
+
`Ordinals: ${e instanceof Error ? e.message : String(e)}`,
|
|
86
|
+
)
|
|
74
87
|
}
|
|
75
88
|
}
|
|
76
89
|
|
|
77
|
-
onProgress(
|
|
78
|
-
return result
|
|
90
|
+
onProgress('Sweep complete')
|
|
91
|
+
return result
|
|
79
92
|
}
|
|
80
93
|
|
|
81
94
|
/**
|
|
@@ -83,29 +96,29 @@ export async function executeSweep(params: {
|
|
|
83
96
|
* Each token requires its own transaction since all inputs must share a tokenId.
|
|
84
97
|
*/
|
|
85
98
|
export async function sweepBsv21Token(params: {
|
|
86
|
-
wallet: WalletInterface
|
|
87
|
-
keys: Map<string, PrivateKey
|
|
88
|
-
token: TokenBalance
|
|
89
|
-
onProgress: (stage: string) => void
|
|
99
|
+
wallet: WalletInterface
|
|
100
|
+
keys: Map<string, PrivateKey>
|
|
101
|
+
token: TokenBalance
|
|
102
|
+
onProgress: (stage: string) => void
|
|
90
103
|
}): Promise<{ txid?: string; error?: string }> {
|
|
91
|
-
const { wallet, keys, token, onProgress } = params
|
|
92
|
-
const ctx = createContext(wallet, { services: getServices(), chain:
|
|
104
|
+
const { wallet, keys, token, onProgress } = params
|
|
105
|
+
const ctx = createContext(wallet, { services: getServices(), chain: 'main' })
|
|
93
106
|
|
|
94
|
-
onProgress(`Sweeping ${token.symbol ?? token.tokenId.slice(0, 8)}...`)
|
|
107
|
+
onProgress(`Sweeping ${token.symbol ?? token.tokenId.slice(0, 8)}...`)
|
|
95
108
|
|
|
96
109
|
try {
|
|
97
110
|
const inputs = token.outputs.map((out) => ({
|
|
98
111
|
outpoint: out.outpoint,
|
|
99
112
|
tokenId: token.tokenId,
|
|
100
|
-
amount: token.amounts.get(out.outpoint) ??
|
|
101
|
-
}))
|
|
113
|
+
amount: token.amounts.get(out.outpoint) ?? '0',
|
|
114
|
+
}))
|
|
102
115
|
|
|
103
|
-
const tokenKeys = buildKeys(token.outputs, keys)
|
|
116
|
+
const tokenKeys = buildKeys(token.outputs, keys)
|
|
104
117
|
|
|
105
|
-
const result = await sweepBsv21.execute(ctx, { inputs, keys: tokenKeys })
|
|
106
|
-
if (result.error) return { error: result.error }
|
|
107
|
-
return { txid: result.txid }
|
|
118
|
+
const result = await sweepBsv21.execute(ctx, { inputs, keys: tokenKeys })
|
|
119
|
+
if (result.error) return { error: result.error }
|
|
120
|
+
return { txid: result.txid }
|
|
108
121
|
} catch (e) {
|
|
109
|
-
return { error: e instanceof Error ? e.message : String(e) }
|
|
122
|
+
return { error: e instanceof Error ? e.message : String(e) }
|
|
110
123
|
}
|
|
111
124
|
}
|
package/src/lib/utils.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { type ClassValue, clsx } from
|
|
2
|
-
import { twMerge } from
|
|
1
|
+
import { type ClassValue, clsx } from 'clsx'
|
|
2
|
+
import { twMerge } from 'tailwind-merge'
|
|
3
3
|
|
|
4
4
|
export function cn(...inputs: ClassValue[]) {
|
|
5
|
-
return twMerge(clsx(inputs))
|
|
5
|
+
return twMerge(clsx(inputs))
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function formatSats(sats: number): string {
|
|
9
|
-
return sats.toLocaleString()
|
|
9
|
+
return sats.toLocaleString()
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function formatTokenAmount(rawAmount: string, decimals: number): string {
|
|
13
|
-
if (decimals === 0) return rawAmount
|
|
14
|
-
const padded = rawAmount.padStart(decimals + 1,
|
|
15
|
-
const intPart = padded.slice(0, -decimals) ||
|
|
16
|
-
const decPart = padded.slice(-decimals).replace(/0+$/,
|
|
17
|
-
return decPart ? `${intPart}.${decPart}` : intPart
|
|
13
|
+
if (decimals === 0) return rawAmount
|
|
14
|
+
const padded = rawAmount.padStart(decimals + 1, '0')
|
|
15
|
+
const intPart = padded.slice(0, -decimals) || '0'
|
|
16
|
+
const decPart = padded.slice(-decimals).replace(/0+$/, '')
|
|
17
|
+
return decPart ? `${intPart}.${decPart}` : intPart
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function truncate(s: string, len = 8): string {
|
|
21
|
-
if (s.length <= len * 2 + 3) return s
|
|
22
|
-
return `${s.slice(0, len)}...${s.slice(-len)}
|
|
21
|
+
if (s.length <= len * 2 + 3) return s
|
|
22
|
+
return `${s.slice(0, len)}...${s.slice(-len)}`
|
|
23
23
|
}
|
package/src/lib/wallet.ts
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
type ConnectWalletResult,
|
|
3
|
+
connectWallet as connect,
|
|
4
|
+
} from '@1sat/connect'
|
|
5
|
+
import type { WalletInterface } from '@bsv/sdk'
|
|
3
6
|
|
|
4
|
-
let connection: ConnectWalletResult | null = null
|
|
7
|
+
let connection: ConnectWalletResult | null = null
|
|
5
8
|
|
|
6
9
|
export async function connectWallet(): Promise<ConnectWalletResult> {
|
|
7
|
-
const result = await connect()
|
|
8
|
-
if (!result) throw new Error(
|
|
9
|
-
connection = result
|
|
10
|
-
return result
|
|
10
|
+
const result = await connect()
|
|
11
|
+
if (!result) throw new Error('No wallet available')
|
|
12
|
+
connection = result
|
|
13
|
+
return result
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export function getWallet(): WalletInterface | null {
|
|
14
|
-
return connection?.wallet ?? null
|
|
17
|
+
return connection?.wallet ?? null
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
export function getIdentityKey(): string | null {
|
|
18
|
-
return connection?.identityKey ?? null
|
|
21
|
+
return connection?.identityKey ?? null
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
export function getProvider(): string | null {
|
|
22
|
-
return connection?.provider ?? null
|
|
25
|
+
return connection?.provider ?? null
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
export function disconnectWallet(): void {
|
|
26
|
-
connection?.disconnect()
|
|
27
|
-
connection = null
|
|
29
|
+
connection?.disconnect()
|
|
30
|
+
connection = null
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export function isConnected(): boolean {
|
|
31
|
-
return connection !== null
|
|
34
|
+
return connection !== null
|
|
32
35
|
}
|
package/src/types.ts
CHANGED