@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: [`type:${input.contentType}`],
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
- if (!result.outputs.find((o) => o.outpoint === outpoint)) {
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: [`type:${contentType}`, `origin:${origin}`],
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);
@@ -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 {
@@ -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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1sat/wallet-toolbox",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "description": "BSV wallet library extending @bsv/wallet-toolbox with 1Sat Ordinals protocol support",
5
5
  "author": "1Sat Team",
6
6
  "license": "MIT",