@1sat/cli 0.0.90 → 0.0.92
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/package.json +8 -8
- package/src/beef.ts +48 -0
- package/src/commands/authfetch.ts +187 -0
- package/src/commands/locks.ts +57 -44
- package/src/commands/messagebox.ts +59 -0
- package/src/commands/opns.ts +144 -143
- package/src/commands/ordinals.ts +100 -161
- package/src/commands/tokens.ts +10 -8
- package/src/help.ts +146 -37
- package/src/main.ts +13 -2
package/src/commands/opns.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpNS commands -
|
|
3
|
-
*
|
|
4
|
-
* Manage OpNS names: payment identity bindings and market listings. Paid
|
|
5
|
-
* mining is product code on 1sat.name.
|
|
2
|
+
* OpNS commands — id-first wallet spends; external buy with outpoint/BEEF.
|
|
6
3
|
*/
|
|
7
4
|
|
|
8
5
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
buyOpns,
|
|
7
|
+
cancelOpnsListing,
|
|
8
|
+
deregisterOpns,
|
|
11
9
|
getDisplayValue,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
internalizeOpns,
|
|
11
|
+
listOpns,
|
|
12
|
+
registerOpns,
|
|
13
|
+
sellOpns,
|
|
14
|
+
sendOpns,
|
|
17
15
|
} from '@1sat/actions'
|
|
16
|
+
import { P1SAT_PROTOCOL } from '@1sat/types'
|
|
18
17
|
import { confirm, isCancel } from '@clack/prompts'
|
|
19
18
|
import type { GlobalFlags } from '../args'
|
|
20
19
|
import { extractFlag } from '../args'
|
|
20
|
+
import { idFromTags, parseBeefFlag, parseToFlag } from '../beef'
|
|
21
21
|
import { loadContext } from '../context'
|
|
22
22
|
import { printCommandHelp } from '../help'
|
|
23
23
|
import { loadKey } from '../keys'
|
|
@@ -41,7 +41,11 @@ export async function handleOpnsCommand(
|
|
|
41
41
|
case 'buy':
|
|
42
42
|
return opnsBuy(rest, opts)
|
|
43
43
|
case 'cancel-listing':
|
|
44
|
-
return
|
|
44
|
+
return opnsCancelListingCmd(rest, opts)
|
|
45
|
+
case 'send':
|
|
46
|
+
return opnsSend(rest, opts)
|
|
47
|
+
case 'internalize':
|
|
48
|
+
return opnsInternalize(rest, opts)
|
|
45
49
|
default:
|
|
46
50
|
printCommandHelp('opns', opts.json)
|
|
47
51
|
if (subcommand && subcommand !== 'help') {
|
|
@@ -50,42 +54,28 @@ export async function handleOpnsCommand(
|
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
const
|
|
57
|
+
function requireId(args: string[]): string {
|
|
58
|
+
const id = extractFlag(args, '--id')
|
|
59
|
+
if (!id) fatal('Missing --id <tracking-id>')
|
|
60
|
+
return id
|
|
61
|
+
}
|
|
55
62
|
|
|
56
|
-
|
|
63
|
+
async function opnsRegister(args: string[], opts: GlobalFlags): Promise<void> {
|
|
64
|
+
const id = requireId(args)
|
|
57
65
|
|
|
58
66
|
if (!opts.yes) {
|
|
59
67
|
const ok = await confirm({
|
|
60
|
-
message: `Register identity on OpNS
|
|
68
|
+
message: `Register identity on OpNS id ${id}?`,
|
|
61
69
|
})
|
|
62
|
-
if (isCancel(ok) || !ok)
|
|
63
|
-
fatal('Registration cancelled.')
|
|
64
|
-
}
|
|
70
|
+
if (isCancel(ok) || !ok) fatal('Registration cancelled.')
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
const privateKey = await loadKey()
|
|
68
|
-
const { ctx, destroy } = await loadContext(privateKey, {
|
|
69
|
-
chain: opts.chain,
|
|
70
|
-
})
|
|
74
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
71
75
|
|
|
72
76
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const ordinal = namesResult.outputs.find((o) => o.outpoint === outpoint)
|
|
76
|
-
if (!ordinal) {
|
|
77
|
-
fatal(`OpNS name not found in wallet: ${outpoint}`)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const result = await opnsRegisterAction.execute(ctx, {
|
|
81
|
-
ordinal,
|
|
82
|
-
inputBEEF: namesResult.BEEF as number[] | undefined,
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
if (result.error) {
|
|
86
|
-
fatal(result.error)
|
|
87
|
-
}
|
|
88
|
-
|
|
77
|
+
const result = await registerOpns.execute(ctx, { id })
|
|
78
|
+
if (result.error) fatal(result.error)
|
|
89
79
|
output(opts.json ? result : { txid: result.txid }, opts)
|
|
90
80
|
} finally {
|
|
91
81
|
await destroy()
|
|
@@ -96,55 +86,55 @@ async function opnsDeregister(
|
|
|
96
86
|
args: string[],
|
|
97
87
|
opts: GlobalFlags,
|
|
98
88
|
): Promise<void> {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
if (!outpoint) fatal('Missing --outpoint <txid.vout>')
|
|
89
|
+
const id = requireId(args)
|
|
102
90
|
|
|
103
91
|
if (!opts.yes) {
|
|
104
92
|
const ok = await confirm({
|
|
105
|
-
message: `Deregister identity from OpNS
|
|
93
|
+
message: `Deregister identity from OpNS id ${id}?`,
|
|
106
94
|
})
|
|
107
|
-
if (isCancel(ok) || !ok)
|
|
108
|
-
fatal('Deregistration cancelled.')
|
|
109
|
-
}
|
|
95
|
+
if (isCancel(ok) || !ok) fatal('Deregistration cancelled.')
|
|
110
96
|
}
|
|
111
97
|
|
|
112
98
|
const privateKey = await loadKey()
|
|
113
|
-
const { ctx, destroy } = await loadContext(privateKey, {
|
|
114
|
-
chain: opts.chain,
|
|
115
|
-
})
|
|
99
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
116
100
|
|
|
117
101
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const ordinal = namesResult.outputs.find((o) => o.outpoint === outpoint)
|
|
121
|
-
if (!ordinal) {
|
|
122
|
-
fatal(`OpNS name not found in wallet: ${outpoint}`)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const result = await opnsDeregisterAction.execute(ctx, {
|
|
126
|
-
ordinal,
|
|
127
|
-
inputBEEF: namesResult.BEEF as number[] | undefined,
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
if (result.error) {
|
|
131
|
-
fatal(result.error)
|
|
132
|
-
}
|
|
133
|
-
|
|
102
|
+
const result = await deregisterOpns.execute(ctx, { id })
|
|
103
|
+
if (result.error) fatal(result.error)
|
|
134
104
|
output(opts.json ? result : { txid: result.txid }, opts)
|
|
135
105
|
} finally {
|
|
136
106
|
await destroy()
|
|
137
107
|
}
|
|
138
108
|
}
|
|
139
109
|
|
|
140
|
-
async function opnsLookup(
|
|
110
|
+
async function opnsLookup(args: string[], opts: GlobalFlags): Promise<void> {
|
|
111
|
+
const limit = Number(extractFlag(args, '--limit') ?? '100')
|
|
112
|
+
const offset = Number(extractFlag(args, '--offset') ?? '0')
|
|
113
|
+
const names = extractFlag(args, '--names')?.split(',').filter(Boolean)
|
|
114
|
+
const ids = extractFlag(args, '--ids')?.split(',').filter(Boolean)
|
|
115
|
+
const tags = extractFlag(args, '--tags')?.split(',').filter(Boolean)
|
|
116
|
+
const tagQueryMode = extractFlag(args, '--tag-query-mode') as
|
|
117
|
+
| 'all'
|
|
118
|
+
| 'any'
|
|
119
|
+
| undefined
|
|
120
|
+
const include = extractFlag(args, '--include') as
|
|
121
|
+
| 'locking scripts'
|
|
122
|
+
| 'entire transactions'
|
|
123
|
+
| undefined
|
|
124
|
+
|
|
141
125
|
const privateKey = await loadKey()
|
|
142
|
-
const { ctx, destroy } = await loadContext(privateKey, {
|
|
143
|
-
chain: opts.chain,
|
|
144
|
-
})
|
|
126
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
145
127
|
|
|
146
128
|
try {
|
|
147
|
-
const result = await
|
|
129
|
+
const result = await listOpns.execute(ctx, {
|
|
130
|
+
limit,
|
|
131
|
+
offset,
|
|
132
|
+
names,
|
|
133
|
+
ids,
|
|
134
|
+
tags,
|
|
135
|
+
tagQueryMode,
|
|
136
|
+
include,
|
|
137
|
+
})
|
|
148
138
|
|
|
149
139
|
if (opts.json) {
|
|
150
140
|
output(result.outputs, opts)
|
|
@@ -157,6 +147,7 @@ async function opnsLookup(_args: string[], opts: GlobalFlags): Promise<void> {
|
|
|
157
147
|
}
|
|
158
148
|
|
|
159
149
|
for (const o of result.outputs) {
|
|
150
|
+
const id = idFromTags(o.tags) ?? ''
|
|
160
151
|
const nameTag = getDisplayValue(o, 'name', 'name') ?? ''
|
|
161
152
|
const publishedTag = o.tags?.find((t) => t === 'opns:published')
|
|
162
153
|
const status = publishedTag ? 'registered' : 'unregistered'
|
|
@@ -168,7 +159,7 @@ async function opnsLookup(_args: string[], opts: GlobalFlags): Promise<void> {
|
|
|
168
159
|
const listed = price ? ` ${formatLabel(`listed @ ${price}`)}` : ''
|
|
169
160
|
|
|
170
161
|
console.log(
|
|
171
|
-
` ${formatValue(o.outpoint)} ${nameTag ? formatValue(nameTag) : ''} ${formatLabel(status)}${listed}`,
|
|
162
|
+
` ${formatValue(id)} ${formatValue(o.outpoint)} ${nameTag ? formatValue(nameTag) : ''} ${formatLabel(status)}${listed}`,
|
|
172
163
|
)
|
|
173
164
|
}
|
|
174
165
|
|
|
@@ -178,44 +169,25 @@ async function opnsLookup(_args: string[], opts: GlobalFlags): Promise<void> {
|
|
|
178
169
|
}
|
|
179
170
|
}
|
|
180
171
|
|
|
181
|
-
async function
|
|
172
|
+
async function opnsCancelListingCmd(
|
|
182
173
|
args: string[],
|
|
183
174
|
opts: GlobalFlags,
|
|
184
175
|
): Promise<void> {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
if (!outpoint) fatal('Missing --outpoint <txid.vout>')
|
|
176
|
+
const id = requireId(args)
|
|
188
177
|
|
|
189
178
|
if (!opts.yes) {
|
|
190
179
|
const ok = await confirm({
|
|
191
|
-
message: `Cancel listing for OpNS
|
|
180
|
+
message: `Cancel listing for OpNS id ${id}?`,
|
|
192
181
|
})
|
|
193
|
-
if (isCancel(ok) || !ok)
|
|
194
|
-
fatal('Cancellation cancelled.')
|
|
195
|
-
}
|
|
182
|
+
if (isCancel(ok) || !ok) fatal('Cancellation cancelled.')
|
|
196
183
|
}
|
|
197
184
|
|
|
198
185
|
const privateKey = await loadKey()
|
|
199
|
-
const { ctx, destroy } = await loadContext(privateKey, {
|
|
200
|
-
chain: opts.chain,
|
|
201
|
-
})
|
|
186
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
202
187
|
|
|
203
188
|
try {
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
if (!listing) {
|
|
207
|
-
fatal(`Listing not found in wallet OpNS basket: ${outpoint}`)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const result = await cancelListing.execute(ctx, {
|
|
211
|
-
listing,
|
|
212
|
-
inputBEEF: namesResult.BEEF as number[] | undefined,
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
if (result.error) {
|
|
216
|
-
fatal(result.error)
|
|
217
|
-
}
|
|
218
|
-
|
|
189
|
+
const result = await cancelOpnsListing.execute(ctx, { id })
|
|
190
|
+
if (result.error) fatal(result.error)
|
|
219
191
|
output(opts.json ? result : { txid: result.txid }, opts)
|
|
220
192
|
} finally {
|
|
221
193
|
await destroy()
|
|
@@ -223,13 +195,11 @@ async function opnsCancelListing(
|
|
|
223
195
|
}
|
|
224
196
|
|
|
225
197
|
async function opnsSell(args: string[], opts: GlobalFlags): Promise<void> {
|
|
226
|
-
const
|
|
198
|
+
const id = requireId(args)
|
|
227
199
|
const priceStr = extractFlag(args, '--price')
|
|
228
|
-
const
|
|
200
|
+
const payAddress = extractFlag(args, '--pay-address')
|
|
229
201
|
|
|
230
|
-
if (!outpoint) fatal('Missing --outpoint <txid.vout>')
|
|
231
202
|
if (!priceStr) fatal('Missing --price <satoshis>')
|
|
232
|
-
|
|
233
203
|
const price = Number(priceStr)
|
|
234
204
|
if (!Number.isFinite(price) || price <= 0) {
|
|
235
205
|
fatal('--price must be a positive number')
|
|
@@ -237,48 +207,47 @@ async function opnsSell(args: string[], opts: GlobalFlags): Promise<void> {
|
|
|
237
207
|
|
|
238
208
|
if (!opts.yes) {
|
|
239
209
|
const ok = await confirm({
|
|
240
|
-
message: `List OpNS
|
|
210
|
+
message: `List OpNS id ${id} for sale at ${price} satoshis?`,
|
|
241
211
|
})
|
|
242
|
-
if (isCancel(ok) || !ok)
|
|
243
|
-
fatal('Listing cancelled.')
|
|
244
|
-
}
|
|
212
|
+
if (isCancel(ok) || !ok) fatal('Listing cancelled.')
|
|
245
213
|
}
|
|
246
214
|
|
|
247
215
|
const privateKey = await loadKey()
|
|
248
|
-
const { ctx, destroy } = await loadContext(privateKey, {
|
|
249
|
-
chain: opts.chain,
|
|
250
|
-
})
|
|
216
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
251
217
|
|
|
252
218
|
try {
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
219
|
+
const result = await sellOpns.execute(ctx, {
|
|
220
|
+
id,
|
|
221
|
+
price,
|
|
222
|
+
...(payAddress && { payAddress }),
|
|
223
|
+
})
|
|
224
|
+
if (result.error) fatal(result.error)
|
|
225
|
+
output(opts.json ? result : { txid: result.txid }, opts)
|
|
226
|
+
} finally {
|
|
227
|
+
await destroy()
|
|
228
|
+
}
|
|
229
|
+
}
|
|
258
230
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
count: 1,
|
|
264
|
-
})
|
|
265
|
-
payAddress = addressResult.derivations[0]?.address
|
|
266
|
-
if (!payAddress) {
|
|
267
|
-
fatal('Failed to derive pay address')
|
|
268
|
-
}
|
|
269
|
-
}
|
|
231
|
+
async function opnsSend(args: string[], opts: GlobalFlags): Promise<void> {
|
|
232
|
+
const id = requireId(args)
|
|
233
|
+
const to = extractFlag(args, '--to')
|
|
234
|
+
if (!to) fatal('Missing --to <address|identityKey>')
|
|
270
235
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
236
|
+
const dest = parseToFlag(to)
|
|
237
|
+
|
|
238
|
+
if (!opts.yes) {
|
|
239
|
+
const ok = await confirm({
|
|
240
|
+
message: `Send OpNS id ${id} to ${to}?`,
|
|
276
241
|
})
|
|
242
|
+
if (isCancel(ok) || !ok) fatal('Send cancelled.')
|
|
243
|
+
}
|
|
277
244
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
245
|
+
const privateKey = await loadKey()
|
|
246
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
281
247
|
|
|
248
|
+
try {
|
|
249
|
+
const result = await sendOpns.execute(ctx, { id, ...dest })
|
|
250
|
+
if (result.error) fatal(result.error)
|
|
282
251
|
output(opts.json ? result : { txid: result.txid }, opts)
|
|
283
252
|
} finally {
|
|
284
253
|
await destroy()
|
|
@@ -287,31 +256,63 @@ async function opnsSell(args: string[], opts: GlobalFlags): Promise<void> {
|
|
|
287
256
|
|
|
288
257
|
async function opnsBuy(args: string[], opts: GlobalFlags): Promise<void> {
|
|
289
258
|
const outpoint = extractFlag(args, '--outpoint')
|
|
259
|
+
const beef = parseBeefFlag(extractFlag(args, '--beef'))
|
|
260
|
+
const name = extractFlag(args, '--name')
|
|
261
|
+
const origin = extractFlag(args, '--origin')
|
|
290
262
|
|
|
291
263
|
if (!outpoint) fatal('Missing --outpoint <txid.vout>')
|
|
292
264
|
|
|
293
265
|
if (!opts.yes) {
|
|
294
266
|
const ok = await confirm({
|
|
295
|
-
message: `Purchase OpNS
|
|
267
|
+
message: `Purchase OpNS listing ${outpoint}?`,
|
|
296
268
|
})
|
|
297
|
-
if (isCancel(ok) || !ok)
|
|
298
|
-
fatal('Purchase cancelled.')
|
|
299
|
-
}
|
|
269
|
+
if (isCancel(ok) || !ok) fatal('Purchase cancelled.')
|
|
300
270
|
}
|
|
301
271
|
|
|
302
272
|
const privateKey = await loadKey()
|
|
303
|
-
const { ctx, destroy } = await loadContext(privateKey, {
|
|
304
|
-
chain: opts.chain,
|
|
305
|
-
})
|
|
273
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
306
274
|
|
|
307
275
|
try {
|
|
308
|
-
const result = await
|
|
276
|
+
const result = await buyOpns.execute(ctx, {
|
|
277
|
+
outpoint,
|
|
278
|
+
...(beef && { inputBEEF: beef }),
|
|
279
|
+
...(name && { name }),
|
|
280
|
+
...(origin && { origin }),
|
|
281
|
+
})
|
|
282
|
+
if (result.error) fatal(result.error)
|
|
283
|
+
output(opts.json ? result : { txid: result.txid }, opts)
|
|
284
|
+
} finally {
|
|
285
|
+
await destroy()
|
|
286
|
+
}
|
|
287
|
+
}
|
|
309
288
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
289
|
+
async function opnsInternalize(
|
|
290
|
+
args: string[],
|
|
291
|
+
opts: GlobalFlags,
|
|
292
|
+
): Promise<void> {
|
|
293
|
+
const beef = parseBeefFlag(extractFlag(args, '--beef'))
|
|
294
|
+
const keyID = extractFlag(args, '--key-id') ?? '1sat 0'
|
|
313
295
|
|
|
314
|
-
|
|
296
|
+
if (!beef) fatal('Missing --beef <file|hex|base64>')
|
|
297
|
+
|
|
298
|
+
if (!opts.yes) {
|
|
299
|
+
const ok = await confirm({
|
|
300
|
+
message: 'Internalize OpNS mint AtomicBEEF into wallet?',
|
|
301
|
+
})
|
|
302
|
+
if (isCancel(ok) || !ok) fatal('Internalize cancelled.')
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const privateKey = await loadKey()
|
|
306
|
+
const { ctx, destroy } = await loadContext(privateKey, { chain: opts.chain })
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
const result = await internalizeOpns.execute(ctx, {
|
|
310
|
+
tx: beef,
|
|
311
|
+
protocolID: P1SAT_PROTOCOL,
|
|
312
|
+
keyID,
|
|
313
|
+
})
|
|
314
|
+
if (result.error) fatal(result.error)
|
|
315
|
+
output(opts.json ? result : result, opts)
|
|
315
316
|
} finally {
|
|
316
317
|
await destroy()
|
|
317
318
|
}
|