@ardrive/turbo-sdk 1.42.0-alpha.1 → 1.42.0-alpha.3

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 (53) hide show
  1. package/lib/cjs/cli/cli.js +46 -0
  2. package/lib/cjs/cli/commands/arns.js +249 -0
  3. package/lib/cjs/cli/commands/index.js +1 -0
  4. package/lib/cjs/cli/options.js +97 -1
  5. package/lib/cjs/common/http.js +4 -3
  6. package/lib/cjs/common/index.js +3 -0
  7. package/lib/cjs/common/payment.js +199 -0
  8. package/lib/cjs/common/signer.js +15 -3
  9. package/lib/cjs/common/turbo.js +44 -0
  10. package/lib/cjs/types.js +8 -1
  11. package/lib/cjs/utils/errors.js +19 -1
  12. package/lib/cjs/utils/uuid.js +31 -0
  13. package/lib/cjs/web/signer.js +4 -2
  14. package/lib/esm/cli/cli.js +47 -1
  15. package/lib/esm/cli/commands/arns.js +233 -0
  16. package/lib/esm/cli/commands/index.js +1 -0
  17. package/lib/esm/cli/options.js +96 -0
  18. package/lib/esm/common/http.js +4 -3
  19. package/lib/esm/common/index.js +3 -0
  20. package/lib/esm/common/payment.js +199 -0
  21. package/lib/esm/common/signer.js +15 -3
  22. package/lib/esm/common/turbo.js +44 -0
  23. package/lib/esm/types.js +7 -0
  24. package/lib/esm/utils/errors.js +17 -0
  25. package/lib/esm/utils/uuid.js +28 -0
  26. package/lib/esm/web/signer.js +4 -2
  27. package/lib/types/cli/commands/arns.d.ts +88 -0
  28. package/lib/types/cli/commands/arns.d.ts.map +1 -0
  29. package/lib/types/cli/commands/index.d.ts +1 -0
  30. package/lib/types/cli/commands/index.d.ts.map +1 -1
  31. package/lib/types/cli/options.d.ts +201 -0
  32. package/lib/types/cli/options.d.ts.map +1 -1
  33. package/lib/types/cli/types.d.ts +27 -0
  34. package/lib/types/cli/types.d.ts.map +1 -1
  35. package/lib/types/common/http.d.ts +2 -1
  36. package/lib/types/common/http.d.ts.map +1 -1
  37. package/lib/types/common/index.d.ts +1 -0
  38. package/lib/types/common/index.d.ts.map +1 -1
  39. package/lib/types/common/payment.d.ts +64 -1
  40. package/lib/types/common/payment.d.ts.map +1 -1
  41. package/lib/types/common/signer.d.ts +2 -6
  42. package/lib/types/common/signer.d.ts.map +1 -1
  43. package/lib/types/common/turbo.d.ts +53 -1
  44. package/lib/types/common/turbo.d.ts.map +1 -1
  45. package/lib/types/types.d.ts +136 -2
  46. package/lib/types/types.d.ts.map +1 -1
  47. package/lib/types/utils/errors.d.ts +14 -0
  48. package/lib/types/utils/errors.d.ts.map +1 -1
  49. package/lib/types/utils/uuid.d.ts +7 -0
  50. package/lib/types/utils/uuid.d.ts.map +1 -0
  51. package/lib/types/web/signer.d.ts +1 -1
  52. package/lib/types/web/signer.d.ts.map +1 -1
  53. package/package.json +2 -2
@@ -17,7 +17,10 @@ exports.TurboAuthenticatedPaymentService = exports.TurboUnauthenticatedPaymentSe
17
17
  * limitations under the License.
18
18
  */
19
19
  const bignumber_js_1 = require("bignumber.js");
20
+ const types_js_1 = require("../types.js");
20
21
  const common_js_1 = require("../utils/common.js");
22
+ const errors_js_1 = require("../utils/errors.js");
23
+ const uuid_js_1 = require("../utils/uuid.js");
21
24
  const http_js_1 = require("./http.js");
22
25
  const http_js_2 = require("./http.js");
23
26
  const logger_js_1 = require("./logger.js");
@@ -94,6 +97,90 @@ class TurboUnauthenticatedPaymentService {
94
97
  equivalentWincTokenAmount: actualPaymentAmount.toString(),
95
98
  };
96
99
  }
100
+ async getArNSPriceForName(params) {
101
+ // `async` so a validation failure surfaces as a rejected promise (consistent
102
+ // with `purchaseArNSName`) rather than a synchronous throw.
103
+ this.validateArNSPurchaseParams(params);
104
+ return this.httpService.get({
105
+ endpoint: `/arns/price/${params.intent.toLowerCase()}/${params.name}${this.buildArNSPurchaseQuery(params)}`,
106
+ });
107
+ }
108
+ /**
109
+ * Fail fast (client-side) on malformed ArNS requests so JS callers that bypass
110
+ * the compile-time intent unions get a clear `ProvidedInputError` instead of an
111
+ * opaque service 4xx. Enforces the required fields per intent:
112
+ * - `Buy-Name`: `type` ('lease' | 'permabuy'); leases also need `years`.
113
+ * `processId` is OPTIONAL — omit it to have the bundler custodially
114
+ * provision the ANT (Turbo owns it), supply it for a user-owned ANT.
115
+ * - `Extend-Lease`: positive `years`
116
+ * - `Increase-Undername-Limit`: positive `increaseQty`
117
+ * - `Upgrade-Name`: just `name`
118
+ */
119
+ validateArNSPurchaseParams(params) {
120
+ const p = params;
121
+ if (!types_js_1.arNSPurchaseIntents.includes(p.intent)) {
122
+ throw new errors_js_1.ProvidedInputError(`Invalid ArNS intent '${p.intent}'. Expected one of: ${types_js_1.arNSPurchaseIntents.join(', ')}.`);
123
+ }
124
+ if (typeof p.name !== 'string' || p.name.length === 0) {
125
+ throw new errors_js_1.ProvidedInputError('An ArNS `name` is required.');
126
+ }
127
+ const isPositiveNumber = (v) => typeof v === 'number' && Number.isFinite(v) && v > 0;
128
+ switch (p.intent) {
129
+ case 'Buy-Name':
130
+ if (p.type !== 'lease' && p.type !== 'permabuy') {
131
+ throw new errors_js_1.ProvidedInputError("Buy-Name requires a `type` of 'lease' or 'permabuy'.");
132
+ }
133
+ // `processId` is optional for Buy-Name: omitting it drives the
134
+ // bundler's custodial provisioning path (Turbo spawns + owns the ANT).
135
+ // If supplied it must be a non-empty string (user-owned ANT).
136
+ if (p.processId !== undefined &&
137
+ (typeof p.processId !== 'string' || p.processId.length === 0)) {
138
+ throw new errors_js_1.ProvidedInputError('Buy-Name `processId`, when provided, must be a non-empty string (the ANT the name resolves to).');
139
+ }
140
+ if (p.type === 'lease' && !isPositiveNumber(p.years)) {
141
+ throw new errors_js_1.ProvidedInputError('A lease `Buy-Name` requires a positive `years`.');
142
+ }
143
+ break;
144
+ case 'Extend-Lease':
145
+ if (!isPositiveNumber(p.years)) {
146
+ throw new errors_js_1.ProvidedInputError('Extend-Lease requires a positive `years`.');
147
+ }
148
+ break;
149
+ case 'Increase-Undername-Limit':
150
+ if (!isPositiveNumber(p.increaseQty)) {
151
+ throw new errors_js_1.ProvidedInputError('Increase-Undername-Limit requires a positive `increaseQty`.');
152
+ }
153
+ break;
154
+ case 'Upgrade-Name':
155
+ break;
156
+ }
157
+ }
158
+ getArNSPurchaseStatus({ nonce, }) {
159
+ return this.httpService.get({
160
+ endpoint: `/arns/purchase/${nonce}`,
161
+ });
162
+ }
163
+ buildArNSPurchaseQuery(input) {
164
+ // The intent-specific union members each carry only their own fields; read
165
+ // them through a single widened view rather than narrowing per intent.
166
+ const { type, years, increaseQty, processId, paidBy } = input;
167
+ const params = new URLSearchParams();
168
+ if (type !== undefined)
169
+ params.set('type', type);
170
+ if (years !== undefined)
171
+ params.set('years', `${years}`);
172
+ if (increaseQty !== undefined)
173
+ params.set('increaseQty', `${increaseQty}`);
174
+ if (processId !== undefined)
175
+ params.set('processId', processId);
176
+ if (paidBy !== undefined) {
177
+ for (const payer of Array.isArray(paidBy) ? paidBy : [paidBy]) {
178
+ params.append('paidBy', payer);
179
+ }
180
+ }
181
+ const query = params.toString();
182
+ return query.length > 0 ? `?${query}` : '';
183
+ }
97
184
  appendPromoCodesToQuery(promoCodes) {
98
185
  const promoCodesQuery = promoCodes.join(',');
99
186
  return promoCodesQuery ? `promoCode=${promoCodesQuery}` : '';
@@ -259,6 +346,118 @@ class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentServic
259
346
  userAddress ??= await this.signer.getNativeAddress();
260
347
  return super.getBalance(userAddress);
261
348
  }
349
+ /**
350
+ * Buy / extend / upgrade an ArNS name, paying with the signer's Turbo credit
351
+ * balance. The bundler performs the on-chain ARIO purchase and debits credits;
352
+ * a `402` (FailedRequestError.status === 402) indicates insufficient credits.
353
+ */
354
+ async purchaseArNSName(params) {
355
+ this.validateArNSPurchaseParams(params);
356
+ // The bundler requires the signed nonce to be a UUID; it also doubles as
357
+ // the idempotency + status-lookup key (`getArNSPurchaseStatus`).
358
+ const nonce = (0, uuid_js_1.uuidV4)();
359
+ const headers = await this.signer.generateSignedRequestHeaders(nonce);
360
+ let response;
361
+ try {
362
+ response = await this.httpService.post({
363
+ endpoint: `/arns/purchase/${params.intent.toLowerCase()}/${params.name}${this.buildArNSPurchaseQuery(params)}`,
364
+ headers,
365
+ // Params travel in the query string + signed headers; the service reads
366
+ // no body, but the HTTP layer requires a `data` field.
367
+ data: Buffer.from([]),
368
+ // Non-idempotent signed write: the nonce is single-use, so a retried
369
+ // (but already-landed) purchase would 4xx as "already exists". Poll
370
+ // status by nonce instead of retrying.
371
+ retry: false,
372
+ });
373
+ }
374
+ catch (error) {
375
+ // Surface a credit shortfall as a typed, catchable error so callers can
376
+ // prompt a top-up. The `nonce` is the idempotency key: after topping up,
377
+ // retry the same purchase (a fresh nonce is fine — the service dedupes by
378
+ // the on-chain effect, and a captured nonce lets you poll status).
379
+ if (error instanceof errors_js_1.FailedRequestError && error.status === 402) {
380
+ throw new errors_js_1.InsufficientCreditsError(error.message);
381
+ }
382
+ throw error;
383
+ }
384
+ // Normalize both nonce fields to the one we signed so callers can poll with
385
+ // either `response.nonce` or `response.purchaseReceipt.nonce`.
386
+ return {
387
+ ...response,
388
+ nonce,
389
+ purchaseReceipt: { ...response.purchaseReceipt, nonce },
390
+ };
391
+ }
392
+ buyArNSName(params) {
393
+ return this.purchaseArNSName({
394
+ ...params,
395
+ intent: 'Buy-Name',
396
+ });
397
+ }
398
+ extendArNSLease(params) {
399
+ return this.purchaseArNSName({ ...params, intent: 'Extend-Lease' });
400
+ }
401
+ increaseArNSUndernameLimit(params) {
402
+ return this.purchaseArNSName({
403
+ ...params,
404
+ intent: 'Increase-Undername-Limit',
405
+ });
406
+ }
407
+ upgradeArNSName(params) {
408
+ return this.purchaseArNSName({ ...params, intent: 'Upgrade-Name' });
409
+ }
410
+ // ---- ArNS ANT custody: self-custody exit + manage records ----
411
+ // Canonical ACTION-BOUND message. MUST match the bundler's
412
+ // buildArNSCustodyMessage byte-for-byte (newline-delimited) or every signature
413
+ // is rejected. The bundler reconstructs this from the request and verifies the
414
+ // signature over `message + nonce`, so a captured signature can't be replayed
415
+ // against a different operation/params.
416
+ buildArNSCustodyMessage(action, fields) {
417
+ return ['arns', action, ...fields].join('\n');
418
+ }
419
+ /**
420
+ * Self-custody exit: move a Turbo-custodied ANT to a Solana pubkey you control.
421
+ * Authenticated with an action-bound, single-use signature.
422
+ */
423
+ async transferArNSAnt({ antId, target, }) {
424
+ const nonce = (0, uuid_js_1.uuidV4)();
425
+ const headers = await this.signer.generateSignedRequestHeaders(nonce, this.buildArNSCustodyMessage('transfer', [antId, target]));
426
+ return this.httpService.post({
427
+ endpoint: `/arns/transfer/${antId}?target=${encodeURIComponent(target)}`,
428
+ headers,
429
+ data: Buffer.from([]),
430
+ retry: false, // single-use action-bound nonce; don't re-POST on 5xx
431
+ });
432
+ }
433
+ /** Set a resolution record on a custodied ANT (undername defaults to '@'). */
434
+ async setArNSRecord({ antId, undername = '@', transactionId, ttlSeconds, }) {
435
+ const nonce = (0, uuid_js_1.uuidV4)();
436
+ const headers = await this.signer.generateSignedRequestHeaders(nonce, this.buildArNSCustodyMessage('set-record', [
437
+ antId,
438
+ undername,
439
+ transactionId,
440
+ String(ttlSeconds),
441
+ ]));
442
+ const query = `?undername=${encodeURIComponent(undername)}&transactionId=${transactionId}&ttlSeconds=${ttlSeconds}`;
443
+ return this.httpService.post({
444
+ endpoint: `/arns/manage/${antId}/set-record${query}`,
445
+ headers,
446
+ data: Buffer.from([]),
447
+ retry: false, // single-use action-bound nonce; don't re-POST on 5xx
448
+ });
449
+ }
450
+ /** Remove a resolution record (an undername) from a custodied ANT. */
451
+ async removeArNSRecord({ antId, undername, }) {
452
+ const nonce = (0, uuid_js_1.uuidV4)();
453
+ const headers = await this.signer.generateSignedRequestHeaders(nonce, this.buildArNSCustodyMessage('remove-record', [antId, undername]));
454
+ return this.httpService.post({
455
+ endpoint: `/arns/manage/${antId}/remove-record?undername=${encodeURIComponent(undername)}`,
456
+ headers,
457
+ data: Buffer.from([]),
458
+ retry: false, // single-use action-bound nonce; don't re-POST on 5xx
459
+ });
460
+ }
262
461
  async getCreditShareApprovals({ userAddress, }) {
263
462
  userAddress ??= await this.signer.getNativeAddress();
264
463
  return super.getCreditShareApprovals({ userAddress });
@@ -73,15 +73,27 @@ class TurboDataItemAbstractSigner {
73
73
  return (0, base64_js_1.ownerToAddress)(owner);
74
74
  }
75
75
  }
76
- async generateSignedRequestHeaders() {
77
- const nonce = (0, crypto_2.randomBytes)(16).toString('hex');
78
- const buffer = Buffer.from(nonce);
76
+ async generateSignedRequestHeaders(
77
+ // Callers may supply the nonce (e.g. a UUID required by some routes); the
78
+ // nonce round-trips to the service in `x-nonce` unchanged.
79
+ nonce = (0, crypto_2.randomBytes)(16).toString('hex'),
80
+ // Optional ACTION-BINDING data prepended to the nonce for SIGNING only (not
81
+ // sent): the service reconstructs the same string from the request and
82
+ // verifies the signature over `additionalData + nonce`. This binds the
83
+ // signature to a specific operation + params so it can't be replayed against
84
+ // a different request. Omitted → signs the bare nonce (unchanged behavior).
85
+ additionalData) {
86
+ const buffer = Buffer.from((additionalData ?? '') + nonce);
79
87
  const signature = await this.signer.sign(Uint8Array.from(buffer));
80
88
  const publicKey = (0, base64_js_1.toB64Url)(this.signer.publicKey);
81
89
  return {
82
90
  'x-public-key': publicKey,
83
91
  'x-nonce': nonce,
84
92
  'x-signature': (0, base64_js_1.toB64Url)(Buffer.from(signature)),
93
+ // Advertise the signature scheme so the service verifies with the right
94
+ // algorithm. Absent this, the server defaults to Arweave and every
95
+ // non-Arweave signed request (Ethereum, Solana, …) fails verification.
96
+ 'x-signature-type': this.signer.signatureType.toString(),
85
97
  };
86
98
  }
87
99
  async getPublicKey() {
@@ -54,6 +54,18 @@ class TurboUnauthenticatedClient {
54
54
  getBalance(address) {
55
55
  return this.paymentService.getBalance(address);
56
56
  }
57
+ /**
58
+ * Returns the price in 'winc' (and mARIO) to buy/extend/upgrade an ArNS name.
59
+ */
60
+ getArNSPriceForName(params) {
61
+ return this.paymentService.getArNSPriceForName(params);
62
+ }
63
+ /**
64
+ * Returns the status of an ArNS purchase by its nonce.
65
+ */
66
+ getArNSPurchaseStatus(p) {
67
+ return this.paymentService.getArNSPurchaseStatus(p);
68
+ }
57
69
  /**
58
70
  * Returns a list of all supported fiat currencies.
59
71
  */
@@ -159,6 +171,38 @@ class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
159
171
  getBalance(userAddress) {
160
172
  return this.paymentService.getBalance(userAddress);
161
173
  }
174
+ /**
175
+ * Buys, extends, or upgrades an ArNS name, paying with the signer's Turbo
176
+ * credit balance. Poll {@link getArNSPurchaseStatus} with the returned nonce.
177
+ */
178
+ purchaseArNSName(params) {
179
+ return this.paymentService.purchaseArNSName(params);
180
+ }
181
+ /** Buys a new ArNS name (lease or permabuy). */
182
+ buyArNSName(params) {
183
+ return this.paymentService.buyArNSName(params);
184
+ }
185
+ /** Extends the lease on an existing ArNS name. */
186
+ extendArNSLease(params) {
187
+ return this.paymentService.extendArNSLease(params);
188
+ }
189
+ /** Increases the undername limit on an existing ArNS name. */
190
+ increaseArNSUndernameLimit(params) {
191
+ return this.paymentService.increaseArNSUndernameLimit(params);
192
+ }
193
+ /** Upgrades an ArNS lease to a permabuy. */
194
+ upgradeArNSName(params) {
195
+ return this.paymentService.upgradeArNSName(params);
196
+ }
197
+ transferArNSAnt(params) {
198
+ return this.paymentService.transferArNSAnt(params);
199
+ }
200
+ setArNSRecord(params) {
201
+ return this.paymentService.setArNSRecord(params);
202
+ }
203
+ removeArNSRecord(params) {
204
+ return this.paymentService.removeArNSRecord(params);
205
+ }
162
206
  /**
163
207
  * Returns a list of all credit share approvals for the user.
164
208
  */
package/lib/cjs/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validChunkingModes = exports.isJWK = exports.isWebUploadFolderParams = exports.isNodeUploadFolderParams = exports.multipartFinalizedStatus = exports.multipartFailedStatus = exports.multipartPendingStatus = exports.X402Funding = exports.OnDemandFunding = exports.ExistingBalanceFunding = exports.supportedEvmSignerTokens = exports.tokenTypes = exports.fiatCurrencyTypes = void 0;
3
+ exports.arNSPurchaseIntents = exports.validChunkingModes = exports.isJWK = exports.isWebUploadFolderParams = exports.isNodeUploadFolderParams = exports.multipartFinalizedStatus = exports.multipartFailedStatus = exports.multipartPendingStatus = exports.X402Funding = exports.OnDemandFunding = exports.ExistingBalanceFunding = exports.supportedEvmSignerTokens = exports.tokenTypes = exports.fiatCurrencyTypes = void 0;
4
4
  exports.isCurrency = isCurrency;
5
5
  exports.isKyvePrivateKey = isKyvePrivateKey;
6
6
  exports.isEthPrivateKey = isEthPrivateKey;
@@ -108,3 +108,10 @@ function isEthereumWalletAdapter(walletAdapter) {
108
108
  return 'getSigner' in walletAdapter;
109
109
  }
110
110
  exports.validChunkingModes = ['force', 'disabled', 'auto'];
111
+ // ===== ArNS purchases paid with Turbo credits (via the bundler REST API) =====
112
+ exports.arNSPurchaseIntents = [
113
+ 'Buy-Name',
114
+ 'Extend-Lease',
115
+ 'Increase-Undername-Limit',
116
+ 'Upgrade-Name',
117
+ ];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AbortError = exports.ProvidedInputError = exports.FailedRequestError = exports.UnauthenticatedRequestError = exports.BaseError = void 0;
3
+ exports.AbortError = exports.InsufficientCreditsError = exports.ProvidedInputError = exports.FailedRequestError = exports.UnauthenticatedRequestError = exports.BaseError = void 0;
4
4
  /**
5
5
  * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
6
6
  *
@@ -42,6 +42,24 @@ class ProvidedInputError extends BaseError {
42
42
  }
43
43
  }
44
44
  exports.ProvidedInputError = ProvidedInputError;
45
+ /**
46
+ * Raised when a credit-paid operation (e.g. an ArNS purchase) is rejected by the
47
+ * service because the paying wallet does not hold enough Turbo credits. Maps the
48
+ * bundler's HTTP `402 Payment Required` response to a typed, catchable error so
49
+ * callers can prompt a top-up without string-matching on messages.
50
+ *
51
+ * Recovery: top up the balance, then retry the SAME operation reusing the
52
+ * captured `nonce` (the nonce is the idempotency key), or mint a fresh request.
53
+ */
54
+ class InsufficientCreditsError extends BaseError {
55
+ constructor(message) {
56
+ super(message ??
57
+ 'Insufficient Turbo credits to complete this purchase. Top up your balance and retry.');
58
+ /** Always the HTTP status that produced this error. */
59
+ this.status = 402;
60
+ }
61
+ }
62
+ exports.InsufficientCreditsError = InsufficientCreditsError;
45
63
  class AbortError extends BaseError {
46
64
  constructor(message = 'Request was aborted') {
47
65
  super(message);
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uuidV4 = uuidV4;
4
+ /**
5
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ const crypto_1 = require("crypto");
20
+ /**
21
+ * RFC 4122 version 4 UUID, derived from `randomBytes` (already used across the
22
+ * SDK in both the node and web builds). Avoids depending on
23
+ * `crypto.randomUUID`, whose availability varies by runtime/polyfill.
24
+ */
25
+ function uuidV4() {
26
+ const bytes = (0, crypto_1.randomBytes)(16);
27
+ bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
28
+ bytes[8] = (bytes[8] & 0x3f) | 0x80; // RFC 4122 variant
29
+ const hex = bytes.toString('hex');
30
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
31
+ }
@@ -64,9 +64,11 @@ class TurboWebArweaveSigner extends signer_js_1.TurboDataItemAbstractSigner {
64
64
  dataItemSizeFactory: () => signedDataItemSize,
65
65
  };
66
66
  }
67
- async generateSignedRequestHeaders() {
67
+ async generateSignedRequestHeaders(nonce, additionalData) {
68
68
  await this.setPublicKey();
69
- return super.generateSignedRequestHeaders();
69
+ // Pass through the caller's nonce + action-binding data (previously dropped,
70
+ // which would override a route-required UUID nonce and the H-2 binding).
71
+ return super.generateSignedRequestHeaders(nonce, additionalData);
70
72
  }
71
73
  async signData(dataToSign) {
72
74
  await this.setPublicKey();
@@ -20,6 +20,7 @@ import { DataItem } from '@dha-team/arbundles';
20
20
  import { program } from 'commander';
21
21
  import { readFileSync, readdirSync } from 'fs';
22
22
  import { version } from '../version.js';
23
+ import { arnsPrice, arnsPurchaseStatus, buyArNSName, extendArNSLease, increaseArNSUndernames, removeArNSRecord, setArNSRecord, transferArNSAnt, upgradeArNSName, } from './commands/arns.js';
23
24
  import { fiatEstimate } from './commands/fiatEstimate.js';
24
25
  import { balance, cryptoFund, price, topUp, uploadFile, uploadFolder, } from './commands/index.js';
25
26
  import { listShares } from './commands/listShares.js';
@@ -27,7 +28,7 @@ import { revokeCredits } from './commands/revokeCredits.js';
27
28
  import { shareCredits } from './commands/shareCredits.js';
28
29
  import { tokenPrice } from './commands/tokenPrice.js';
29
30
  import { x402UploadUnsignedFile } from './commands/x402UploadUnsignedData.js';
30
- import { globalOptions, listSharesOptions, optionMap, revokeCreditsOptions, shareCreditsOptions, uploadFileOptions, uploadFolderOptions, walletOptions, } from './options.js';
31
+ import { arnsPriceOptions, arnsPurchaseStatusOptions, buyArNSNameOptions, extendArNSLeaseOptions, globalOptions, increaseArNSUndernamesOptions, listSharesOptions, optionMap, removeArNSRecordOptions, revokeCreditsOptions, setArNSRecordOptions, shareCreditsOptions, transferArNSAntOptions, upgradeArNSNameOptions, uploadFileOptions, uploadFolderOptions, walletOptions, } from './options.js';
31
32
  import { applyOptions, runCommand } from './utils.js';
32
33
  applyOptions(program
33
34
  .name('turbo')
@@ -84,6 +85,51 @@ applyOptions(program
84
85
  .description('Lists all given or received Turbo credit share approvals for specified address or connected wallet'), listSharesOptions).action(async (_commandOptions, command) => {
85
86
  await runCommand(command, listShares);
86
87
  });
88
+ applyOptions(program
89
+ .command('arns-price')
90
+ .description('Get the Turbo Credit (winc + mARIO) price to buy, extend, increase undernames, or upgrade an ArNS name'), arnsPriceOptions).action(async (_commandOptions, command) => {
91
+ await runCommand(command, arnsPrice);
92
+ });
93
+ applyOptions(program
94
+ .command('buy-arns-name')
95
+ .description('Buy an ArNS name (lease or permabuy) with Turbo Credits'), buyArNSNameOptions).action(async (_commandOptions, command) => {
96
+ await runCommand(command, buyArNSName);
97
+ });
98
+ applyOptions(program
99
+ .command('extend-arns-lease')
100
+ .description('Extend an ArNS name lease with Turbo Credits'), extendArNSLeaseOptions).action(async (_commandOptions, command) => {
101
+ await runCommand(command, extendArNSLease);
102
+ });
103
+ applyOptions(program
104
+ .command('increase-arns-undernames')
105
+ .description('Increase the undername limit of an ArNS name with Turbo Credits'), increaseArNSUndernamesOptions).action(async (_commandOptions, command) => {
106
+ await runCommand(command, increaseArNSUndernames);
107
+ });
108
+ applyOptions(program
109
+ .command('upgrade-arns-name')
110
+ .description('Upgrade an ArNS leased name to a permabuy with Turbo Credits'), upgradeArNSNameOptions).action(async (_commandOptions, command) => {
111
+ await runCommand(command, upgradeArNSName);
112
+ });
113
+ applyOptions(program
114
+ .command('arns-purchase-status')
115
+ .description('Get the status of an ArNS purchase by its nonce'), arnsPurchaseStatusOptions).action(async (_commandOptions, command) => {
116
+ await runCommand(command, arnsPurchaseStatus);
117
+ });
118
+ applyOptions(program
119
+ .command('transfer-arns-ant')
120
+ .description('Transfer a Turbo-custodied ANT to a Solana pubkey you control'), transferArNSAntOptions).action(async (_commandOptions, command) => {
121
+ await runCommand(command, transferArNSAnt);
122
+ });
123
+ applyOptions(program
124
+ .command('set-arns-record')
125
+ .description('Set a resolution record on a Turbo-custodied ANT'), setArNSRecordOptions).action(async (_commandOptions, command) => {
126
+ await runCommand(command, setArNSRecord);
127
+ });
128
+ applyOptions(program
129
+ .command('remove-arns-record')
130
+ .description('Remove a resolution record (undername) from a Turbo-custodied ANT'), removeArNSRecordOptions).action(async (_commandOptions, command) => {
131
+ await runCommand(command, removeArNSRecord);
132
+ });
87
133
  applyOptions(program
88
134
  .command('inspect-data-items')
89
135
  .description('Lists all given or received Turbo credit share approvals for specified address or connected wallet'), [optionMap.folderPath]).action(async (_commandOptions, command) => {