@1sat/wallet-toolbox 0.0.25 → 0.0.27
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.
|
@@ -61,6 +61,11 @@ export const inscribe = {
|
|
|
61
61
|
});
|
|
62
62
|
const address = PublicKey.fromString(publicKey).toAddress();
|
|
63
63
|
const lockingScript = buildInscriptionScript(address, input.base64Content, input.contentType);
|
|
64
|
+
// Build tags - type is always included, name from MAP if provided
|
|
65
|
+
const tags = [`type:${input.contentType}`];
|
|
66
|
+
if (input.map?.name) {
|
|
67
|
+
tags.push(`name:${input.map.name}`);
|
|
68
|
+
}
|
|
64
69
|
const result = await ctx.wallet.createAction({
|
|
65
70
|
description: "Create inscription",
|
|
66
71
|
outputs: [
|
|
@@ -69,10 +74,11 @@ export const inscribe = {
|
|
|
69
74
|
satoshis: 1,
|
|
70
75
|
outputDescription: "Inscription",
|
|
71
76
|
basket: ORDINALS_BASKET,
|
|
72
|
-
tags
|
|
77
|
+
tags,
|
|
73
78
|
customInstructions: JSON.stringify({
|
|
74
79
|
protocolID: ONESAT_PROTOCOL,
|
|
75
80
|
keyID,
|
|
81
|
+
...(input.map?.name && { name: input.map.name.slice(0, 64) }),
|
|
76
82
|
}),
|
|
77
83
|
},
|
|
78
84
|
],
|
|
@@ -36,6 +36,8 @@ export interface PurchaseOrdinalRequest {
|
|
|
36
36
|
contentType?: string;
|
|
37
37
|
/** Optional origin outpoint - looked up from ordfs API if not provided */
|
|
38
38
|
origin?: string;
|
|
39
|
+
/** Optional name from MAP metadata - looked up from ordfs API if not provided */
|
|
40
|
+
name?: string;
|
|
39
41
|
}
|
|
40
42
|
export interface OrdinalOperationResponse {
|
|
41
43
|
txid?: string;
|
|
@@ -8,6 +8,20 @@ import { BigNumber, Hash, LockingScript, OP, P2PKH, PublicKey, Script, Transacti
|
|
|
8
8
|
import { OrdLock } from "@bopen-io/templates";
|
|
9
9
|
import { ORDINALS_BASKET, ORDLOCK_PREFIX, ORDLOCK_SUFFIX, ONESAT_PROTOCOL } from "../constants";
|
|
10
10
|
// ============================================================================
|
|
11
|
+
// Helpers
|
|
12
|
+
// ============================================================================
|
|
13
|
+
function extractName(customInstructions) {
|
|
14
|
+
if (!customInstructions)
|
|
15
|
+
return undefined;
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(customInstructions);
|
|
18
|
+
return parsed.name;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ============================================================================
|
|
11
25
|
// Internal helpers
|
|
12
26
|
// ============================================================================
|
|
13
27
|
async function deriveCancelAddressInternal(ctx, outpoint) {
|
|
@@ -107,12 +121,23 @@ export async function buildTransferOrdinal(ctx, request) {
|
|
|
107
121
|
}
|
|
108
122
|
const result = await ctx.wallet.listOutputs({
|
|
109
123
|
basket: ORDINALS_BASKET,
|
|
124
|
+
includeTags: true,
|
|
125
|
+
includeCustomInstructions: true,
|
|
110
126
|
include: "locking scripts",
|
|
111
127
|
limit: 10000,
|
|
112
128
|
});
|
|
113
|
-
|
|
129
|
+
const sourceOutput = result.outputs.find((o) => o.outpoint === outpoint);
|
|
130
|
+
if (!sourceOutput) {
|
|
114
131
|
return { error: "ordinal-not-found" };
|
|
115
132
|
}
|
|
133
|
+
// Preserve important tags from source output
|
|
134
|
+
const tags = [];
|
|
135
|
+
for (const tag of sourceOutput.tags ?? []) {
|
|
136
|
+
if (tag.startsWith("type:") || tag.startsWith("origin:") || tag.startsWith("name:")) {
|
|
137
|
+
tags.push(tag);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const sourceName = extractName(sourceOutput.customInstructions);
|
|
116
141
|
return {
|
|
117
142
|
description: "Transfer ordinal",
|
|
118
143
|
inputs: [{ outpoint, inputDescription: "Ordinal to transfer" }],
|
|
@@ -121,6 +146,13 @@ export async function buildTransferOrdinal(ctx, request) {
|
|
|
121
146
|
lockingScript: new P2PKH().lock(recipientAddress).toHex(),
|
|
122
147
|
satoshis: 1,
|
|
123
148
|
outputDescription: "Ordinal transfer",
|
|
149
|
+
basket: ORDINALS_BASKET,
|
|
150
|
+
tags,
|
|
151
|
+
customInstructions: JSON.stringify({
|
|
152
|
+
protocolID: ONESAT_PROTOCOL,
|
|
153
|
+
keyID: outpoint,
|
|
154
|
+
...(sourceName && { name: sourceName }),
|
|
155
|
+
}),
|
|
124
156
|
},
|
|
125
157
|
],
|
|
126
158
|
};
|
|
@@ -138,6 +170,7 @@ export async function buildListOrdinal(ctx, request) {
|
|
|
138
170
|
const result = await ctx.wallet.listOutputs({
|
|
139
171
|
basket: ORDINALS_BASKET,
|
|
140
172
|
includeTags: true,
|
|
173
|
+
includeCustomInstructions: true,
|
|
141
174
|
include: "locking scripts",
|
|
142
175
|
limit: 10000,
|
|
143
176
|
});
|
|
@@ -147,12 +180,16 @@ export async function buildListOrdinal(ctx, request) {
|
|
|
147
180
|
}
|
|
148
181
|
const typeTag = sourceOutput.tags?.find((t) => t.startsWith("type:"));
|
|
149
182
|
const originTag = sourceOutput.tags?.find((t) => t.startsWith("origin:"));
|
|
183
|
+
const nameTag = sourceOutput.tags?.find((t) => t.startsWith("name:"));
|
|
150
184
|
const originOutpoint = originTag ? originTag.slice(7) : outpoint;
|
|
185
|
+
const sourceName = extractName(sourceOutput.customInstructions);
|
|
151
186
|
const cancelAddress = await deriveCancelAddressInternal(ctx, outpoint);
|
|
152
187
|
const lockingScript = buildOrdLockScript(cancelAddress, payAddress, price);
|
|
153
188
|
const tags = ["ordlock", `origin:${originOutpoint}`, `price:${price}`];
|
|
154
189
|
if (typeTag)
|
|
155
190
|
tags.push(typeTag);
|
|
191
|
+
if (nameTag)
|
|
192
|
+
tags.push(nameTag);
|
|
156
193
|
return {
|
|
157
194
|
description: `List ordinal for ${price} sats`,
|
|
158
195
|
inputs: [{ outpoint, inputDescription: "Ordinal to list" }],
|
|
@@ -166,6 +203,7 @@ export async function buildListOrdinal(ctx, request) {
|
|
|
166
203
|
customInstructions: JSON.stringify({
|
|
167
204
|
protocolID: ONESAT_PROTOCOL,
|
|
168
205
|
keyID: outpoint,
|
|
206
|
+
...(sourceName && { name: sourceName }),
|
|
169
207
|
}),
|
|
170
208
|
},
|
|
171
209
|
],
|
|
@@ -328,15 +366,18 @@ export const cancelListing = {
|
|
|
328
366
|
if (!listing.customInstructions) {
|
|
329
367
|
return { error: "missing-custom-instructions" };
|
|
330
368
|
}
|
|
331
|
-
const { protocolID, keyID } = JSON.parse(listing.customInstructions);
|
|
369
|
+
const { protocolID, keyID, name: listingName } = JSON.parse(listing.customInstructions);
|
|
332
370
|
const typeTag = listing.tags?.find((t) => t.startsWith("type:"));
|
|
333
371
|
const originTag = listing.tags?.find((t) => t.startsWith("origin:"));
|
|
372
|
+
const nameTag = listing.tags?.find((t) => t.startsWith("name:"));
|
|
334
373
|
const cancelAddress = await deriveCancelAddressInternal(ctx, keyID);
|
|
335
374
|
const tags = [];
|
|
336
375
|
if (typeTag)
|
|
337
376
|
tags.push(typeTag);
|
|
338
377
|
if (originTag)
|
|
339
378
|
tags.push(originTag);
|
|
379
|
+
if (nameTag)
|
|
380
|
+
tags.push(nameTag);
|
|
340
381
|
const createResult = await ctx.wallet.createAction({
|
|
341
382
|
description: "Cancel ordinal listing",
|
|
342
383
|
inputs: [
|
|
@@ -353,7 +394,7 @@ export const cancelListing = {
|
|
|
353
394
|
outputDescription: "Cancelled listing",
|
|
354
395
|
basket: ORDINALS_BASKET,
|
|
355
396
|
tags,
|
|
356
|
-
customInstructions: JSON.stringify({ protocolID, keyID }),
|
|
397
|
+
customInstructions: JSON.stringify({ protocolID, keyID, ...(listingName && { name: listingName }) }),
|
|
357
398
|
},
|
|
358
399
|
],
|
|
359
400
|
options: { signAndProcess: false, randomizeOutputs: false },
|
|
@@ -454,11 +495,18 @@ export const purchaseOrdinal = {
|
|
|
454
495
|
}
|
|
455
496
|
const [txid, voutStr] = parts;
|
|
456
497
|
const vout = Number.parseInt(voutStr, 10);
|
|
457
|
-
let { contentType, origin } = input;
|
|
458
|
-
if (!contentType || !origin) {
|
|
498
|
+
let { contentType, origin, name } = input;
|
|
499
|
+
if (!contentType || !origin || name === undefined) {
|
|
459
500
|
const metadata = await ctx.services.ordfs.getMetadata(outpoint);
|
|
460
501
|
contentType = contentType ?? metadata.contentType;
|
|
461
502
|
origin = origin ?? metadata.origin ?? outpoint;
|
|
503
|
+
// Extract name from map.name or map.subTypeData.name
|
|
504
|
+
if (name === undefined && metadata.map) {
|
|
505
|
+
const mapName = metadata.map.name;
|
|
506
|
+
const subTypeData = metadata.map.subTypeData;
|
|
507
|
+
name = (typeof mapName === "string" ? mapName : undefined) ??
|
|
508
|
+
(typeof subTypeData?.name === "string" ? subTypeData.name : undefined);
|
|
509
|
+
}
|
|
462
510
|
}
|
|
463
511
|
const beef = await ctx.services.getBeefForTxid(txid);
|
|
464
512
|
const listingBeefTx = beef.findTxid(txid);
|
|
@@ -482,15 +530,19 @@ export const purchaseOrdinal = {
|
|
|
482
530
|
const ourOrdAddress = PublicKey.fromString(publicKey).toAddress();
|
|
483
531
|
const outputs = [];
|
|
484
532
|
const p2pkh = new P2PKH();
|
|
533
|
+
const purchaseTags = [`type:${contentType}`, `origin:${origin}`];
|
|
534
|
+
if (name)
|
|
535
|
+
purchaseTags.push(`name:${name}`);
|
|
485
536
|
outputs.push({
|
|
486
537
|
lockingScript: p2pkh.lock(ourOrdAddress).toHex(),
|
|
487
538
|
satoshis: 1,
|
|
488
539
|
outputDescription: "Purchased ordinal",
|
|
489
540
|
basket: ORDINALS_BASKET,
|
|
490
|
-
tags:
|
|
541
|
+
tags: purchaseTags,
|
|
491
542
|
customInstructions: JSON.stringify({
|
|
492
543
|
protocolID: ONESAT_PROTOCOL,
|
|
493
544
|
keyID: outpoint,
|
|
545
|
+
...(name && { name: name.slice(0, 64) }),
|
|
494
546
|
}),
|
|
495
547
|
});
|
|
496
548
|
const payoutReader = new Utils.Reader(ordLockData.payout);
|
package/dist/api/sweep/index.js
CHANGED
|
@@ -244,6 +244,7 @@ export const sweepOrdinals = {
|
|
|
244
244
|
lockingScript: { type: "string", description: "Locking script hex" },
|
|
245
245
|
contentType: { type: "string", description: "Content type from metadata" },
|
|
246
246
|
origin: { type: "string", description: "Origin outpoint" },
|
|
247
|
+
name: { type: "string", description: "Name from MAP metadata" },
|
|
247
248
|
},
|
|
248
249
|
required: ["outpoint", "satoshis", "lockingScript"],
|
|
249
250
|
},
|
|
@@ -316,6 +317,7 @@ export const sweepOrdinals = {
|
|
|
316
317
|
customInstructions: JSON.stringify({
|
|
317
318
|
protocolID: ONESAT_PROTOCOL,
|
|
318
319
|
keyID: input.outpoint,
|
|
320
|
+
...(input.name && { name: input.name.slice(0, 64) }),
|
|
319
321
|
}),
|
|
320
322
|
});
|
|
321
323
|
}
|
|
@@ -34,6 +34,8 @@ export interface SweepOrdinalInput extends SweepInput {
|
|
|
34
34
|
contentType?: string;
|
|
35
35
|
/** Origin outpoint for tracking */
|
|
36
36
|
origin?: string;
|
|
37
|
+
/** Name from MAP metadata */
|
|
38
|
+
name?: string;
|
|
37
39
|
}
|
|
38
40
|
/** Request to sweep ordinals */
|
|
39
41
|
export interface SweepOrdinalsRequest {
|
package/dist/sync/SyncManager.js
CHANGED
|
@@ -352,17 +352,18 @@ export class SyncProcessor {
|
|
|
352
352
|
// These outputs need custom unlock scripts when spent
|
|
353
353
|
const basket = txo.basket || "custom";
|
|
354
354
|
const tags = this.collectTags(txo);
|
|
355
|
+
const nameTag = tags.find((t) => t.startsWith("name:"));
|
|
355
356
|
return {
|
|
356
357
|
outputIndex: vout,
|
|
357
358
|
protocol: "basket insertion",
|
|
358
359
|
insertionRemittance: {
|
|
359
360
|
basket,
|
|
360
361
|
tags,
|
|
361
|
-
// Store derivation info for future signing
|
|
362
362
|
customInstructions: JSON.stringify({
|
|
363
363
|
derivationPrefix: derivation.derivationPrefix,
|
|
364
364
|
derivationSuffix: derivation.derivationSuffix,
|
|
365
365
|
senderIdentityKey: derivation.senderIdentityKey,
|
|
366
|
+
...(nameTag && { name: nameTag.slice(5).slice(0, 64) }),
|
|
366
367
|
}),
|
|
367
368
|
},
|
|
368
369
|
};
|