@ardrive/turbo-sdk 1.41.3 → 1.42.0-alpha.10
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/lib/cjs/cli/cli.js +61 -0
- package/lib/cjs/cli/commands/arns.js +317 -0
- package/lib/cjs/cli/commands/freeStatus.js +47 -0
- package/lib/cjs/cli/commands/index.js +3 -0
- package/lib/cjs/cli/commands/paymentHistory.js +25 -0
- package/lib/cjs/cli/options.js +124 -11
- package/lib/cjs/cli/utils.js +3 -19
- package/lib/cjs/common/arnsActions.js +102 -0
- package/lib/cjs/common/factory.js +1 -3
- package/lib/cjs/common/http.js +20 -5
- package/lib/cjs/common/index.js +6 -0
- package/lib/cjs/common/payment.js +482 -3
- package/lib/cjs/common/signer.js +27 -6
- package/lib/cjs/common/token/ario.js +104 -83
- package/lib/cjs/common/token/index.js +0 -11
- package/lib/cjs/common/token/solana.js +1 -0
- package/lib/cjs/common/turbo.js +131 -0
- package/lib/cjs/common/upload.js +3 -2
- package/lib/cjs/node/factory.js +1 -3
- package/lib/cjs/types.js +44 -3
- package/lib/cjs/utils/common.js +5 -21
- package/lib/cjs/utils/errors.js +38 -1
- package/lib/cjs/utils/uuid.js +31 -0
- package/lib/cjs/web/factory.js +1 -3
- package/lib/cjs/web/signer.js +4 -2
- package/lib/esm/cli/cli.js +63 -2
- package/lib/esm/cli/commands/arns.js +300 -0
- package/lib/esm/cli/commands/freeStatus.js +44 -0
- package/lib/esm/cli/commands/index.js +3 -0
- package/lib/esm/cli/commands/paymentHistory.js +22 -0
- package/lib/esm/cli/options.js +123 -10
- package/lib/esm/cli/utils.js +4 -20
- package/lib/esm/common/arnsActions.js +93 -0
- package/lib/esm/common/factory.js +1 -3
- package/lib/esm/common/http.js +19 -4
- package/lib/esm/common/index.js +6 -0
- package/lib/esm/common/payment.js +482 -3
- package/lib/esm/common/signer.js +28 -7
- package/lib/esm/common/token/ario.js +102 -84
- package/lib/esm/common/token/index.js +1 -12
- package/lib/esm/common/token/solana.js +1 -0
- package/lib/esm/common/turbo.js +131 -0
- package/lib/esm/common/upload.js +4 -3
- package/lib/esm/node/factory.js +1 -3
- package/lib/esm/types.js +43 -2
- package/lib/esm/utils/common.js +4 -20
- package/lib/esm/utils/errors.js +35 -0
- package/lib/esm/utils/uuid.js +28 -0
- package/lib/esm/web/factory.js +1 -3
- package/lib/esm/web/signer.js +4 -2
- package/lib/types/cli/commands/arns.d.ts +86 -0
- package/lib/types/cli/commands/arns.d.ts.map +1 -0
- package/lib/types/cli/commands/freeStatus.d.ts +3 -0
- package/lib/types/cli/commands/freeStatus.d.ts.map +1 -0
- package/lib/types/cli/commands/index.d.ts +3 -0
- package/lib/types/cli/commands/index.d.ts.map +1 -1
- package/lib/types/cli/commands/paymentHistory.d.ts +18 -0
- package/lib/types/cli/commands/paymentHistory.d.ts.map +1 -0
- package/lib/types/cli/options.d.ts +238 -10
- package/lib/types/cli/options.d.ts.map +1 -1
- package/lib/types/cli/types.d.ts +41 -2
- package/lib/types/cli/types.d.ts.map +1 -1
- package/lib/types/cli/utils.d.ts.map +1 -1
- package/lib/types/common/arnsActions.d.ts +43 -0
- package/lib/types/common/arnsActions.d.ts.map +1 -0
- package/lib/types/common/factory.d.ts +1 -1
- package/lib/types/common/factory.d.ts.map +1 -1
- package/lib/types/common/http.d.ts +14 -1
- package/lib/types/common/http.d.ts.map +1 -1
- package/lib/types/common/index.d.ts +2 -0
- package/lib/types/common/index.d.ts.map +1 -1
- package/lib/types/common/payment.d.ts +230 -1
- package/lib/types/common/payment.d.ts.map +1 -1
- package/lib/types/common/signer.d.ts +12 -6
- package/lib/types/common/signer.d.ts.map +1 -1
- package/lib/types/common/token/ario.d.ts +13 -9
- package/lib/types/common/token/ario.d.ts.map +1 -1
- package/lib/types/common/token/index.d.ts.map +1 -1
- package/lib/types/common/token/solana.d.ts.map +1 -1
- package/lib/types/common/turbo.d.ts +140 -1
- package/lib/types/common/turbo.d.ts.map +1 -1
- package/lib/types/common/upload.d.ts.map +1 -1
- package/lib/types/node/factory.d.ts +1 -1
- package/lib/types/node/factory.d.ts.map +1 -1
- package/lib/types/types.d.ts +483 -7
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/utils/common.d.ts +0 -12
- package/lib/types/utils/common.d.ts.map +1 -1
- package/lib/types/utils/errors.d.ts +29 -0
- package/lib/types/utils/errors.d.ts.map +1 -1
- package/lib/types/utils/uuid.d.ts +7 -0
- package/lib/types/utils/uuid.d.ts.map +1 -0
- package/lib/types/web/factory.d.ts +1 -1
- package/lib/types/web/factory.d.ts.map +1 -1
- package/lib/types/web/signer.d.ts +1 -1
- package/lib/types/web/signer.d.ts.map +1 -1
- package/package.json +3 -2
package/lib/esm/cli/options.js
CHANGED
|
@@ -73,16 +73,6 @@ export const optionMap = {
|
|
|
73
73
|
description: 'Set a custom payment service URL',
|
|
74
74
|
default: undefined,
|
|
75
75
|
},
|
|
76
|
-
processId: {
|
|
77
|
-
alias: '--process-id <processId>',
|
|
78
|
-
description: 'Set a custom target process ID for the action',
|
|
79
|
-
default: undefined,
|
|
80
|
-
},
|
|
81
|
-
cuUrl: {
|
|
82
|
-
alias: '--cu-url <cuUrl>',
|
|
83
|
-
description: 'Set a custom CU URL for the action',
|
|
84
|
-
default: undefined,
|
|
85
|
-
},
|
|
86
76
|
dev: {
|
|
87
77
|
alias: '--dev',
|
|
88
78
|
description: 'Enable Turbo development endpoints',
|
|
@@ -196,6 +186,60 @@ export const optionMap = {
|
|
|
196
186
|
alias: '--max-crypto-top-up-value <maxCryptoTopUpValue>',
|
|
197
187
|
description: 'Maximum crypto top-up value to use for the upload. Defaults to no limit.',
|
|
198
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
|
+
// ---- Payment history ----
|
|
235
|
+
limit: {
|
|
236
|
+
alias: '--limit <limit>',
|
|
237
|
+
description: 'Max number of payment-history rows to return (1-100, default 50)',
|
|
238
|
+
},
|
|
239
|
+
cursor: {
|
|
240
|
+
alias: '--cursor <cursor>',
|
|
241
|
+
description: 'Opaque pagination cursor from a prior payment-history response',
|
|
242
|
+
},
|
|
199
243
|
};
|
|
200
244
|
export const walletOptions = [
|
|
201
245
|
optionMap.walletFile,
|
|
@@ -249,3 +293,72 @@ export const shareCreditsOptions = [
|
|
|
249
293
|
];
|
|
250
294
|
export const revokeCreditsOptions = [...walletOptions, optionMap.address];
|
|
251
295
|
export const listSharesOptions = revokeCreditsOptions;
|
|
296
|
+
// ---- ArNS command option sets (token + --payment-url come from globalOptions) ----
|
|
297
|
+
export const arnsPriceOptions = [
|
|
298
|
+
optionMap.arnsName,
|
|
299
|
+
optionMap.arnsType,
|
|
300
|
+
optionMap.arnsYears,
|
|
301
|
+
optionMap.arnsIncreaseQty,
|
|
302
|
+
];
|
|
303
|
+
export const arnsFiatQuoteOptions = [
|
|
304
|
+
optionMap.arnsName,
|
|
305
|
+
optionMap.arnsType,
|
|
306
|
+
optionMap.arnsYears,
|
|
307
|
+
optionMap.arnsIncreaseQty,
|
|
308
|
+
optionMap.address,
|
|
309
|
+
optionMap.currency,
|
|
310
|
+
{
|
|
311
|
+
alias: '--method <method>',
|
|
312
|
+
description: 'Stripe integration mode: payment-intent (default) or checkout-session',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
alias: '--promo-code <promoCode...>',
|
|
316
|
+
description: 'Promo code(s) to apply to the fiat price',
|
|
317
|
+
},
|
|
318
|
+
];
|
|
319
|
+
export const buyArNSNameOptions = [
|
|
320
|
+
...walletOptions,
|
|
321
|
+
optionMap.arnsName,
|
|
322
|
+
optionMap.arnsType,
|
|
323
|
+
optionMap.arnsYears,
|
|
324
|
+
optionMap.arnsOwnerKey,
|
|
325
|
+
optionMap.paidBy,
|
|
326
|
+
];
|
|
327
|
+
export const extendArNSLeaseOptions = [
|
|
328
|
+
...walletOptions,
|
|
329
|
+
optionMap.arnsName,
|
|
330
|
+
optionMap.arnsYears,
|
|
331
|
+
optionMap.paidBy,
|
|
332
|
+
];
|
|
333
|
+
export const increaseArNSUndernamesOptions = [
|
|
334
|
+
...walletOptions,
|
|
335
|
+
optionMap.arnsName,
|
|
336
|
+
optionMap.arnsIncreaseQty,
|
|
337
|
+
optionMap.paidBy,
|
|
338
|
+
];
|
|
339
|
+
export const upgradeArNSNameOptions = [
|
|
340
|
+
...walletOptions,
|
|
341
|
+
optionMap.arnsName,
|
|
342
|
+
optionMap.paidBy,
|
|
343
|
+
];
|
|
344
|
+
export const arnsPurchaseStatusOptions = [optionMap.arnsNonce];
|
|
345
|
+
export const transferArNSAntOptions = [
|
|
346
|
+
...walletOptions,
|
|
347
|
+
optionMap.arnsOwnerKey,
|
|
348
|
+
optionMap.arnsAntId,
|
|
349
|
+
optionMap.arnsTarget,
|
|
350
|
+
];
|
|
351
|
+
export const setArNSRecordOptions = [
|
|
352
|
+
...walletOptions,
|
|
353
|
+
optionMap.arnsOwnerKey,
|
|
354
|
+
optionMap.arnsAntId,
|
|
355
|
+
optionMap.arnsUndername,
|
|
356
|
+
optionMap.arnsTransactionId,
|
|
357
|
+
optionMap.arnsTtlSeconds,
|
|
358
|
+
];
|
|
359
|
+
export const removeArNSRecordOptions = [
|
|
360
|
+
...walletOptions,
|
|
361
|
+
optionMap.arnsOwnerKey,
|
|
362
|
+
optionMap.arnsAntId,
|
|
363
|
+
optionMap.arnsUndername,
|
|
364
|
+
];
|
package/lib/esm/cli/utils.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import bs58 from 'bs58';
|
|
17
17
|
import { readFileSync, statSync } from 'fs';
|
|
18
18
|
import { ExistingBalanceFunding, OnDemandFunding, TurboFactory, X402Funding, defaultTurboConfiguration, developmentTurboConfiguration, fiatCurrencyTypes, isCurrency, isTokenType, privateKeyFromKyveMnemonic, tokenToBaseMap, } from '../node/index.js';
|
|
19
|
-
import {
|
|
19
|
+
import { tokenToDevGatewayMap } from '../utils/common.js';
|
|
20
20
|
import { NoWalletProvidedError } from './errors.js';
|
|
21
21
|
export function exitWithErrorLog(error) {
|
|
22
22
|
console.error(error instanceof Error ? error.message : error);
|
|
@@ -100,7 +100,9 @@ export async function privateKeyFromOptions({ mnemonic, privateKey, walletFile,
|
|
|
100
100
|
}
|
|
101
101
|
else if (walletFile !== undefined) {
|
|
102
102
|
const wallet = JSON.parse(readFileSync(walletFile, 'utf-8'));
|
|
103
|
-
return token === 'solana'
|
|
103
|
+
return token === 'solana' || token === 'ario'
|
|
104
|
+
? bs58.encode(wallet)
|
|
105
|
+
: wallet;
|
|
104
106
|
}
|
|
105
107
|
else if (privateKey !== undefined) {
|
|
106
108
|
return privateKey;
|
|
@@ -114,8 +116,6 @@ export function configFromOptions(options) {
|
|
|
114
116
|
let paymentUrl = undefined;
|
|
115
117
|
let uploadUrl = undefined;
|
|
116
118
|
let gatewayUrl = undefined;
|
|
117
|
-
let processId = undefined;
|
|
118
|
-
let cuUrl = undefined;
|
|
119
119
|
if (options.local && options.dev) {
|
|
120
120
|
throw new Error('Cannot use both --local and --dev flags');
|
|
121
121
|
}
|
|
@@ -124,10 +124,6 @@ export function configFromOptions(options) {
|
|
|
124
124
|
paymentUrl = developmentTurboConfiguration.paymentServiceConfig.url;
|
|
125
125
|
uploadUrl = developmentTurboConfiguration.uploadServiceConfig.url;
|
|
126
126
|
gatewayUrl = tokenToDevGatewayMap[token];
|
|
127
|
-
if (options.token === 'ario') {
|
|
128
|
-
processId = tokenToDevAoConfigMap[token].processId;
|
|
129
|
-
cuUrl = tokenToDevAoConfigMap[token].cuUrl;
|
|
130
|
-
}
|
|
131
127
|
}
|
|
132
128
|
else if (options.local) {
|
|
133
129
|
// Use local endpoints
|
|
@@ -139,10 +135,6 @@ export function configFromOptions(options) {
|
|
|
139
135
|
// Use default endpoints
|
|
140
136
|
paymentUrl = defaultTurboConfiguration.paymentServiceConfig.url;
|
|
141
137
|
uploadUrl = defaultTurboConfiguration.uploadServiceConfig.url;
|
|
142
|
-
if (options.token === 'ario') {
|
|
143
|
-
processId = defaultProdAoConfigs[token].processId;
|
|
144
|
-
cuUrl = defaultProdAoConfigs[token].cuUrl;
|
|
145
|
-
}
|
|
146
138
|
}
|
|
147
139
|
// Override gateway, payment, and upload service default endpoints if provided
|
|
148
140
|
if (options.gateway !== undefined) {
|
|
@@ -154,19 +146,11 @@ export function configFromOptions(options) {
|
|
|
154
146
|
if (options.uploadUrl !== undefined) {
|
|
155
147
|
uploadUrl = options.uploadUrl;
|
|
156
148
|
}
|
|
157
|
-
if (options.cuUrl !== undefined) {
|
|
158
|
-
cuUrl = options.cuUrl;
|
|
159
|
-
}
|
|
160
|
-
if (options.processId !== undefined) {
|
|
161
|
-
processId = options.processId;
|
|
162
|
-
}
|
|
163
149
|
const config = {
|
|
164
150
|
paymentServiceConfig: { url: paymentUrl },
|
|
165
151
|
uploadServiceConfig: { url: uploadUrl },
|
|
166
152
|
gatewayUrl,
|
|
167
153
|
token,
|
|
168
|
-
processId,
|
|
169
|
-
cuUrl,
|
|
170
154
|
};
|
|
171
155
|
return config;
|
|
172
156
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
/** Solana's signature-type discriminator in Turbo's signed-request scheme. */
|
|
34
|
+
const SOLANA_SIGNATURE_TYPE = 4;
|
|
35
|
+
/**
|
|
36
|
+
* The ANT owner's half of the envelope, in its own `x-owner-*` headers.
|
|
37
|
+
*
|
|
38
|
+
* Two signatures travel on a record action — the PAYER's signed request over
|
|
39
|
+
* `"" + nonce`, and the OWNER's action-bound proof over `message + nonce` —
|
|
40
|
+
* from two different keys, usually on two different chains. They cannot share
|
|
41
|
+
* one header set: whichever verifier ran second would reject a signature that
|
|
42
|
+
* was never meant for it.
|
|
43
|
+
*/
|
|
44
|
+
export async function arNSOwnerProofHeaders(owner, message, nonce) {
|
|
45
|
+
const address = await owner.getAddress();
|
|
46
|
+
const signature = await owner.signMessage(Uint8Array.from(Buffer.from(message + nonce)));
|
|
47
|
+
return {
|
|
48
|
+
// A Solana address IS the base58-encoded 32-byte ed25519 public key, so
|
|
49
|
+
// decoding the address recovers exactly the bytes the bundler verifies
|
|
50
|
+
// against. Keeps ArNSOwnerSigner minimal — no separate getPublicKey().
|
|
51
|
+
'x-owner-public-key': toB64Url(Buffer.from(bs58.decode(address))),
|
|
52
|
+
'x-owner-nonce': nonce,
|
|
53
|
+
'x-owner-signature': toB64Url(Buffer.from(signature)),
|
|
54
|
+
'x-owner-signature-type': String(SOLANA_SIGNATURE_TYPE),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build an {@link ArNSOwnerSigner} from a raw Solana secret key.
|
|
59
|
+
*
|
|
60
|
+
* For servers and tests. A browser wallet (Phantom, Solflare, or a console's
|
|
61
|
+
* embedded wallet) should implement the interface directly against its own
|
|
62
|
+
* `signTransaction` / `signMessage` rather than exposing a secret key.
|
|
63
|
+
*
|
|
64
|
+
* Note the owner needs a key to SIGN with, not a funded account: Turbo is the
|
|
65
|
+
* fee payer on every sponsored action, so this wallet's SOL balance can stay
|
|
66
|
+
* at zero for the entire life of the name.
|
|
67
|
+
*/
|
|
68
|
+
export function solanaOwnerSigner(secretKey) {
|
|
69
|
+
const keypair = Keypair.fromSecretKey(typeof secretKey === 'string' ? bs58.decode(secretKey) : secretKey);
|
|
70
|
+
return {
|
|
71
|
+
getAddress: () => keypair.publicKey.toBase58(),
|
|
72
|
+
signTransaction: async (transactionBase64) => {
|
|
73
|
+
const tx = VersionedTransaction.deserialize(Buffer.from(transactionBase64, 'base64'));
|
|
74
|
+
// Sign the bytes as returned. Turbo's fee-payer signature already covers
|
|
75
|
+
// this exact message; rebuilding it from parts invalidates that and the
|
|
76
|
+
// submission is rejected.
|
|
77
|
+
tx.sign([keypair]);
|
|
78
|
+
return Buffer.from(tx.serialize()).toString('base64');
|
|
79
|
+
},
|
|
80
|
+
signMessage: async (message) => nacl.sign.detached(message, keypair.secretKey),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Count the signature slots a prepared transaction still has empty.
|
|
85
|
+
*
|
|
86
|
+
* Turbo pre-signs as fee payer and leaves exactly one slot for the owner, so a
|
|
87
|
+
* client can assert that before prompting a wallet — a cheap way to catch a
|
|
88
|
+
* malformed or already-signed transaction before bothering the user.
|
|
89
|
+
*/
|
|
90
|
+
export function emptySignatureSlots(transactionBase64) {
|
|
91
|
+
const tx = VersionedTransaction.deserialize(Buffer.from(transactionBase64, 'base64'));
|
|
92
|
+
return tx.signatures.filter((sig) => sig.every((byte) => byte === 0)).length;
|
|
93
|
+
}
|
|
@@ -43,7 +43,7 @@ export class TurboBaseFactory {
|
|
|
43
43
|
paymentService,
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
-
getAuthenticatedTurbo({ privateKey, signer: providedSigner, paymentServiceConfig = {}, uploadServiceConfig = {}, token, gatewayUrl, tokenMap, tokenTools, logger, walletAdapter,
|
|
46
|
+
getAuthenticatedTurbo({ privateKey, signer: providedSigner, paymentServiceConfig = {}, uploadServiceConfig = {}, token, gatewayUrl, tokenMap, tokenTools, logger, walletAdapter, }) {
|
|
47
47
|
token = token === 'pol' ? 'matic' : token;
|
|
48
48
|
if (!token) {
|
|
49
49
|
if (providedSigner) {
|
|
@@ -101,8 +101,6 @@ export class TurboBaseFactory {
|
|
|
101
101
|
tokenTools = tokenMap.arweave;
|
|
102
102
|
}
|
|
103
103
|
tokenTools = defaultTokenMap[token]?.({
|
|
104
|
-
cuUrl,
|
|
105
|
-
processId,
|
|
106
104
|
gatewayUrl,
|
|
107
105
|
logger,
|
|
108
106
|
});
|
package/lib/esm/common/http.js
CHANGED
|
@@ -30,6 +30,18 @@ const defaultHeaders = {
|
|
|
30
30
|
'x-turbo-source-version': version,
|
|
31
31
|
'x-turbo-source-identifier': 'turbo-sdk',
|
|
32
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Canonical x402 upload routes on the upload service.
|
|
35
|
+
*
|
|
36
|
+
* These were previously `/x402/data-item/{signed,unsigned}`. The service
|
|
37
|
+
* renamed them to `/x402/upload/*` and kept a `data-item/signed` alias, but not
|
|
38
|
+
* a `data-item/unsigned` one — so every unsigned x402 upload 404ed. Both
|
|
39
|
+
* canonical paths are served by all released upload-service versions.
|
|
40
|
+
*/
|
|
41
|
+
export const x402UploadEndpoints = {
|
|
42
|
+
signed: '/x402/upload/signed',
|
|
43
|
+
unsigned: '/x402/upload/unsigned',
|
|
44
|
+
};
|
|
33
45
|
export class TurboHTTPService {
|
|
34
46
|
constructor({ url, logger, retryConfig = defaultRetryConfig(logger), }) {
|
|
35
47
|
this.logger = logger;
|
|
@@ -43,7 +55,7 @@ export class TurboHTTPService {
|
|
|
43
55
|
signal,
|
|
44
56
|
}), allowedStatuses);
|
|
45
57
|
}
|
|
46
|
-
async post({ endpoint, signal, allowedStatuses = [200, 202], headers, data, x402Options, }) {
|
|
58
|
+
async post({ endpoint, signal, allowedStatuses = [200, 202], headers, data, x402Options, retry = true, }) {
|
|
47
59
|
if (x402Options !== undefined) {
|
|
48
60
|
return this.x402Post({
|
|
49
61
|
signal,
|
|
@@ -55,9 +67,10 @@ export class TurboHTTPService {
|
|
|
55
67
|
}
|
|
56
68
|
// Convert all data types to fetch-compatible body
|
|
57
69
|
const { body, duplex } = await toFetchBody(data);
|
|
58
|
-
// Use retry for Buffer/Uint8Array, tryRequest for streams
|
|
70
|
+
// Use retry for Buffer/Uint8Array, tryRequest for streams. Callers can opt
|
|
71
|
+
// out of retry for non-idempotent signed writes via `retry: false`.
|
|
59
72
|
const isReusableData = data instanceof Buffer || data instanceof Uint8Array;
|
|
60
|
-
const requestFn = isReusableData
|
|
73
|
+
const requestFn = isReusableData && retry
|
|
61
74
|
? this.withRetry.bind(this)
|
|
62
75
|
: this.tryRequest.bind(this);
|
|
63
76
|
return requestFn(() => fetch(this.baseURL + endpoint, {
|
|
@@ -119,7 +132,9 @@ export class TurboHTTPService {
|
|
|
119
132
|
throw new FailedRequestError('Max retries reached - ' + lastError?.message, lastError?.status);
|
|
120
133
|
}
|
|
121
134
|
async x402Post({ signal, allowedStatuses, headers, data, x402Options, }) {
|
|
122
|
-
const endpoint =
|
|
135
|
+
const endpoint = x402Options.unsignedData
|
|
136
|
+
? x402UploadEndpoints.unsigned
|
|
137
|
+
: x402UploadEndpoints.signed;
|
|
123
138
|
this.logger.debug('Using X402 options for POST request', {
|
|
124
139
|
endpoint,
|
|
125
140
|
x402Options,
|
package/lib/esm/common/index.js
CHANGED
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
*/
|
|
16
16
|
export * from './upload.js';
|
|
17
17
|
export * from './payment.js';
|
|
18
|
+
// The ANT-owner helpers. Without this the documented
|
|
19
|
+
// `import { solanaOwnerSigner } from '@ardrive/turbo-sdk'` does not resolve.
|
|
20
|
+
export * from './arnsActions.js';
|
|
18
21
|
export * from './turbo.js';
|
|
19
22
|
export * from './currency.js';
|
|
20
23
|
export * from './token/index.js';
|
|
24
|
+
// Typed errors so consumers can `catch (e) { if (e instanceof InsufficientCreditsError) ... }`
|
|
25
|
+
// e.g. to prompt a top-up on a 402 ArNS purchase.
|
|
26
|
+
export * from '../utils/errors.js';
|