@1sat/actions 0.0.190 → 0.0.192

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.
Files changed (41) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/inscriptions/index.d.ts +2 -2
  6. package/dist/inscriptions/index.d.ts.map +1 -1
  7. package/dist/inscriptions/index.js +3 -6
  8. package/dist/inscriptions/index.js.map +1 -1
  9. package/dist/locks/index.d.ts +32 -3
  10. package/dist/locks/index.d.ts.map +1 -1
  11. package/dist/locks/index.js +76 -5
  12. package/dist/locks/index.js.map +1 -1
  13. package/dist/opns/index.d.ts +43 -76
  14. package/dist/opns/index.d.ts.map +1 -1
  15. package/dist/opns/index.js +420 -234
  16. package/dist/opns/index.js.map +1 -1
  17. package/dist/ordinals/index.d.ts +58 -44
  18. package/dist/ordinals/index.d.ts.map +1 -1
  19. package/dist/ordinals/index.js +217 -188
  20. package/dist/ordinals/index.js.map +1 -1
  21. package/dist/tokens/index.d.ts +3 -3
  22. package/dist/tokens/index.d.ts.map +1 -1
  23. package/dist/tokens/index.js +38 -24
  24. package/dist/tokens/index.js.map +1 -1
  25. package/dist/utils/createTrackedAction.js +1 -1
  26. package/dist/utils/internalizeBeef.d.ts.map +1 -1
  27. package/dist/utils/internalizeBeef.js +1 -25
  28. package/dist/utils/internalizeBeef.js.map +1 -1
  29. package/dist/utils/loadBasketOutput.d.ts +25 -0
  30. package/dist/utils/loadBasketOutput.d.ts.map +1 -0
  31. package/dist/utils/loadBasketOutput.js +50 -0
  32. package/dist/utils/loadBasketOutput.js.map +1 -0
  33. package/dist/utils/ordinalSeedTags.d.ts +8 -0
  34. package/dist/utils/ordinalSeedTags.d.ts.map +1 -0
  35. package/dist/utils/ordinalSeedTags.js +24 -0
  36. package/dist/utils/ordinalSeedTags.js.map +1 -0
  37. package/package.json +9 -9
  38. package/dist/utils/resolveBeef.d.ts +0 -20
  39. package/dist/utils/resolveBeef.d.ts.map +0 -1
  40. package/dist/utils/resolveBeef.js +0 -36
  41. package/dist/utils/resolveBeef.js.map +0 -1
@@ -11,7 +11,8 @@ import { parseOutpoint } from '@1sat/utils';
11
11
  import { Beef, BigNumber, LockingScript, OP, P2PKH, PublicKey, Script, TransactionSignature, UnlockingScript, Utils, } from '@bsv/sdk';
12
12
  import { OPNS_BASKET, ORDINALS_BASKET, ORD_LOCK_PREFIX, ORD_LOCK_SUFFIX, P1SAT_PROTOCOL, } from '../constants';
13
13
  import { executeTrackedAction } from '../utils/createTrackedAction';
14
- import { resolveBeef } from '../utils/resolveBeef';
14
+ import { loadBasketOutputBeef } from '../utils/loadBasketOutput';
15
+ import { ordinalSeedTags } from '../utils/ordinalSeedTags';
15
16
  import { signOrdinalInput, unlockingScriptLengthForInstructions, } from '../utils/signOrdinalInput';
16
17
  // ============================================================================
17
18
  // Helpers
@@ -102,7 +103,8 @@ export async function resolveOrdinalTags(ctx, outpoint, source) {
102
103
  // ============================================================================
103
104
  // Internal helpers
104
105
  // ============================================================================
105
- async function deriveCancelAddressInternal(ctx, outpoint) {
106
+ /** Cancel/list key address for an outpoint (P1SAT self). */
107
+ export async function deriveCancelAddressInternal(ctx, outpoint) {
106
108
  const result = await ctx.wallet.getPublicKey({
107
109
  protocolID: P1SAT_PROTOCOL,
108
110
  keyID: outpoint,
@@ -110,7 +112,17 @@ async function deriveCancelAddressInternal(ctx, outpoint) {
110
112
  });
111
113
  return PublicKey.fromString(result.publicKey).toAddress();
112
114
  }
113
- function buildOrdLockScript(ordAddress, payAddress, price) {
115
+ /** Default OrdLock payment address: P1SAT keyID `1sat 0`, self. */
116
+ export async function defaultPayAddress(ctx) {
117
+ const result = await ctx.wallet.getPublicKey({
118
+ protocolID: P1SAT_PROTOCOL,
119
+ keyID: '1sat 0',
120
+ counterparty: 'self',
121
+ forSelf: true,
122
+ });
123
+ return PublicKey.fromString(result.publicKey).toAddress();
124
+ }
125
+ export function buildOrdLockScript(ordAddress, payAddress, price) {
114
126
  const cancelPkh = Utils.fromBase58Check(ordAddress).data;
115
127
  const payPkh = Utils.fromBase58Check(payAddress).data;
116
128
  const payoutScript = new P2PKH().lock(payPkh).toBinary();
@@ -172,9 +184,26 @@ async function buildPurchaseUnlockingScript(tx, inputIndex, sourceSatoshis, lock
172
184
  // ============================================================================
173
185
  // Builder functions (utilities for advanced use)
174
186
  // ============================================================================
187
+ async function loadOrdinalSpend(ctx, id) {
188
+ return loadBasketOutputBeef(ctx.wallet, ORDINALS_BASKET, id);
189
+ }
190
+ function nameFromOutput(output, tags) {
191
+ if (output.customInstructions) {
192
+ try {
193
+ const n = JSON.parse(output.customInstructions).name;
194
+ if (typeof n === 'string' && n)
195
+ return n.slice(0, 64);
196
+ }
197
+ catch { }
198
+ }
199
+ const fromTags = (tags ?? output.tags)
200
+ ?.find((t) => t.startsWith('name:'))
201
+ ?.slice(5);
202
+ return fromTags?.slice(0, 64);
203
+ }
175
204
  /**
176
205
  * Build CreateActionArgs for transferring one or more ordinals.
177
- * Does NOT execute - returns params for createAction.
206
+ * Loads each id once from the ordinals basket.
178
207
  */
179
208
  export async function buildTransferOrdinals(ctx, request) {
180
209
  const { transfers } = request;
@@ -184,11 +213,21 @@ export async function buildTransferOrdinals(ctx, request) {
184
213
  const inputs = [];
185
214
  const outputs = [];
186
215
  const labels = [];
187
- let resolvedBasket = ORDINALS_BASKET;
188
- for (const { ordinal, counterparty, address, map, extraTags } of transfers) {
216
+ const sources = [];
217
+ const beefParts = [];
218
+ for (const item of transfers) {
219
+ const { id, counterparty, address, map } = item;
220
+ if (!id)
221
+ return { error: 'missing-id' };
189
222
  if (!counterparty && !address) {
190
223
  return { error: 'must-provide-counterparty-or-address' };
191
224
  }
225
+ const loaded = await loadOrdinalSpend(ctx, id);
226
+ if ('error' in loaded)
227
+ return loaded;
228
+ const { output: ordinal, beef } = loaded;
229
+ sources.push(ordinal);
230
+ beefParts.push(beef);
192
231
  const outpoint = ordinal.outpoint;
193
232
  const sourceType = ordinal.tags
194
233
  ?.find((t) => t.startsWith('type:'))
@@ -215,24 +254,16 @@ export async function buildTransferOrdinals(ctx, request) {
215
254
  else {
216
255
  return { error: 'must-provide-counterparty-or-address' };
217
256
  }
218
- const { tags, basket } = await resolveOrdinalTags(ctx, outpoint, {
219
- tags: ordinal.tags,
220
- });
221
- if (extraTags)
222
- tags.push(...extraTags);
223
- resolvedBasket = basket;
257
+ const tags = ordinalSeedTags(ordinal);
258
+ const basket = ORDINALS_BASKET;
224
259
  inputs?.push({
225
260
  outpoint,
226
261
  inputDescription: 'Ordinal to transfer',
227
262
  unlockingScriptLength: unlockingScriptLengthForInstructions(ordinal.customInstructions),
228
263
  });
229
- // Emit a per-ordinal input label so the 1Sat permission module can
230
- // resolve the source output's id-tagged record in wallet storage and
231
- // render trusted metadata (origin / contentType / name).
232
264
  const inputId = readAssetIdTag(ordinal.tags);
233
265
  if (inputId)
234
266
  labels.push(buildInputAssetLabel(basket, inputId));
235
- // Build locking script — append MAP metadata when provided
236
267
  const p2pkhScript = new P2PKH().lock(recipientAddress);
237
268
  let lockingScript;
238
269
  if (map && Object.keys(map).length > 0) {
@@ -247,20 +278,8 @@ export async function buildTransferOrdinals(ctx, request) {
247
278
  else {
248
279
  lockingScript = p2pkhScript.toHex();
249
280
  }
250
- // Carry forward the name from CI, else from resolved tags.
251
- let sourceName;
252
- if (ordinal.customInstructions) {
253
- try {
254
- sourceName = JSON.parse(ordinal.customInstructions).name;
255
- }
256
- catch { }
257
- }
258
- if (!sourceName) {
259
- sourceName = tags.find((t) => t.startsWith('name:'))?.slice(5);
260
- }
281
+ const sourceName = nameFromOutput(ordinal, tags);
261
282
  if (isSelf) {
262
- // Keep the ordinal in our wallet with full labeling (register/deregister,
263
- // self-retags). External sends must not basket on the sender side.
264
283
  outputs?.push({
265
284
  lockingScript,
266
285
  satoshis: 1,
@@ -285,8 +304,9 @@ export async function buildTransferOrdinals(ctx, request) {
285
304
  });
286
305
  }
287
306
  }
288
- const inputBEEF = request.inputBEEF ??
289
- (await resolveBeef(ctx.wallet, resolvedBasket, transfers[0].ordinal));
307
+ if (!beefParts.length)
308
+ return { error: 'missing-input-beef' };
309
+ const inputBEEF = beefParts[0];
290
310
  return {
291
311
  description: transfers.length === 1
292
312
  ? 'Transfer ordinal'
@@ -295,18 +315,24 @@ export async function buildTransferOrdinals(ctx, request) {
295
315
  inputs,
296
316
  outputs,
297
317
  labels,
318
+ sources,
298
319
  };
299
320
  }
300
321
  /**
301
322
  * Build CreateActionArgs for listing an ordinal for sale.
302
- * Does NOT execute - returns params for createAction.
323
+ * Loads id once from the ordinals basket.
303
324
  */
304
325
  export async function buildListOrdinal(ctx, request) {
305
- const { ordinal, price, payAddress, map } = request;
306
- if (!payAddress)
307
- return { error: 'missing-pay-address' };
326
+ const { id, price, map } = request;
327
+ if (!id)
328
+ return { error: 'missing-id' };
308
329
  if (price <= 0)
309
330
  return { error: 'invalid-price' };
331
+ const loaded = await loadOrdinalSpend(ctx, id);
332
+ if ('error' in loaded)
333
+ return loaded;
334
+ const { output: ordinal, beef } = loaded;
335
+ const payAddress = request.payAddress ?? (await defaultPayAddress(ctx));
310
336
  const outpoint = ordinal.outpoint;
311
337
  const cancelAddress = await deriveCancelAddressInternal(ctx, outpoint);
312
338
  const ordLockScript = buildOrdLockScript(cancelAddress, payAddress, price);
@@ -325,23 +351,14 @@ export async function buildListOrdinal(ctx, request) {
325
351
  else {
326
352
  lockingScript = ordLockScript.toHex();
327
353
  }
328
- const { tags, basket } = await resolveOrdinalTags(ctx, outpoint, {
329
- tags: ordinal.tags,
330
- });
331
- tags.push('ordlock', `price:${price}`);
332
- let sourceName;
333
- if (ordinal.customInstructions) {
334
- try {
335
- sourceName = JSON.parse(ordinal.customInstructions).name;
336
- }
337
- catch { }
338
- }
339
- const inputBEEF = request.inputBEEF ?? (await resolveBeef(ctx.wallet, basket, ordinal));
354
+ const tags = [...ordinalSeedTags(ordinal), 'ordlock', `price:${price}`];
355
+ const basket = ORDINALS_BASKET;
356
+ const sourceName = nameFromOutput(ordinal, tags);
340
357
  const inputId = readAssetIdTag(ordinal.tags);
341
358
  const labels = inputId ? [buildInputAssetLabel(basket, inputId)] : undefined;
342
359
  return {
343
360
  description: `List ordinal for ${price} sats`,
344
- inputBEEF,
361
+ inputBEEF: beef,
345
362
  ...(labels && { labels }),
346
363
  inputs: [
347
364
  {
@@ -364,6 +381,7 @@ export async function buildListOrdinal(ctx, request) {
364
381
  }),
365
382
  },
366
383
  ],
384
+ source: ordinal,
367
385
  };
368
386
  }
369
387
  /**
@@ -371,17 +389,23 @@ export async function buildListOrdinal(ctx, request) {
371
389
  * Does NOT execute - returns params for createAction.
372
390
  */
373
391
  export async function buildBurnOrdinals(ctx, request) {
374
- const { ordinals } = request;
375
- if (!ordinals.length) {
392
+ const ordinals = [];
393
+ const beefParts = [];
394
+ if (!request.ids?.length) {
376
395
  return { error: 'no-ordinals' };
377
396
  }
397
+ for (const id of request.ids) {
398
+ const loaded = await loadOrdinalSpend(ctx, id);
399
+ if ('error' in loaded)
400
+ return loaded;
401
+ ordinals.push(loaded.output);
402
+ beefParts.push(loaded.beef);
403
+ }
378
404
  const inputs = ordinals.map((ordinal) => ({
379
405
  outpoint: ordinal.outpoint,
380
406
  inputDescription: 'Ordinal to burn',
381
407
  unlockingScriptLength: unlockingScriptLengthForInstructions(ordinal.customInstructions),
382
408
  }));
383
- const inputBEEF = request.inputBEEF ??
384
- (await resolveBeef(ctx.wallet, ORDINALS_BASKET, ordinals[0]));
385
409
  const mapScript = MAPTemplate.set({
386
410
  app: request.app ?? '1sat',
387
411
  type: 'ord',
@@ -398,7 +422,7 @@ export async function buildBurnOrdinals(ctx, request) {
398
422
  description: ordinals.length === 1
399
423
  ? 'Burn ordinal'
400
424
  : `Burn ${ordinals.length} ordinals`,
401
- inputBEEF,
425
+ inputBEEF: beefParts[0],
402
426
  ...(labels.length > 0 && { labels }),
403
427
  inputs,
404
428
  outputs: [
@@ -408,19 +432,27 @@ export async function buildBurnOrdinals(ctx, request) {
408
432
  outputDescription: 'Burn ordinals',
409
433
  },
410
434
  ],
435
+ sources: ordinals,
411
436
  };
412
437
  }
413
438
  /**
414
- * Get ordinals from the wallet with BEEF for spending.
439
+ * List ordinals in the wallet. Metadata (tags/CI) by default; BEEF on demand.
415
440
  */
416
- export const getOrdinals = {
441
+ export const listOrdinals = {
417
442
  meta: {
418
- name: 'getOrdinals',
419
- description: 'Get ordinals/inscriptions from the wallet with BEEF for spending',
443
+ name: 'listOrdinals',
444
+ description: 'List ordinals/inscriptions (metadata by default; optional BEEF)',
420
445
  category: 'ordinals',
421
446
  inputSchema: {
422
447
  type: 'object',
423
448
  properties: {
449
+ tags: { type: 'array', items: { type: 'string' } },
450
+ tagQueryMode: { type: 'string', enum: ['all', 'any'] },
451
+ ids: { type: 'array', items: { type: 'string' } },
452
+ include: {
453
+ type: 'string',
454
+ enum: ['locking scripts', 'entire transactions'],
455
+ },
424
456
  limit: {
425
457
  type: 'integer',
426
458
  description: 'Max ordinals to return (default: 100)',
@@ -433,26 +465,40 @@ export const getOrdinals = {
433
465
  },
434
466
  },
435
467
  async execute(ctx, input) {
468
+ const tags = [...(input.tags ?? [])];
469
+ for (const id of input.ids ?? []) {
470
+ if (id)
471
+ tags.push(id.startsWith('id:') ? id : `id:${id}`);
472
+ }
473
+ const filtering = tags.length > 0;
436
474
  const result = await ctx.wallet.listOutputs({
437
475
  basket: ORDINALS_BASKET,
438
- includeTags: true,
439
- includeCustomInstructions: true,
440
- include: 'entire transactions',
476
+ ...(filtering && {
477
+ tags,
478
+ tagQueryMode: input.tagQueryMode ?? 'any',
479
+ }),
480
+ ...(input.include && { include: input.include }),
481
+ includeTags: input.includeTags ?? true,
482
+ includeCustomInstructions: input.includeCustomInstructions ?? true,
483
+ ...(input.includeLabels != null && {
484
+ includeLabels: input.includeLabels,
485
+ }),
441
486
  limit: input.limit ?? 100,
442
487
  offset: input.offset ?? 0,
443
488
  });
444
489
  return {
445
490
  outputs: result.outputs,
446
491
  BEEF: result.BEEF,
492
+ totalOutputs: result.totalOutputs,
447
493
  };
448
494
  },
449
495
  };
450
496
  /**
451
497
  * Transfer an ordinal to a new owner.
452
498
  */
453
- export const transferOrdinals = {
499
+ export const sendOrdinals = {
454
500
  meta: {
455
- name: 'transferOrdinals',
501
+ name: 'sendOrdinals',
456
502
  description: 'Transfer one or more ordinals to new owners',
457
503
  category: 'ordinals',
458
504
  inputSchema: {
@@ -464,9 +510,9 @@ export const transferOrdinals = {
464
510
  items: {
465
511
  type: 'object',
466
512
  properties: {
467
- ordinal: {
468
- type: 'object',
469
- description: 'WalletOutput from listOutputs',
513
+ id: {
514
+ type: 'string',
515
+ description: 'Tracking id in the ordinals basket',
470
516
  },
471
517
  counterparty: {
472
518
  type: 'string',
@@ -481,15 +527,11 @@ export const transferOrdinals = {
481
527
  description: 'Optional MAP metadata to append to the output script',
482
528
  },
483
529
  },
484
- required: ['ordinal'],
530
+ required: ['id'],
485
531
  },
486
532
  },
487
- inputBEEF: {
488
- type: 'array',
489
- description: "BEEF from listOutputs with include: 'entire transactions'",
490
- },
491
533
  },
492
- required: ['transfers', 'inputBEEF'],
534
+ required: ['transfers'],
493
535
  },
494
536
  },
495
537
  async execute(ctx, input) {
@@ -498,7 +540,7 @@ export const transferOrdinals = {
498
540
  if ('error' in params) {
499
541
  return params;
500
542
  }
501
- console.log('[transferOrdinals] params:', JSON.stringify({
543
+ console.log('[sendOrdinals] params:', JSON.stringify({
502
544
  description: params.description,
503
545
  inputBEEF: params.inputBEEF
504
546
  ? `[${params.inputBEEF.length} bytes]`
@@ -512,23 +554,24 @@ export const transferOrdinals = {
512
554
  // Debug: Check if BEEF contains the source transactions
513
555
  try {
514
556
  const beef = Beef.fromBinary(params.inputBEEF);
515
- console.log('[transferOrdinals] BEEF tx count:', beef.txs.length);
557
+ console.log('[sendOrdinals] BEEF tx count:', beef.txs.length);
516
558
  for (const inp of params.inputs ?? []) {
517
559
  const [txid] = inp.outpoint.split('.');
518
560
  const sourceTx = beef.findTxid(txid);
519
- console.log(`[transferOrdinals] Source tx for ${inp.outpoint}: ${sourceTx ? 'FOUND' : 'MISSING'}`);
561
+ console.log(`[sendOrdinals] Source tx for ${inp.outpoint}: ${sourceTx ? 'FOUND' : 'MISSING'}`);
520
562
  }
521
563
  }
522
564
  catch (e) {
523
- console.log('[transferOrdinals] BEEF parse error:', e);
565
+ console.log('[sendOrdinals] BEEF parse error:', e);
524
566
  }
567
+ const { sources, ...createArgs } = params;
525
568
  const result = await executeTrackedAction(ctx.wallet, {
526
- ...params,
569
+ ...createArgs,
527
570
  options: { randomizeOutputs: false },
528
571
  }, input.fundingProvider, params.inputBEEF, async (tx) => {
529
572
  const spends = {};
530
- for (let i = 0; i < input.transfers.length; i++) {
531
- const { ordinal } = input.transfers[i];
573
+ for (let i = 0; i < sources.length; i++) {
574
+ const ordinal = sources[i];
532
575
  if (!ordinal.customInstructions) {
533
576
  throw new Error(`missing-custom-instructions-for-${ordinal.outpoint}`);
534
577
  }
@@ -540,19 +583,19 @@ export const transferOrdinals = {
540
583
  return spends;
541
584
  });
542
585
  if (ctx.debug && ctx.log) {
543
- const logOutputs = input.transfers.map((t, i) => ({
586
+ const logOutputs = sources.map((s, i) => ({
544
587
  index: i,
545
588
  protocolID: P1SAT_PROTOCOL,
546
- keyID: t.ordinal.outpoint,
589
+ keyID: s.outpoint,
547
590
  basket: ORDINALS_BASKET,
548
591
  satoshis: 1,
549
592
  }));
550
593
  ctx.log({
551
594
  timestamp: new Date().toISOString(),
552
- action: 'transferOrdinals',
595
+ action: 'sendOrdinals',
553
596
  input: {
554
597
  transfers: input.transfers.map((t) => ({
555
- outpoint: t.ordinal.outpoint,
598
+ id: t.id,
556
599
  counterparty: t.counterparty,
557
600
  address: t.address,
558
601
  })),
@@ -565,14 +608,14 @@ export const transferOrdinals = {
565
608
  return result;
566
609
  }
567
610
  catch (error) {
568
- console.error('[transferOrdinals]', error);
611
+ console.error('[sendOrdinals]', error);
569
612
  if (ctx.debug && ctx.log) {
570
613
  ctx.log({
571
614
  timestamp: new Date().toISOString(),
572
- action: 'transferOrdinals',
615
+ action: 'sendOrdinals',
573
616
  input: {
574
617
  transfers: input.transfers.map((t) => ({
575
- outpoint: t.ordinal.outpoint,
618
+ id: t.id,
576
619
  })),
577
620
  },
578
621
  error: error instanceof Error ? error.message : 'unknown-error',
@@ -587,33 +630,29 @@ export const transferOrdinals = {
587
630
  /**
588
631
  * List an ordinal for sale on the global orderbook.
589
632
  */
590
- export const listOrdinal = {
633
+ export const sellOrdinal = {
591
634
  meta: {
592
- name: 'listOrdinal',
635
+ name: 'sellOrdinal',
593
636
  description: 'List an ordinal for sale on the global orderbook',
594
637
  category: 'ordinals',
595
638
  inputSchema: {
596
639
  type: 'object',
597
640
  properties: {
598
- ordinal: {
599
- type: 'object',
600
- description: 'WalletOutput from listOutputs',
601
- },
602
- inputBEEF: {
603
- type: 'array',
604
- description: "BEEF from listOutputs with include: 'entire transactions'",
641
+ id: {
642
+ type: 'string',
643
+ description: 'Tracking id in the ordinals basket',
605
644
  },
606
645
  price: { type: 'integer', description: 'Price in satoshis' },
607
646
  payAddress: {
608
647
  type: 'string',
609
- description: 'Address to receive payment on purchase',
648
+ description: 'Address to receive payment (default: P1SAT keyID 1sat 0)',
610
649
  },
611
650
  map: {
612
651
  type: 'object',
613
652
  description: 'Optional MAP metadata to append to the listing output script',
614
653
  },
615
654
  },
616
- required: ['ordinal', 'inputBEEF', 'price', 'payAddress'],
655
+ required: ['id', 'price'],
617
656
  },
618
657
  },
619
658
  async execute(ctx, input) {
@@ -622,14 +661,15 @@ export const listOrdinal = {
622
661
  if ('error' in params) {
623
662
  return params;
624
663
  }
625
- if (!input.ordinal.customInstructions) {
664
+ const { source, ...createArgs } = params;
665
+ if (!source.customInstructions) {
626
666
  return { error: 'missing-custom-instructions' };
627
667
  }
628
668
  const result = await executeTrackedAction(ctx.wallet, {
629
- ...params,
669
+ ...createArgs,
630
670
  options: { randomizeOutputs: false },
631
671
  }, input.fundingProvider, params.inputBEEF, async (tx) => {
632
- const unlocking = await signOrdinalInput(ctx, tx, 0, input.ordinal.customInstructions);
672
+ const unlocking = await signOrdinalInput(ctx, tx, 0, source.customInstructions);
633
673
  if (typeof unlocking !== 'string')
634
674
  throw new Error(unlocking.error);
635
675
  return { 0: { unlockingScript: unlocking } };
@@ -637,15 +677,15 @@ export const listOrdinal = {
637
677
  if (ctx.debug && ctx.log) {
638
678
  ctx.log({
639
679
  timestamp: new Date().toISOString(),
640
- action: 'listOrdinal',
641
- input: { outpoint: input.ordinal.outpoint, price: input.price },
680
+ action: 'sellOrdinal',
681
+ input: { outpoint: source.outpoint, price: input.price },
642
682
  txid: result.txid,
643
683
  rawtx: result.tx ? Utils.toHex(result.tx) : undefined,
644
684
  outputs: [
645
685
  {
646
686
  index: 0,
647
687
  protocolID: P1SAT_PROTOCOL,
648
- keyID: input.ordinal.outpoint,
688
+ keyID: source.outpoint,
649
689
  basket: ORDINALS_BASKET,
650
690
  satoshis: 1,
651
691
  },
@@ -655,12 +695,12 @@ export const listOrdinal = {
655
695
  return result;
656
696
  }
657
697
  catch (error) {
658
- console.error('[listOrdinal]', error);
698
+ console.error('[sellOrdinal]', error);
659
699
  if (ctx.debug && ctx.log) {
660
700
  ctx.log({
661
701
  timestamp: new Date().toISOString(),
662
- action: 'listOrdinal',
663
- input: { outpoint: input.ordinal.outpoint, price: input.price },
702
+ action: 'sellOrdinal',
703
+ input: { price: input.price },
664
704
  error: error instanceof Error ? error.message : 'unknown-error',
665
705
  });
666
706
  }
@@ -673,29 +713,30 @@ export const listOrdinal = {
673
713
  /**
674
714
  * Cancel an ordinal listing.
675
715
  */
676
- export const cancelListing = {
716
+ export const cancelOrdinalListing = {
677
717
  meta: {
678
- name: 'cancelListing',
718
+ name: 'cancelOrdinalListing',
679
719
  description: 'Cancel an ordinal listing and return the ordinal to the wallet',
680
720
  category: 'ordinals',
681
721
  inputSchema: {
682
722
  type: 'object',
683
723
  properties: {
684
- listing: {
685
- type: 'object',
686
- description: 'WalletOutput of the listing (must include lockingScript)',
687
- },
688
- inputBEEF: {
689
- type: 'array',
690
- description: 'BEEF — resolved automatically via ID tag if omitted',
724
+ id: {
725
+ type: 'string',
726
+ description: 'Tracking id of the listing in the ordinals basket',
691
727
  },
692
728
  },
693
- required: ['listing'],
729
+ required: ['id'],
694
730
  },
695
731
  },
696
732
  async execute(ctx, input) {
697
733
  try {
698
- const { listing } = input;
734
+ if (!input.id)
735
+ return { error: 'missing-id' };
736
+ const loaded = await loadOrdinalSpend(ctx, input.id);
737
+ if ('error' in loaded)
738
+ return loaded;
739
+ const { output: listing, beef: inputBEEF } = loaded;
699
740
  const outpoint = listing.outpoint;
700
741
  if (!listing.customInstructions) {
701
742
  return { error: 'missing-custom-instructions' };
@@ -712,18 +753,9 @@ export const cancelListing = {
712
753
  // derivation so the next spend reproduces the same key.
713
754
  const newKeyID = outpoint;
714
755
  const cancelAddress = await deriveCancelAddressInternal(ctx, newKeyID);
715
- const { tags, basket } = await resolveOrdinalTags(ctx, outpoint, {
716
- tags: listing.tags,
717
- });
718
- const inputBEEF = input.inputBEEF ?? (await resolveBeef(ctx.wallet, basket, listing));
719
- let sourceName;
720
- try {
721
- sourceName = JSON.parse(listing.customInstructions).name;
722
- }
723
- catch { }
724
- if (!sourceName) {
725
- sourceName = tags.find((t) => t.startsWith('name:'))?.slice(5);
726
- }
756
+ const tags = ordinalSeedTags(listing);
757
+ const basket = ORDINALS_BASKET;
758
+ const sourceName = nameFromOutput(listing, tags);
727
759
  const cancelUnlock = OrdLock.cancelWithWallet(ctx.wallet, signProtocolID, signKeyID, signCounterparty);
728
760
  const inputId = readAssetIdTag(listing.tags);
729
761
  const result = await executeTrackedAction(ctx.wallet, {
@@ -761,7 +793,7 @@ export const cancelListing = {
761
793
  if (ctx.debug && ctx.log) {
762
794
  ctx.log({
763
795
  timestamp: new Date().toISOString(),
764
- action: 'cancelListing',
796
+ action: 'cancelOrdinalListing',
765
797
  input: { outpoint, signKeyID },
766
798
  txid: result.txid,
767
799
  rawtx: result.tx ? Utils.toHex(result.tx) : undefined,
@@ -778,12 +810,12 @@ export const cancelListing = {
778
810
  return result;
779
811
  }
780
812
  catch (error) {
781
- console.error('[cancelListing]', error);
813
+ console.error('[cancelOrdinalListing]', error);
782
814
  if (ctx.debug && ctx.log) {
783
815
  ctx.log({
784
816
  timestamp: new Date().toISOString(),
785
- action: 'cancelListing',
786
- input: { outpoint: input.listing.outpoint },
817
+ action: 'cancelOrdinalListing',
818
+ input: { id: input.id },
787
819
  error: error instanceof Error ? error.message : 'unknown-error',
788
820
  });
789
821
  }
@@ -796,9 +828,9 @@ export const cancelListing = {
796
828
  /**
797
829
  * Purchase an ordinal from the global orderbook.
798
830
  */
799
- export const purchaseOrdinal = {
831
+ export const buyOrdinal = {
800
832
  meta: {
801
- name: 'purchaseOrdinal',
833
+ name: 'buyOrdinal',
802
834
  description: 'Purchase an ordinal from the global orderbook',
803
835
  category: 'ordinals',
804
836
  requiresServices: true,
@@ -809,6 +841,11 @@ export const purchaseOrdinal = {
809
841
  type: 'string',
810
842
  description: 'Outpoint of the listing to purchase',
811
843
  },
844
+ inputBEEF: {
845
+ type: 'array',
846
+ description: 'BEEF for listing tx; else services fetch',
847
+ items: { type: 'integer' },
848
+ },
812
849
  marketplaceAddress: {
813
850
  type: 'string',
814
851
  description: 'Marketplace address for fees',
@@ -832,16 +869,32 @@ export const purchaseOrdinal = {
832
869
  async execute(ctx, input) {
833
870
  try {
834
871
  const { outpoint, marketplaceAddress, marketplaceRate } = input;
835
- if (!ctx.services) {
836
- return { error: 'services-required-for-purchase' };
837
- }
838
872
  const { txid, vout } = parseOutpoint(outpoint);
839
- const { tags, basket } = await resolveOrdinalTags(ctx, outpoint, {
840
- contentType: input.contentType,
841
- origin: input.origin,
842
- name: input.name,
843
- });
844
- const beef = await ctx.services.getBeefForTxid(txid);
873
+ let tags;
874
+ let basket;
875
+ if (input.tags?.length) {
876
+ basket = input.basket ?? ORDINALS_BASKET;
877
+ tags = input.tags;
878
+ }
879
+ else {
880
+ const resolved = await resolveOrdinalTags(ctx, outpoint, {
881
+ contentType: input.contentType,
882
+ origin: input.origin,
883
+ name: input.name,
884
+ });
885
+ tags = resolved.tags;
886
+ basket = input.basket ?? resolved.basket;
887
+ }
888
+ let beef;
889
+ if (input.inputBEEF) {
890
+ beef = Beef.fromBinary(input.inputBEEF);
891
+ }
892
+ else {
893
+ if (!ctx.services) {
894
+ return { error: 'services-required-for-purchase' };
895
+ }
896
+ beef = await ctx.services.getBeefForTxid(txid);
897
+ }
845
898
  const listingBeefTx = beef.findTxid(txid);
846
899
  if (!listingBeefTx?.tx) {
847
900
  return { error: 'listing-transaction-not-found' };
@@ -862,6 +915,7 @@ export const purchaseOrdinal = {
862
915
  });
863
916
  const ourOrdAddress = PublicKey.fromString(publicKey).toAddress();
864
917
  const outputs = [];
918
+ const name = input.name ?? tags.find((t) => t.startsWith('name:'))?.slice(5);
865
919
  outputs.push({
866
920
  lockingScript: new P2PKH().lock(ourOrdAddress).toHex(),
867
921
  satoshis: 1,
@@ -871,7 +925,7 @@ export const purchaseOrdinal = {
871
925
  customInstructions: JSON.stringify({
872
926
  protocolID: P1SAT_PROTOCOL,
873
927
  keyID: outpoint,
874
- ...(input.name && { name: input.name }),
928
+ ...(name && { name }),
875
929
  }),
876
930
  });
877
931
  const payoutReader = new Utils.Reader(ordLockData.payout);
@@ -916,7 +970,7 @@ export const purchaseOrdinal = {
916
970
  if (ctx.debug && ctx.log) {
917
971
  ctx.log({
918
972
  timestamp: new Date().toISOString(),
919
- action: 'purchaseOrdinal',
973
+ action: 'buyOrdinal',
920
974
  input: { outpoint },
921
975
  txid: result.txid,
922
976
  rawtx: result.tx ? Utils.toHex(result.tx) : undefined,
@@ -934,11 +988,11 @@ export const purchaseOrdinal = {
934
988
  return result;
935
989
  }
936
990
  catch (error) {
937
- console.error('[purchaseOrdinal]', error);
991
+ console.error('[buyOrdinal]', error);
938
992
  if (ctx.debug && ctx.log) {
939
993
  ctx.log({
940
994
  timestamp: new Date().toISOString(),
941
- action: 'purchaseOrdinal',
995
+ action: 'buyOrdinal',
942
996
  input: { outpoint: input.outpoint },
943
997
  error: error instanceof Error ? error.message : 'unknown-error',
944
998
  });
@@ -950,7 +1004,7 @@ export const purchaseOrdinal = {
950
1004
  },
951
1005
  };
952
1006
  /**
953
- * Burn one or more ordinals (send to OP_FALSE OP_RETURN).
1007
+ * Burn one or more ordinals.
954
1008
  */
955
1009
  export const burnOrdinals = {
956
1010
  meta: {
@@ -960,20 +1014,13 @@ export const burnOrdinals = {
960
1014
  inputSchema: {
961
1015
  type: 'object',
962
1016
  properties: {
963
- ordinals: {
1017
+ ids: {
964
1018
  type: 'array',
965
- description: 'WalletOutputs to burn',
966
- items: {
967
- type: 'object',
968
- description: 'WalletOutput from listOutputs',
969
- },
970
- },
971
- inputBEEF: {
972
- type: 'array',
973
- description: 'BEEF — resolved automatically via ID tag if omitted',
1019
+ description: 'Tracking ids in the ordinals basket',
1020
+ items: { type: 'string' },
974
1021
  },
975
1022
  },
976
- required: ['ordinals'],
1023
+ required: ['ids'],
977
1024
  },
978
1025
  },
979
1026
  async execute(ctx, input) {
@@ -982,24 +1029,14 @@ export const burnOrdinals = {
982
1029
  if ('error' in params) {
983
1030
  return params;
984
1031
  }
985
- console.log('[burnOrdinals] params:', JSON.stringify({
986
- description: params.description,
987
- inputBEEF: params.inputBEEF
988
- ? `[${params.inputBEEF.length} bytes]`
989
- : 'undefined',
990
- inputs: params.inputs,
991
- outputs: params.outputs?.map((o) => ({
992
- ...o,
993
- lockingScript: `${o.lockingScript?.slice(0, 20)}...`,
994
- })),
995
- }, null, 2));
1032
+ const { sources, ...createArgs } = params;
996
1033
  const result = await executeTrackedAction(ctx.wallet, {
997
- ...params,
1034
+ ...createArgs,
998
1035
  options: { randomizeOutputs: false },
999
1036
  }, input.fundingProvider, params.inputBEEF, async (tx) => {
1000
1037
  const spends = {};
1001
- for (let i = 0; i < input.ordinals.length; i++) {
1002
- const ordinal = input.ordinals[i];
1038
+ for (let i = 0; i < sources.length; i++) {
1039
+ const ordinal = sources[i];
1003
1040
  if (!ordinal.customInstructions) {
1004
1041
  throw new Error(`missing-custom-instructions-for-${ordinal.outpoint}`);
1005
1042
  }
@@ -1014,11 +1051,7 @@ export const burnOrdinals = {
1014
1051
  ctx.log({
1015
1052
  timestamp: new Date().toISOString(),
1016
1053
  action: 'burnOrdinals',
1017
- input: {
1018
- ordinals: input.ordinals.map((o) => ({
1019
- outpoint: o.outpoint,
1020
- })),
1021
- },
1054
+ input: { ids: input.ids },
1022
1055
  txid: result.txid,
1023
1056
  rawtx: result.tx ? Utils.toHex(result.tx) : undefined,
1024
1057
  });
@@ -1031,11 +1064,7 @@ export const burnOrdinals = {
1031
1064
  ctx.log({
1032
1065
  timestamp: new Date().toISOString(),
1033
1066
  action: 'burnOrdinals',
1034
- input: {
1035
- ordinals: input.ordinals.map((o) => ({
1036
- outpoint: o.outpoint,
1037
- })),
1038
- },
1067
+ input: { ids: input.ids },
1039
1068
  error: error instanceof Error ? error.message : 'unknown-error',
1040
1069
  });
1041
1070
  }
@@ -1050,11 +1079,11 @@ export const burnOrdinals = {
1050
1079
  // ============================================================================
1051
1080
  /** All ordinals actions for registry */
1052
1081
  export const ordinalsActions = [
1053
- getOrdinals,
1054
- transferOrdinals,
1055
- listOrdinal,
1056
- cancelListing,
1057
- purchaseOrdinal,
1082
+ listOrdinals,
1083
+ sendOrdinals,
1084
+ sellOrdinal,
1085
+ cancelOrdinalListing,
1086
+ buyOrdinal,
1058
1087
  burnOrdinals,
1059
1088
  ];
1060
1089
  //# sourceMappingURL=index.js.map