@1sat/cli 0.0.81 → 0.0.83

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/cli",
3
- "version": "0.0.81",
3
+ "version": "0.0.83",
4
4
  "description": "CLI for 1Sat Ordinals SDK",
5
5
  "type": "module",
6
6
  "main": "./src/cli.ts",
@@ -1,14 +1,19 @@
1
1
  /**
2
- * OpNS commands - register, deregister, lookup.
2
+ * OpNS commands - register, deregister, lookup, sell, buy, cancel-listing.
3
3
  *
4
- * Manage OpNS name identity bindings. Paid mining is product code on 1sat.name.
4
+ * Manage OpNS names: payment identity bindings and market listings. Paid
5
+ * mining is product code on 1sat.name.
5
6
  */
6
7
 
7
8
  import {
9
+ cancelListing,
10
+ deriveDepositAddresses,
8
11
  getDisplayValue,
9
12
  getOpnsNames,
13
+ listOrdinal,
10
14
  opnsDeregister as opnsDeregisterAction,
11
15
  opnsRegister as opnsRegisterAction,
16
+ purchaseOrdinal,
12
17
  } from '@1sat/actions'
13
18
  import { confirm, isCancel } from '@clack/prompts'
14
19
  import type { GlobalFlags } from '../args'
@@ -31,6 +36,12 @@ export async function handleOpnsCommand(
31
36
  return opnsDeregister(rest, opts)
32
37
  case 'lookup':
33
38
  return opnsLookup(rest, opts)
39
+ case 'sell':
40
+ return opnsSell(rest, opts)
41
+ case 'buy':
42
+ return opnsBuy(rest, opts)
43
+ case 'cancel-listing':
44
+ return opnsCancelListing(rest, opts)
34
45
  default:
35
46
  printCommandHelp('opns', opts.json)
36
47
  if (subcommand && subcommand !== 'help') {
@@ -149,9 +160,15 @@ async function opnsLookup(_args: string[], opts: GlobalFlags): Promise<void> {
149
160
  const nameTag = getDisplayValue(o, 'name', 'name') ?? ''
150
161
  const publishedTag = o.tags?.find((t) => t === 'opns:published')
151
162
  const status = publishedTag ? 'registered' : 'unregistered'
163
+ const price = o.tags?.some((t) => t === 'ordlock')
164
+ ? (o.tags
165
+ ?.find((t) => t.startsWith('price:'))
166
+ ?.slice('price:'.length) ?? '?')
167
+ : undefined
168
+ const listed = price ? ` ${formatLabel(`listed @ ${price}`)}` : ''
152
169
 
153
170
  console.log(
154
- ` ${formatValue(o.outpoint)} ${nameTag ? formatValue(nameTag) : ''} ${formatLabel(status)}`,
171
+ ` ${formatValue(o.outpoint)} ${nameTag ? formatValue(nameTag) : ''} ${formatLabel(status)}${listed}`,
155
172
  )
156
173
  }
157
174
 
@@ -160,3 +177,142 @@ async function opnsLookup(_args: string[], opts: GlobalFlags): Promise<void> {
160
177
  await destroy()
161
178
  }
162
179
  }
180
+
181
+ async function opnsCancelListing(
182
+ args: string[],
183
+ opts: GlobalFlags,
184
+ ): Promise<void> {
185
+ const outpoint = extractFlag(args, '--outpoint')
186
+
187
+ if (!outpoint) fatal('Missing --outpoint <txid.vout>')
188
+
189
+ if (!opts.yes) {
190
+ const ok = await confirm({
191
+ message: `Cancel listing for OpNS name ${outpoint}?`,
192
+ })
193
+ if (isCancel(ok) || !ok) {
194
+ fatal('Cancellation cancelled.')
195
+ }
196
+ }
197
+
198
+ const privateKey = await loadKey()
199
+ const { ctx, destroy } = await loadContext(privateKey, {
200
+ chain: opts.chain,
201
+ })
202
+
203
+ try {
204
+ const namesResult = await getOpnsNames.execute(ctx, { limit: 10000 })
205
+ const listing = namesResult.outputs.find((o) => o.outpoint === outpoint)
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
+
219
+ output(opts.json ? result : { txid: result.txid }, opts)
220
+ } finally {
221
+ await destroy()
222
+ }
223
+ }
224
+
225
+ async function opnsSell(args: string[], opts: GlobalFlags): Promise<void> {
226
+ const outpoint = extractFlag(args, '--outpoint')
227
+ const priceStr = extractFlag(args, '--price')
228
+ const payAddressFlag = extractFlag(args, '--pay-address')
229
+
230
+ if (!outpoint) fatal('Missing --outpoint <txid.vout>')
231
+ if (!priceStr) fatal('Missing --price <satoshis>')
232
+
233
+ const price = Number(priceStr)
234
+ if (!Number.isFinite(price) || price <= 0) {
235
+ fatal('--price must be a positive number')
236
+ }
237
+
238
+ if (!opts.yes) {
239
+ const ok = await confirm({
240
+ message: `List OpNS name ${outpoint} for sale at ${price} satoshis?`,
241
+ })
242
+ if (isCancel(ok) || !ok) {
243
+ fatal('Listing cancelled.')
244
+ }
245
+ }
246
+
247
+ const privateKey = await loadKey()
248
+ const { ctx, destroy } = await loadContext(privateKey, {
249
+ chain: opts.chain,
250
+ })
251
+
252
+ try {
253
+ const namesResult = await getOpnsNames.execute(ctx, { limit: 10000 })
254
+ const ordinal = namesResult.outputs.find((o) => o.outpoint === outpoint)
255
+ if (!ordinal) {
256
+ fatal(`OpNS name not found in wallet: ${outpoint}`)
257
+ }
258
+
259
+ let payAddress = payAddressFlag
260
+ if (!payAddress) {
261
+ const addressResult = await deriveDepositAddresses.execute(ctx, {
262
+ prefix: '1sat',
263
+ count: 1,
264
+ })
265
+ payAddress = addressResult.derivations[0]?.address
266
+ if (!payAddress) {
267
+ fatal('Failed to derive pay address')
268
+ }
269
+ }
270
+
271
+ const result = await listOrdinal.execute(ctx, {
272
+ ordinal,
273
+ price,
274
+ payAddress,
275
+ inputBEEF: namesResult.BEEF as number[] | undefined,
276
+ })
277
+
278
+ if (result.error) {
279
+ fatal(result.error)
280
+ }
281
+
282
+ output(opts.json ? result : { txid: result.txid }, opts)
283
+ } finally {
284
+ await destroy()
285
+ }
286
+ }
287
+
288
+ async function opnsBuy(args: string[], opts: GlobalFlags): Promise<void> {
289
+ const outpoint = extractFlag(args, '--outpoint')
290
+
291
+ if (!outpoint) fatal('Missing --outpoint <txid.vout>')
292
+
293
+ if (!opts.yes) {
294
+ const ok = await confirm({
295
+ message: `Purchase OpNS name listing ${outpoint}?`,
296
+ })
297
+ if (isCancel(ok) || !ok) {
298
+ fatal('Purchase cancelled.')
299
+ }
300
+ }
301
+
302
+ const privateKey = await loadKey()
303
+ const { ctx, destroy } = await loadContext(privateKey, {
304
+ chain: opts.chain,
305
+ })
306
+
307
+ try {
308
+ const result = await purchaseOrdinal.execute(ctx, { outpoint })
309
+
310
+ if (result.error) {
311
+ fatal(result.error)
312
+ }
313
+
314
+ output(opts.json ? result : { txid: result.txid }, opts)
315
+ } finally {
316
+ await destroy()
317
+ }
318
+ }
package/src/help.ts CHANGED
@@ -496,19 +496,42 @@ export const COMMANDS: CommandSpec[] = [
496
496
  {
497
497
  group: 'OpNS',
498
498
  name: 'opns',
499
- description: 'Ordinals Name System — bind BAP identity to a name',
499
+ description: 'Ordinals Name System — on-chain names',
500
500
  subcommands: [
501
501
  {
502
502
  name: 'register',
503
- description: 'Register identity on an OpNS name',
503
+ description: 'Register a payment identity key on an OpNS name',
504
504
  args: [{ flag: '--outpoint', values: '<txid.vout>', required: true }],
505
505
  },
506
506
  {
507
507
  name: 'deregister',
508
- description: 'Deregister identity from an OpNS name',
508
+ description: 'Deregister the payment identity from an OpNS name',
509
509
  args: [{ flag: '--outpoint', values: '<txid.vout>', required: true }],
510
510
  },
511
511
  { name: 'lookup', description: 'List OpNS names from wallet' },
512
+ {
513
+ name: 'sell',
514
+ description: 'List an OpNS name for sale',
515
+ args: [
516
+ { flag: '--outpoint', values: '<txid.vout>', required: true },
517
+ { flag: '--price', values: '<satoshis>', required: true },
518
+ {
519
+ flag: '--pay-address',
520
+ values: '<address>',
521
+ required: false,
522
+ },
523
+ ],
524
+ },
525
+ {
526
+ name: 'buy',
527
+ description: 'Purchase an OpNS name listing',
528
+ args: [{ flag: '--outpoint', values: '<txid.vout>', required: true }],
529
+ },
530
+ {
531
+ name: 'cancel-listing',
532
+ description: 'Cancel a market listing on an OpNS name',
533
+ args: [{ flag: '--outpoint', values: '<txid.vout>', required: true }],
534
+ },
512
535
  ],
513
536
  },
514
537