@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.
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/inscriptions/index.d.ts +2 -2
- package/dist/inscriptions/index.d.ts.map +1 -1
- package/dist/inscriptions/index.js +3 -6
- package/dist/inscriptions/index.js.map +1 -1
- package/dist/locks/index.d.ts +32 -3
- package/dist/locks/index.d.ts.map +1 -1
- package/dist/locks/index.js +76 -5
- package/dist/locks/index.js.map +1 -1
- package/dist/opns/index.d.ts +43 -76
- package/dist/opns/index.d.ts.map +1 -1
- package/dist/opns/index.js +420 -234
- package/dist/opns/index.js.map +1 -1
- package/dist/ordinals/index.d.ts +58 -44
- package/dist/ordinals/index.d.ts.map +1 -1
- package/dist/ordinals/index.js +217 -188
- package/dist/ordinals/index.js.map +1 -1
- package/dist/tokens/index.d.ts +3 -3
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +38 -24
- package/dist/tokens/index.js.map +1 -1
- package/dist/utils/createTrackedAction.js +1 -1
- package/dist/utils/internalizeBeef.d.ts.map +1 -1
- package/dist/utils/internalizeBeef.js +1 -25
- package/dist/utils/internalizeBeef.js.map +1 -1
- package/dist/utils/loadBasketOutput.d.ts +25 -0
- package/dist/utils/loadBasketOutput.d.ts.map +1 -0
- package/dist/utils/loadBasketOutput.js +50 -0
- package/dist/utils/loadBasketOutput.js.map +1 -0
- package/dist/utils/ordinalSeedTags.d.ts +8 -0
- package/dist/utils/ordinalSeedTags.d.ts.map +1 -0
- package/dist/utils/ordinalSeedTags.js +24 -0
- package/dist/utils/ordinalSeedTags.js.map +1 -0
- package/package.json +9 -9
- package/dist/utils/resolveBeef.d.ts +0 -20
- package/dist/utils/resolveBeef.d.ts.map +0 -1
- package/dist/utils/resolveBeef.js +0 -36
- package/dist/utils/resolveBeef.js.map +0 -1
package/dist/ordinals/index.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
188
|
-
|
|
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
|
|
219
|
-
|
|
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
|
-
|
|
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
|
-
|
|
289
|
-
|
|
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
|
-
*
|
|
323
|
+
* Loads id once from the ordinals basket.
|
|
303
324
|
*/
|
|
304
325
|
export async function buildListOrdinal(ctx, request) {
|
|
305
|
-
const {
|
|
306
|
-
if (!
|
|
307
|
-
return { error: 'missing-
|
|
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
|
|
329
|
-
|
|
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
|
|
375
|
-
|
|
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
|
-
*
|
|
439
|
+
* List ordinals in the wallet. Metadata (tags/CI) by default; BEEF on demand.
|
|
415
440
|
*/
|
|
416
|
-
export const
|
|
441
|
+
export const listOrdinals = {
|
|
417
442
|
meta: {
|
|
418
|
-
name: '
|
|
419
|
-
description: '
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
|
499
|
+
export const sendOrdinals = {
|
|
454
500
|
meta: {
|
|
455
|
-
name: '
|
|
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
|
-
|
|
468
|
-
type: '
|
|
469
|
-
description: '
|
|
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: ['
|
|
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'
|
|
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('[
|
|
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('[
|
|
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(`[
|
|
561
|
+
console.log(`[sendOrdinals] Source tx for ${inp.outpoint}: ${sourceTx ? 'FOUND' : 'MISSING'}`);
|
|
520
562
|
}
|
|
521
563
|
}
|
|
522
564
|
catch (e) {
|
|
523
|
-
console.log('[
|
|
565
|
+
console.log('[sendOrdinals] BEEF parse error:', e);
|
|
524
566
|
}
|
|
567
|
+
const { sources, ...createArgs } = params;
|
|
525
568
|
const result = await executeTrackedAction(ctx.wallet, {
|
|
526
|
-
...
|
|
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 <
|
|
531
|
-
const
|
|
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 =
|
|
586
|
+
const logOutputs = sources.map((s, i) => ({
|
|
544
587
|
index: i,
|
|
545
588
|
protocolID: P1SAT_PROTOCOL,
|
|
546
|
-
keyID:
|
|
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: '
|
|
595
|
+
action: 'sendOrdinals',
|
|
553
596
|
input: {
|
|
554
597
|
transfers: input.transfers.map((t) => ({
|
|
555
|
-
|
|
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('[
|
|
611
|
+
console.error('[sendOrdinals]', error);
|
|
569
612
|
if (ctx.debug && ctx.log) {
|
|
570
613
|
ctx.log({
|
|
571
614
|
timestamp: new Date().toISOString(),
|
|
572
|
-
action: '
|
|
615
|
+
action: 'sendOrdinals',
|
|
573
616
|
input: {
|
|
574
617
|
transfers: input.transfers.map((t) => ({
|
|
575
|
-
|
|
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
|
|
633
|
+
export const sellOrdinal = {
|
|
591
634
|
meta: {
|
|
592
|
-
name: '
|
|
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
|
-
|
|
599
|
-
type: '
|
|
600
|
-
description: '
|
|
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
|
|
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: ['
|
|
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
|
-
|
|
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
|
-
...
|
|
669
|
+
...createArgs,
|
|
630
670
|
options: { randomizeOutputs: false },
|
|
631
671
|
}, input.fundingProvider, params.inputBEEF, async (tx) => {
|
|
632
|
-
const unlocking = await signOrdinalInput(ctx, tx, 0,
|
|
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: '
|
|
641
|
-
input: { outpoint:
|
|
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:
|
|
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('[
|
|
698
|
+
console.error('[sellOrdinal]', error);
|
|
659
699
|
if (ctx.debug && ctx.log) {
|
|
660
700
|
ctx.log({
|
|
661
701
|
timestamp: new Date().toISOString(),
|
|
662
|
-
action: '
|
|
663
|
-
input: {
|
|
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
|
|
716
|
+
export const cancelOrdinalListing = {
|
|
677
717
|
meta: {
|
|
678
|
-
name: '
|
|
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
|
-
|
|
685
|
-
type: '
|
|
686
|
-
description: '
|
|
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: ['
|
|
729
|
+
required: ['id'],
|
|
694
730
|
},
|
|
695
731
|
},
|
|
696
732
|
async execute(ctx, input) {
|
|
697
733
|
try {
|
|
698
|
-
|
|
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
|
|
716
|
-
|
|
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: '
|
|
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('[
|
|
813
|
+
console.error('[cancelOrdinalListing]', error);
|
|
782
814
|
if (ctx.debug && ctx.log) {
|
|
783
815
|
ctx.log({
|
|
784
816
|
timestamp: new Date().toISOString(),
|
|
785
|
-
action: '
|
|
786
|
-
input: {
|
|
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
|
|
831
|
+
export const buyOrdinal = {
|
|
800
832
|
meta: {
|
|
801
|
-
name: '
|
|
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
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
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
|
-
...(
|
|
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: '
|
|
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('[
|
|
991
|
+
console.error('[buyOrdinal]', error);
|
|
938
992
|
if (ctx.debug && ctx.log) {
|
|
939
993
|
ctx.log({
|
|
940
994
|
timestamp: new Date().toISOString(),
|
|
941
|
-
action: '
|
|
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
|
|
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
|
-
|
|
1017
|
+
ids: {
|
|
964
1018
|
type: 'array',
|
|
965
|
-
description: '
|
|
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: ['
|
|
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
|
-
|
|
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
|
-
...
|
|
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 <
|
|
1002
|
-
const ordinal =
|
|
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
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1082
|
+
listOrdinals,
|
|
1083
|
+
sendOrdinals,
|
|
1084
|
+
sellOrdinal,
|
|
1085
|
+
cancelOrdinalListing,
|
|
1086
|
+
buyOrdinal,
|
|
1058
1087
|
burnOrdinals,
|
|
1059
1088
|
];
|
|
1060
1089
|
//# sourceMappingURL=index.js.map
|