@ardrive/turbo-sdk 1.42.0 → 1.43.0-alpha.2

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 (99) hide show
  1. package/lib/cjs/cli/cli.js +97 -0
  2. package/lib/cjs/cli/commands/arns.js +475 -0
  3. package/lib/cjs/cli/commands/freeStatus.js +47 -0
  4. package/lib/cjs/cli/commands/index.js +3 -0
  5. package/lib/cjs/cli/commands/paymentHistory.js +25 -0
  6. package/lib/cjs/cli/options.js +202 -1
  7. package/lib/cjs/common/arnsActions.js +125 -0
  8. package/lib/cjs/common/chunked.js +51 -1
  9. package/lib/cjs/common/folderIndex.js +401 -0
  10. package/lib/cjs/common/http.js +40 -6
  11. package/lib/cjs/common/index.js +7 -0
  12. package/lib/cjs/common/payment.js +548 -2
  13. package/lib/cjs/common/signer.js +27 -6
  14. package/lib/cjs/common/token/index.js +0 -11
  15. package/lib/cjs/common/turbo.js +162 -0
  16. package/lib/cjs/common/upload.js +314 -31
  17. package/lib/cjs/node/folderIndex.js +132 -0
  18. package/lib/cjs/node/index.js +1 -0
  19. package/lib/cjs/node/upload.js +7 -0
  20. package/lib/cjs/types.js +53 -3
  21. package/lib/cjs/utils/common.js +0 -4
  22. package/lib/cjs/utils/errors.js +38 -1
  23. package/lib/cjs/utils/folderIndex.js +88 -0
  24. package/lib/cjs/utils/uuid.js +31 -0
  25. package/lib/cjs/web/signer.js +4 -2
  26. package/lib/esm/cli/cli.js +99 -2
  27. package/lib/esm/cli/commands/arns.js +450 -0
  28. package/lib/esm/cli/commands/freeStatus.js +44 -0
  29. package/lib/esm/cli/commands/index.js +3 -0
  30. package/lib/esm/cli/commands/paymentHistory.js +22 -0
  31. package/lib/esm/cli/options.js +201 -0
  32. package/lib/esm/common/arnsActions.js +114 -0
  33. package/lib/esm/common/chunked.js +51 -1
  34. package/lib/esm/common/folderIndex.js +396 -0
  35. package/lib/esm/common/http.js +39 -5
  36. package/lib/esm/common/index.js +7 -0
  37. package/lib/esm/common/payment.js +548 -2
  38. package/lib/esm/common/signer.js +28 -7
  39. package/lib/esm/common/token/index.js +1 -12
  40. package/lib/esm/common/turbo.js +162 -0
  41. package/lib/esm/common/upload.js +316 -33
  42. package/lib/esm/node/folderIndex.js +129 -0
  43. package/lib/esm/node/index.js +1 -0
  44. package/lib/esm/node/upload.js +7 -0
  45. package/lib/esm/types.js +52 -2
  46. package/lib/esm/utils/common.js +0 -4
  47. package/lib/esm/utils/errors.js +35 -0
  48. package/lib/esm/utils/folderIndex.js +81 -0
  49. package/lib/esm/utils/uuid.js +28 -0
  50. package/lib/esm/web/signer.js +4 -2
  51. package/lib/types/cli/commands/arns.d.ts +147 -0
  52. package/lib/types/cli/commands/arns.d.ts.map +1 -0
  53. package/lib/types/cli/commands/freeStatus.d.ts +3 -0
  54. package/lib/types/cli/commands/freeStatus.d.ts.map +1 -0
  55. package/lib/types/cli/commands/index.d.ts +3 -0
  56. package/lib/types/cli/commands/index.d.ts.map +1 -1
  57. package/lib/types/cli/commands/paymentHistory.d.ts +18 -0
  58. package/lib/types/cli/commands/paymentHistory.d.ts.map +1 -0
  59. package/lib/types/cli/options.d.ts +423 -0
  60. package/lib/types/cli/options.d.ts.map +1 -1
  61. package/lib/types/cli/types.d.ts +78 -0
  62. package/lib/types/cli/types.d.ts.map +1 -1
  63. package/lib/types/common/arnsActions.d.ts +58 -0
  64. package/lib/types/common/arnsActions.d.ts.map +1 -0
  65. package/lib/types/common/chunked.d.ts +47 -2
  66. package/lib/types/common/chunked.d.ts.map +1 -1
  67. package/lib/types/common/folderIndex.d.ts +54 -0
  68. package/lib/types/common/folderIndex.d.ts.map +1 -0
  69. package/lib/types/common/http.d.ts +25 -2
  70. package/lib/types/common/http.d.ts.map +1 -1
  71. package/lib/types/common/index.d.ts +3 -0
  72. package/lib/types/common/index.d.ts.map +1 -1
  73. package/lib/types/common/payment.d.ts +291 -1
  74. package/lib/types/common/payment.d.ts.map +1 -1
  75. package/lib/types/common/signer.d.ts +12 -6
  76. package/lib/types/common/signer.d.ts.map +1 -1
  77. package/lib/types/common/token/index.d.ts.map +1 -1
  78. package/lib/types/common/turbo.d.ts +183 -1
  79. package/lib/types/common/turbo.d.ts.map +1 -1
  80. package/lib/types/common/upload.d.ts +41 -0
  81. package/lib/types/common/upload.d.ts.map +1 -1
  82. package/lib/types/node/folderIndex.d.ts +28 -0
  83. package/lib/types/node/folderIndex.d.ts.map +1 -0
  84. package/lib/types/node/index.d.ts +1 -0
  85. package/lib/types/node/index.d.ts.map +1 -1
  86. package/lib/types/node/upload.d.ts +1 -0
  87. package/lib/types/node/upload.d.ts.map +1 -1
  88. package/lib/types/types.d.ts +694 -3
  89. package/lib/types/types.d.ts.map +1 -1
  90. package/lib/types/utils/common.d.ts.map +1 -1
  91. package/lib/types/utils/errors.d.ts +29 -0
  92. package/lib/types/utils/errors.d.ts.map +1 -1
  93. package/lib/types/utils/folderIndex.d.ts +47 -0
  94. package/lib/types/utils/folderIndex.d.ts.map +1 -0
  95. package/lib/types/utils/uuid.d.ts +7 -0
  96. package/lib/types/utils/uuid.d.ts.map +1 -0
  97. package/lib/types/web/signer.d.ts +1 -1
  98. package/lib/types/web/signer.d.ts.map +1 -1
  99. package/package.json +1 -1
@@ -186,6 +186,102 @@ export const optionMap = {
186
186
  alias: '--max-crypto-top-up-value <maxCryptoTopUpValue>',
187
187
  description: 'Maximum crypto top-up value to use for the upload. Defaults to no limit.',
188
188
  },
189
+ // ---- ArNS (paid with Turbo Credits) ----
190
+ arnsName: {
191
+ alias: '--name <name>',
192
+ description: 'ArNS name to price, buy, or manage',
193
+ },
194
+ arnsType: {
195
+ alias: '--type <type>',
196
+ description: "ArNS purchase type for Buy-Name: 'lease' or 'permabuy'",
197
+ },
198
+ arnsYears: {
199
+ alias: '--years <years>',
200
+ description: 'Lease duration in years (Buy-Name lease / Extend-Lease)',
201
+ },
202
+ arnsIncreaseQty: {
203
+ alias: '--increase-qty <qty>',
204
+ description: 'Number of additional undernames (Increase-Undername-Limit)',
205
+ },
206
+ arnsOwnerKey: {
207
+ alias: '--owner-key <base58SolanaSecretKey>',
208
+ description: 'Base58 Solana secret key that OWNS the ANT and signs for it. Separate from the wallet paying in Turbo Credits — the owner needs a key to sign with, not SOL: Turbo pays every fee and rent',
209
+ },
210
+ arnsNonce: {
211
+ alias: '--nonce <nonce>',
212
+ description: 'ArNS purchase nonce to look up the status for',
213
+ },
214
+ arnsAntId: {
215
+ alias: '--ant-id <antId>',
216
+ description: 'ANT (Metaplex Core asset) ID to transfer or manage',
217
+ },
218
+ arnsTarget: {
219
+ alias: '--target <address>',
220
+ description: 'Target Solana pubkey to transfer the ANT to',
221
+ },
222
+ arnsUndername: {
223
+ alias: '--undername <undername>',
224
+ description: "ArNS undername record to set or remove (defaults to '@')",
225
+ },
226
+ arnsTransactionId: {
227
+ alias: '--transaction-id <transactionId>',
228
+ description: 'Arweave transaction ID the ArNS record resolves to',
229
+ },
230
+ arnsTtlSeconds: {
231
+ alias: '--ttl-seconds <ttlSeconds>',
232
+ description: 'TTL in seconds for the ArNS record',
233
+ },
234
+ arnsDisplayName: {
235
+ alias: '--display-name <displayName>',
236
+ description: 'Display name for the record (Set-Record-Metadata)',
237
+ },
238
+ arnsClearDisplayName: {
239
+ alias: '--clear-display-name',
240
+ description: 'Clear the record display name (Set-Record-Metadata)',
241
+ default: false,
242
+ },
243
+ arnsRecordLogo: {
244
+ alias: '--record-logo <transactionId>',
245
+ description: 'Arweave transaction ID for the record logo (Set-Record-Metadata)',
246
+ },
247
+ arnsClearRecordLogo: {
248
+ alias: '--clear-record-logo',
249
+ description: 'Clear the record logo (Set-Record-Metadata)',
250
+ default: false,
251
+ },
252
+ arnsRecordDescription: {
253
+ alias: '--record-description <description>',
254
+ description: 'Description for the record (Set-Record-Metadata)',
255
+ },
256
+ arnsClearRecordDescription: {
257
+ alias: '--clear-record-description',
258
+ description: 'Clear the record description (Set-Record-Metadata)',
259
+ default: false,
260
+ },
261
+ arnsRecordKeywords: {
262
+ alias: '--record-keywords <keywords...>',
263
+ description: 'Keywords for the record (Set-Record-Metadata)',
264
+ type: 'array',
265
+ },
266
+ arnsClearRecordKeywords: {
267
+ alias: '--clear-record-keywords',
268
+ description: 'Clear the record keywords (Set-Record-Metadata)',
269
+ default: false,
270
+ },
271
+ arnsAction: {
272
+ alias: '--action <action>',
273
+ description: 'ArNS action to price: set-record, remove-record, set-record-metadata, ' +
274
+ 'remove-record-metadata, transfer-record, add-controller, remove-controller, or transfer',
275
+ },
276
+ // ---- Payment history ----
277
+ limit: {
278
+ alias: '--limit <limit>',
279
+ description: 'Max number of payment-history rows to return (1-100, default 50)',
280
+ },
281
+ cursor: {
282
+ alias: '--cursor <cursor>',
283
+ description: 'Opaque pagination cursor from a prior payment-history response',
284
+ },
189
285
  };
190
286
  export const walletOptions = [
191
287
  optionMap.walletFile,
@@ -239,3 +335,108 @@ export const shareCreditsOptions = [
239
335
  ];
240
336
  export const revokeCreditsOptions = [...walletOptions, optionMap.address];
241
337
  export const listSharesOptions = revokeCreditsOptions;
338
+ // ---- ArNS command option sets (token + --payment-url come from globalOptions) ----
339
+ export const arnsPriceOptions = [
340
+ optionMap.arnsName,
341
+ optionMap.arnsType,
342
+ optionMap.arnsYears,
343
+ optionMap.arnsIncreaseQty,
344
+ ];
345
+ export const arnsFiatQuoteOptions = [
346
+ optionMap.arnsName,
347
+ optionMap.arnsType,
348
+ optionMap.arnsYears,
349
+ optionMap.arnsIncreaseQty,
350
+ optionMap.address,
351
+ optionMap.currency,
352
+ {
353
+ alias: '--method <method>',
354
+ description: 'Stripe integration mode: payment-intent (default) or checkout-session',
355
+ },
356
+ {
357
+ alias: '--promo-code <promoCode...>',
358
+ description: 'Promo code(s) to apply to the fiat price',
359
+ },
360
+ ];
361
+ export const buyArNSNameOptions = [
362
+ ...walletOptions,
363
+ optionMap.arnsName,
364
+ optionMap.arnsType,
365
+ optionMap.arnsYears,
366
+ optionMap.arnsOwnerKey,
367
+ optionMap.paidBy,
368
+ ];
369
+ export const extendArNSLeaseOptions = [
370
+ ...walletOptions,
371
+ optionMap.arnsName,
372
+ optionMap.arnsYears,
373
+ optionMap.paidBy,
374
+ ];
375
+ export const increaseArNSUndernamesOptions = [
376
+ ...walletOptions,
377
+ optionMap.arnsName,
378
+ optionMap.arnsIncreaseQty,
379
+ optionMap.paidBy,
380
+ ];
381
+ export const upgradeArNSNameOptions = [
382
+ ...walletOptions,
383
+ optionMap.arnsName,
384
+ optionMap.paidBy,
385
+ ];
386
+ export const arnsPurchaseStatusOptions = [optionMap.arnsNonce];
387
+ export const arnsActionStatusOptions = [...walletOptions, optionMap.arnsNonce];
388
+ export const transferArNSAntOptions = [
389
+ ...walletOptions,
390
+ optionMap.arnsOwnerKey,
391
+ optionMap.arnsAntId,
392
+ optionMap.arnsTarget,
393
+ ];
394
+ export const setArNSRecordOptions = [
395
+ ...walletOptions,
396
+ optionMap.arnsOwnerKey,
397
+ optionMap.arnsAntId,
398
+ optionMap.arnsUndername,
399
+ optionMap.arnsTransactionId,
400
+ optionMap.arnsTtlSeconds,
401
+ ];
402
+ export const removeArNSRecordOptions = [
403
+ ...walletOptions,
404
+ optionMap.arnsOwnerKey,
405
+ optionMap.arnsAntId,
406
+ optionMap.arnsUndername,
407
+ ];
408
+ export const addArNSControllerOptions = [
409
+ ...walletOptions,
410
+ optionMap.arnsOwnerKey,
411
+ optionMap.arnsAntId,
412
+ optionMap.arnsTarget,
413
+ ];
414
+ export const removeArNSControllerOptions = addArNSControllerOptions;
415
+ export const transferArNSRecordOptions = [
416
+ ...walletOptions,
417
+ optionMap.arnsOwnerKey,
418
+ optionMap.arnsAntId,
419
+ optionMap.arnsUndername,
420
+ optionMap.arnsTarget,
421
+ ];
422
+ export const setArNSRecordMetadataOptions = [
423
+ ...walletOptions,
424
+ optionMap.arnsOwnerKey,
425
+ optionMap.arnsAntId,
426
+ optionMap.arnsUndername,
427
+ optionMap.arnsDisplayName,
428
+ optionMap.arnsClearDisplayName,
429
+ optionMap.arnsRecordLogo,
430
+ optionMap.arnsClearRecordLogo,
431
+ optionMap.arnsRecordDescription,
432
+ optionMap.arnsClearRecordDescription,
433
+ optionMap.arnsRecordKeywords,
434
+ optionMap.arnsClearRecordKeywords,
435
+ ];
436
+ export const removeArNSRecordMetadataOptions = [
437
+ ...walletOptions,
438
+ optionMap.arnsOwnerKey,
439
+ optionMap.arnsAntId,
440
+ optionMap.arnsUndername,
441
+ ];
442
+ export const arnsActionPriceOptions = [optionMap.arnsAction];
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { Keypair, VersionedTransaction } from '@solana/web3.js';
17
+ import bs58 from 'bs58';
18
+ import nacl from 'tweetnacl';
19
+ import { toB64Url } from '../utils/base64.js';
20
+ /**
21
+ * Canonical ACTION-BOUND message for the owner proof.
22
+ *
23
+ * MUST match the bundler's `buildArNSCustodyMessage` byte for byte
24
+ * (newline-delimited) or every signature is rejected. The bundler rebuilds this
25
+ * from the request and verifies the signature over `message + nonce`, so a
26
+ * signature captured for one operation cannot authorize a different one, and
27
+ * the nonce is consumed on use so the same one cannot be replayed (e.g. to
28
+ * revert a record to an older value).
29
+ */
30
+ export function buildArNSCustodyMessage(action, fields) {
31
+ return ['arns', action, ...fields].join('\n');
32
+ }
33
+ /**
34
+ * A metadata field's ABSENT/EMPTY distinction, as the bundler binds it.
35
+ *
36
+ * `null` (clear the field) must not sign the same message as `''` (set it to
37
+ * empty), or a signature authorizing one would authorize the other. NUL can
38
+ * never appear in a value that reached here — the route rejects control
39
+ * characters — so it is a safe sentinel.
40
+ */
41
+ export function arNSMetadataField(value) {
42
+ return value === null || value === undefined ? '\u0000' : value;
43
+ }
44
+ /**
45
+ * Keywords joined on a separator the route rejects INSIDE a keyword, so
46
+ * `['a,b']` and `['a','b']` cannot be re-partitioned into one another with the
47
+ * same signature.
48
+ */
49
+ export function arNSKeywordsField(keywords) {
50
+ return keywords === null || keywords === undefined
51
+ ? '\u0000'
52
+ : keywords.join('\u0001');
53
+ }
54
+ /** Solana's signature-type discriminator in Turbo's signed-request scheme. */
55
+ const SOLANA_SIGNATURE_TYPE = 4;
56
+ /**
57
+ * The ANT owner's half of the envelope, in its own `x-owner-*` headers.
58
+ *
59
+ * Two signatures travel on a record action — the PAYER's signed request over
60
+ * `"" + nonce`, and the OWNER's action-bound proof over `message + nonce` —
61
+ * from two different keys, usually on two different chains. They cannot share
62
+ * one header set: whichever verifier ran second would reject a signature that
63
+ * was never meant for it.
64
+ */
65
+ export async function arNSOwnerProofHeaders(owner, message, nonce) {
66
+ const address = await owner.getAddress();
67
+ const signature = await owner.signMessage(Uint8Array.from(Buffer.from(message + nonce)));
68
+ return {
69
+ // A Solana address IS the base58-encoded 32-byte ed25519 public key, so
70
+ // decoding the address recovers exactly the bytes the bundler verifies
71
+ // against. Keeps ArNSOwnerSigner minimal — no separate getPublicKey().
72
+ 'x-owner-public-key': toB64Url(Buffer.from(bs58.decode(address))),
73
+ 'x-owner-nonce': nonce,
74
+ 'x-owner-signature': toB64Url(Buffer.from(signature)),
75
+ 'x-owner-signature-type': String(SOLANA_SIGNATURE_TYPE),
76
+ };
77
+ }
78
+ /**
79
+ * Build an {@link ArNSOwnerSigner} from a raw Solana secret key.
80
+ *
81
+ * For servers and tests. A browser wallet (Phantom, Solflare, or a console's
82
+ * embedded wallet) should implement the interface directly against its own
83
+ * `signTransaction` / `signMessage` rather than exposing a secret key.
84
+ *
85
+ * Note the owner needs a key to SIGN with, not a funded account: Turbo is the
86
+ * fee payer on every sponsored action, so this wallet's SOL balance can stay
87
+ * at zero for the entire life of the name.
88
+ */
89
+ export function solanaOwnerSigner(secretKey) {
90
+ const keypair = Keypair.fromSecretKey(typeof secretKey === 'string' ? bs58.decode(secretKey) : secretKey);
91
+ return {
92
+ getAddress: () => keypair.publicKey.toBase58(),
93
+ signTransaction: async (transactionBase64) => {
94
+ const tx = VersionedTransaction.deserialize(Buffer.from(transactionBase64, 'base64'));
95
+ // Sign the bytes as returned. Turbo's fee-payer signature already covers
96
+ // this exact message; rebuilding it from parts invalidates that and the
97
+ // submission is rejected.
98
+ tx.sign([keypair]);
99
+ return Buffer.from(tx.serialize()).toString('base64');
100
+ },
101
+ signMessage: async (message) => nacl.sign.detached(message, keypair.secretKey),
102
+ };
103
+ }
104
+ /**
105
+ * Count the signature slots a prepared transaction still has empty.
106
+ *
107
+ * Turbo pre-signs as fee payer and leaves exactly one slot for the owner, so a
108
+ * client can assert that before prompting a wallet — a cheap way to catch a
109
+ * malformed or already-signed transaction before bothering the user.
110
+ */
111
+ export function emptySignatureSlots(transactionBase64) {
112
+ const tx = VersionedTransaction.deserialize(Buffer.from(transactionBase64, 'base64'));
113
+ return tx.signatures.filter((sig) => sig.every((byte) => byte === 0)).length;
114
+ }
@@ -35,7 +35,7 @@ const chunkingHeader = { 'x-chunking-version': '2' };
35
35
  * uploading them in parallel, and emitting progress/error events.
36
36
  */
37
37
  export class ChunkedUploader {
38
- constructor({ http, token, maxChunkConcurrency = defaultMaxChunkConcurrency, maxFinalizeMs, chunkByteCount = defaultChunkByteCount, logger = Logger.default, chunkingMode = 'auto', dataItemByteCount, }) {
38
+ constructor({ http, token, maxChunkConcurrency = defaultMaxChunkConcurrency, maxFinalizeMs, chunkByteCount = defaultChunkByteCount, logger = Logger.default, chunkingMode = 'auto', dataItemByteCount, x402, x402RefundIdentity, }) {
39
39
  this.assertChunkParams({
40
40
  chunkByteCount,
41
41
  chunkingMode,
@@ -54,6 +54,9 @@ export class ChunkedUploader {
54
54
  dataItemByteCount,
55
55
  });
56
56
  this.maxBacklogQueue = this.maxChunkConcurrency * backlogQueueFactor;
57
+ this.x402 = x402;
58
+ this.x402RefundIdentity = x402RefundIdentity;
59
+ this.dataItemByteCount = dataItemByteCount;
57
60
  }
58
61
  shouldChunkUpload({ chunkByteCount, chunkingMode, dataItemByteCount, }) {
59
62
  if (chunkingMode === 'disabled') {
@@ -92,7 +95,54 @@ export class ChunkedUploader {
92
95
  /**
93
96
  * Initialize or resume an upload session, returning the upload ID.
94
97
  */
98
+ /**
99
+ * Open a multipart upload paid for with x402.
100
+ *
101
+ * The bundler settles the payment at CREATE, before accepting a single chunk
102
+ * — so an unpaid upload never consumes storage. That is why the size is
103
+ * declared here and the money moves here, not at finalize.
104
+ *
105
+ * The 402 handshake is delegated to `wrapFetchWithPayment`, the same
106
+ * mechanism the single-shot x402 POST already uses, so the signer and the
107
+ * spend cap behave identically on both paths.
108
+ */
109
+ async initPaidUpload(x402) {
110
+ if (this.paidUploadId !== undefined) {
111
+ this.logger.debug('Resuming the already-paid chunked upload', {
112
+ uploadId: this.paidUploadId,
113
+ });
114
+ return this.paidUploadId;
115
+ }
116
+ if (this.x402RefundIdentity === undefined) {
117
+ throw new Error('An x402-paid chunked upload needs a refund identity — it is the Turbo wallet credited if the upload delivers fewer bytes than were paid for.');
118
+ }
119
+ const { address, signatureType } = this.x402RefundIdentity;
120
+ const endpoint = `/chunks/${this.token}/-1/-1?chunkSize=${this.chunkByteCount}` +
121
+ `&totalBytes=${this.dataItemByteCount}` +
122
+ `&address=${encodeURIComponent(address)}` +
123
+ `&signatureType=${signatureType}`;
124
+ this.logger.debug('Opening an x402-paid chunked upload', {
125
+ totalBytes: this.dataItemByteCount,
126
+ });
127
+ const res = await this.http.get({
128
+ endpoint: endpoint,
129
+ headers: chunkingHeader,
130
+ x402Options: x402,
131
+ });
132
+ if (res.chunkSize !== undefined && res.chunkSize !== this.chunkByteCount) {
133
+ this.logger.warn('Chunk size mismatch! Overriding with server value.', {
134
+ clientExpected: this.chunkByteCount,
135
+ serverReturned: res.chunkSize,
136
+ });
137
+ this.chunkByteCount = res.chunkSize;
138
+ }
139
+ this.paidUploadId = res.id;
140
+ return res.id;
141
+ }
95
142
  async initUpload() {
143
+ if (this.x402 !== undefined) {
144
+ return this.initPaidUpload(this.x402);
145
+ }
96
146
  const res = await this.http.get({
97
147
  endpoint: `/chunks/${this.token}/-1/-1?chunkSize=${this.chunkByteCount}`,
98
148
  headers: chunkingHeader,