@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
|
@@ -13,106 +13,124 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { createAssociatedTokenAccountIdempotentInstruction, createTransferCheckedInstruction, getAssociatedTokenAddressSync, } from '@solana/spl-token';
|
|
17
|
+
import { Connection, PublicKey, Transaction, TransactionInstruction, } from '@solana/web3.js';
|
|
18
18
|
import { BigNumber } from 'bignumber.js';
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
19
|
+
import bs58 from 'bs58';
|
|
20
|
+
import { defaultProdGatewayUrls, sleep } from '../../utils/common.js';
|
|
21
21
|
import { Logger } from '../logger.js';
|
|
22
|
+
import { memoProgramId } from './solana.js';
|
|
23
|
+
const ARIO_SPL_MINT_ADDRESS = 'DcNnMuFxwhgV4WY1HVSaSEgr92bv2b1vUvEKiNxWqHdF';
|
|
24
|
+
const DEVNET_ARIO_SPL_MINT_ADDRESS = '6vTw5CysRXQ4ybbHkDUiisHWVsBeMtUzYvJqs2iqHyaN';
|
|
25
|
+
const ARIO_TOKEN_DECIMALS = 6;
|
|
22
26
|
export class ARIOToken {
|
|
23
|
-
constructor({
|
|
27
|
+
constructor({ gatewayUrl = defaultProdGatewayUrls.solana, logger = Logger.default, pollingOptions = {
|
|
28
|
+
maxAttempts: 10,
|
|
29
|
+
pollingIntervalMs: 2_500,
|
|
24
30
|
initialBackoffMs: 500,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
this.ao = connect({
|
|
29
|
-
CU_URL: cuUrl,
|
|
30
|
-
});
|
|
31
|
-
this.processId = processId;
|
|
31
|
+
}, } = {}) {
|
|
32
|
+
this.gatewayUrl = gatewayUrl;
|
|
33
|
+
this.connection = new Connection(gatewayUrl, 'confirmed');
|
|
32
34
|
this.pollingOptions = pollingOptions;
|
|
33
35
|
this.logger = logger;
|
|
36
|
+
if (gatewayUrl.includes('devnet')) {
|
|
37
|
+
this.mintAddress = DEVNET_ARIO_SPL_MINT_ADDRESS;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.mintAddress = ARIO_SPL_MINT_ADDRESS;
|
|
41
|
+
}
|
|
34
42
|
}
|
|
35
|
-
async createAndSubmitTx({ target, signer
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
value: tokenAmount.toString(),
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'Turbo-SDK',
|
|
51
|
-
value: version,
|
|
52
|
-
},
|
|
53
|
-
];
|
|
43
|
+
async createAndSubmitTx({ target, signer, tokenAmount, turboCreditDestinationAddress, }) {
|
|
44
|
+
const ownerPublicKey = new PublicKey(bs58.encode(Uint8Array.from(await signer.getPublicKey())));
|
|
45
|
+
const recipient = new PublicKey(target);
|
|
46
|
+
const mint = new PublicKey(this.mintAddress);
|
|
47
|
+
const fromAta = getAssociatedTokenAddressSync(mint, ownerPublicKey);
|
|
48
|
+
const toAta = getAssociatedTokenAddressSync(mint, recipient);
|
|
49
|
+
const tx = new Transaction({
|
|
50
|
+
feePayer: ownerPublicKey,
|
|
51
|
+
...(await this.connection.getLatestBlockhash()),
|
|
52
|
+
});
|
|
53
|
+
tx.add(createAssociatedTokenAccountIdempotentInstruction(ownerPublicKey, toAta, recipient, mint));
|
|
54
|
+
tx.add(createTransferCheckedInstruction(fromAta, mint, toAta, ownerPublicKey, BigInt(new BigNumber(tokenAmount).toFixed(0)), ARIO_TOKEN_DECIMALS));
|
|
54
55
|
if (turboCreditDestinationAddress !== undefined) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
tx.add(new TransactionInstruction({
|
|
57
|
+
programId: new PublicKey(memoProgramId),
|
|
58
|
+
keys: [],
|
|
59
|
+
data: Buffer.from('turboCreditDestinationAddress=' + turboCreditDestinationAddress),
|
|
60
|
+
}));
|
|
59
61
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.logger.debug('Submitted
|
|
62
|
+
const serializedTx = tx.serializeMessage();
|
|
63
|
+
const signature = await signer.signData(Uint8Array.from(serializedTx));
|
|
64
|
+
tx.addSignature(ownerPublicKey, Buffer.from(signature));
|
|
65
|
+
const txId = bs58.encode(signature);
|
|
66
|
+
await this.submitTx(tx, txId);
|
|
67
|
+
this.logger.debug('Submitted ARIO SPL transfer transaction...', {
|
|
66
68
|
id: txId,
|
|
67
69
|
target,
|
|
68
70
|
tokenAmount,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
fromAta: fromAta.toBase58(),
|
|
72
|
+
toAta: toAta.toBase58(),
|
|
73
|
+
mint: mint.toBase58(),
|
|
71
74
|
});
|
|
72
75
|
return { id: txId, target, reward: '0' };
|
|
73
76
|
}
|
|
74
|
-
async
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (!('publicKey' in signer)) {
|
|
84
|
-
return createDataItemSigner(signer);
|
|
85
|
-
}
|
|
86
|
-
const aoSigner = async ({ data, tags, target, anchor }) => {
|
|
87
|
-
// ensure appropriate permissions are granted with injected signers.
|
|
88
|
-
if (signer.publicKey === undefined &&
|
|
89
|
-
'setPublicKey' in signer &&
|
|
90
|
-
typeof signer.setPublicKey === 'function') {
|
|
91
|
-
await signer.setPublicKey();
|
|
77
|
+
async submitTx(tx, id) {
|
|
78
|
+
this.logger.debug('Submitting ARIO fund transaction...', { id });
|
|
79
|
+
await this.connection.sendRawTransaction(tx.serialize(), {
|
|
80
|
+
maxRetries: this.pollingOptions.maxAttempts,
|
|
81
|
+
});
|
|
82
|
+
if (tx.recentBlockhash === undefined ||
|
|
83
|
+
tx.lastValidBlockHeight === undefined) {
|
|
84
|
+
throw new Error('Failed to submit Transaction -- missing blockhash or lastValidBlockHeight from transaction creation. Solana Gateway Url:' +
|
|
85
|
+
this.gatewayUrl);
|
|
92
86
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
await this.connection.confirmTransaction({
|
|
88
|
+
signature: id,
|
|
89
|
+
blockhash: tx.recentBlockhash,
|
|
90
|
+
lastValidBlockHeight: tx.lastValidBlockHeight,
|
|
91
|
+
}, 'finalized');
|
|
92
|
+
}
|
|
93
|
+
async pollTxAvailability({ txId }) {
|
|
94
|
+
const { maxAttempts, pollingIntervalMs, initialBackoffMs } = this.pollingOptions;
|
|
95
|
+
this.logger.debug('Polling for ARIO SPL transaction...', {
|
|
96
|
+
txId,
|
|
97
|
+
pollingOptions: this.pollingOptions,
|
|
98
|
+
gatewayUrl: this.gatewayUrl,
|
|
99
|
+
});
|
|
100
|
+
await sleep(initialBackoffMs);
|
|
101
|
+
let attempts = 0;
|
|
102
|
+
while (attempts < maxAttempts) {
|
|
103
|
+
let status;
|
|
104
|
+
attempts++;
|
|
105
|
+
try {
|
|
106
|
+
const statuses = await this.connection.getSignatureStatuses([txId], {
|
|
107
|
+
searchTransactionHistory: true,
|
|
108
|
+
});
|
|
109
|
+
status = {
|
|
110
|
+
context: statuses.context,
|
|
111
|
+
value: statuses.value[0],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
this.logger.debug('Failed to poll ARIO SPL transaction...', { err });
|
|
116
|
+
}
|
|
117
|
+
if (status && status.value && status.value.err !== null) {
|
|
118
|
+
throw new Error(`Transaction failed: ${status.value.err}`);
|
|
119
|
+
}
|
|
120
|
+
if (status && status.value && status.value.slot !== null) {
|
|
121
|
+
this.logger.debug('Transaction found!', { txId, status });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
this.logger.debug('ARIO SPL transaction not found, polling...', {
|
|
125
|
+
txId,
|
|
126
|
+
attempts,
|
|
127
|
+
maxAttempts,
|
|
128
|
+
pollingIntervalMs,
|
|
100
129
|
});
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
id: dataItem.id,
|
|
104
|
-
raw: dataItem.getRaw(),
|
|
105
|
-
};
|
|
130
|
+
await sleep(pollingIntervalMs);
|
|
106
131
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const signedData = {
|
|
110
|
-
id: dataItem.id,
|
|
111
|
-
raw: dataItem.getRaw(),
|
|
112
|
-
};
|
|
113
|
-
return signedData;
|
|
114
|
-
};
|
|
115
|
-
// eslint-disable-next-line
|
|
116
|
-
// @ts-ignore Buffer vs ArrayBuffer type mismatch
|
|
117
|
-
return aoSigner;
|
|
132
|
+
throw new Error('Transaction not found after polling, transaction id: ' + txId);
|
|
133
|
+
}
|
|
118
134
|
}
|
|
135
|
+
export const mARIOToTokenAmount = (mARIO) => mARIO;
|
|
136
|
+
export const ARIOToTokenAmount = (ario) => new BigNumber(ario).times(1e6).valueOf();
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { tokenTypes, } from '../../types.js';
|
|
2
|
-
import { defaultProdGatewayUrls } from '../../utils/common.js';
|
|
3
2
|
import { ARIOToTokenAmount, ARIOToken } from './ario.js';
|
|
4
3
|
import { ARToTokenAmount, ArweaveToken } from './arweave.js';
|
|
5
|
-
import { BaseEthToken
|
|
6
|
-
import { ERC20Token } from './erc20.js';
|
|
4
|
+
import { BaseEthToken } from './baseEth.js';
|
|
7
5
|
import { ETHToTokenAmount, EthereumToken } from './ethereum.js';
|
|
8
6
|
import { KYVEToTokenAmount, KyveToken } from './kyve.js';
|
|
9
7
|
import { POLToTokenAmount, PolygonToken } from './polygon.js';
|
|
10
8
|
import { SOLToTokenAmount, SolanaToken } from './solana.js';
|
|
11
9
|
import { USDCToTokenAmount, USDCToken } from './usdc.js';
|
|
12
|
-
const baseARIOContractAddress = '0x138746adfA52909E5920def027f5a8dc1C7EfFb6';
|
|
13
10
|
export const defaultTokenMap = {
|
|
14
11
|
arweave: (config) => new ArweaveToken(config),
|
|
15
12
|
ario: (config) => new ARIOToken(config),
|
|
@@ -22,12 +19,6 @@ export const defaultTokenMap = {
|
|
|
22
19
|
usdc: (config) => new USDCToken({ network: 'ethereum', ...config }),
|
|
23
20
|
'base-usdc': (config) => new USDCToken({ network: 'base', ...config }),
|
|
24
21
|
'polygon-usdc': (config) => new USDCToken({ network: 'polygon', ...config }),
|
|
25
|
-
'base-ario': (config) => new ERC20Token({
|
|
26
|
-
...config,
|
|
27
|
-
pollingOptions: config.pollingOptions ?? defaultBaseNetworkPollingOptions,
|
|
28
|
-
tokenContractAddress: baseARIOContractAddress,
|
|
29
|
-
gatewayUrl: config.gatewayUrl ?? defaultProdGatewayUrls['base-ario'],
|
|
30
|
-
}),
|
|
31
22
|
};
|
|
32
23
|
const ethExponent = 18;
|
|
33
24
|
const usdcExponent = 6;
|
|
@@ -35,7 +26,6 @@ const arioExponent = 6;
|
|
|
35
26
|
export const exponentMap = {
|
|
36
27
|
arweave: 12,
|
|
37
28
|
ario: arioExponent,
|
|
38
|
-
'base-ario': arioExponent,
|
|
39
29
|
solana: 9,
|
|
40
30
|
ethereum: ethExponent,
|
|
41
31
|
'base-eth': ethExponent,
|
|
@@ -49,7 +39,6 @@ export const exponentMap = {
|
|
|
49
39
|
export const tokenToBaseMap = {
|
|
50
40
|
arweave: (a) => ARToTokenAmount(a),
|
|
51
41
|
ario: (a) => ARIOToTokenAmount(a),
|
|
52
|
-
'base-ario': (a) => USDCToTokenAmount(a),
|
|
53
42
|
solana: (a) => SOLToTokenAmount(a),
|
|
54
43
|
ethereum: (a) => ETHToTokenAmount(a),
|
|
55
44
|
'base-eth': (a) => ETHToTokenAmount(a),
|
|
@@ -106,6 +106,7 @@ export class SolanaToken {
|
|
|
106
106
|
throw new Error(`Transaction failed: ${status.value.err}`);
|
|
107
107
|
}
|
|
108
108
|
if (status && status.value && status.value.slot !== null) {
|
|
109
|
+
this.logger.debug('Transaction found!', { txId, status });
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
112
|
this.logger.debug('Transaction not found, polling...', {
|
package/lib/esm/common/turbo.js
CHANGED
|
@@ -51,6 +51,45 @@ export class TurboUnauthenticatedClient {
|
|
|
51
51
|
getBalance(address) {
|
|
52
52
|
return this.paymentService.getBalance(address);
|
|
53
53
|
}
|
|
54
|
+
getFreeStatus(address) {
|
|
55
|
+
return this.paymentService.getFreeStatus(address);
|
|
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
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the ArNS names a wallet owns or controls via Turbo's custodial
|
|
71
|
+
* ArNS-with-credits feature. `custodial: true` on a returned name means
|
|
72
|
+
* Turbo still holds/manages its ANT (transfer/manage routes apply);
|
|
73
|
+
* `custodial: false` means self-custody (or an already-completed exit) and
|
|
74
|
+
* is informational only.
|
|
75
|
+
*
|
|
76
|
+
* To read a name's current records or lease/expiration state, use
|
|
77
|
+
* `@ar.io/sdk` directly against the returned `antId`.
|
|
78
|
+
*/
|
|
79
|
+
getArNSNames(address) {
|
|
80
|
+
return this.paymentService.getArNSNames(address);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Quote a fiat (Stripe) ArNS purchase — buy a name with a credit card in one
|
|
84
|
+
* step, no Turbo Credits top-up in between. Complete the returned
|
|
85
|
+
* `paymentSession` with Stripe, then poll {@link getArNSPurchaseStatus} using
|
|
86
|
+
* `purchaseQuote.nonce`.
|
|
87
|
+
*
|
|
88
|
+
* Throws `FiatPaymentsDisabledError` when the service has Stripe switched off.
|
|
89
|
+
*/
|
|
90
|
+
getArNSFiatPurchaseQuote(params) {
|
|
91
|
+
return this.paymentService.getArNSFiatPurchaseQuote(params);
|
|
92
|
+
}
|
|
54
93
|
/**
|
|
55
94
|
* Returns a list of all supported fiat currencies.
|
|
56
95
|
*/
|
|
@@ -155,6 +194,98 @@ export class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
|
|
|
155
194
|
getBalance(userAddress) {
|
|
156
195
|
return this.paymentService.getBalance(userAddress);
|
|
157
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Returns how many free-tier bytes the wallet can still upload for free
|
|
199
|
+
* (`bytesRemaining`), or `null` for an unlimited (exempt/partner) wallet.
|
|
200
|
+
*/
|
|
201
|
+
getFreeStatus(userAddress) {
|
|
202
|
+
return this.paymentService.getFreeStatus(userAddress);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Returns the signer's OWN completed top-up history (crypto + fiat), newest
|
|
206
|
+
* first and keyset-paginated. Signature-required and self-scoped: it only ever
|
|
207
|
+
* returns the signing wallet's rows. Pass `cursor` from a prior response's
|
|
208
|
+
* `cursor` field (with `hasMore === true`) to fetch the next page.
|
|
209
|
+
*/
|
|
210
|
+
getPaymentHistory(params) {
|
|
211
|
+
return this.paymentService.getPaymentHistory(params);
|
|
212
|
+
}
|
|
213
|
+
// ===== ArNS actions (sponsored) =====
|
|
214
|
+
//
|
|
215
|
+
// Thin delegations. The two-shape branch and the owner-proof construction
|
|
216
|
+
// live in the payment service; see its comments for why callers must branch
|
|
217
|
+
// on `status` rather than on which action they asked for.
|
|
218
|
+
/** Create an action. Debits credits HERE — capture the nonce before signing. */
|
|
219
|
+
createArNSAction(action, params, ownerProof) {
|
|
220
|
+
return this.paymentService.createArNSAction(action, params, ownerProof);
|
|
221
|
+
}
|
|
222
|
+
/** Submit the owner-signed transaction (FULL serialized tx, base64). */
|
|
223
|
+
signArNSAction(nonce, signedTransaction) {
|
|
224
|
+
return this.paymentService.signArNSAction(nonce, signedTransaction);
|
|
225
|
+
}
|
|
226
|
+
/** Status by nonce — open, needs no signature. Use it to resume. */
|
|
227
|
+
getArNSActionStatus(nonce) {
|
|
228
|
+
return this.paymentService.getArNSActionStatus(nonce);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Quote a fiat (Stripe) ArNS purchase for this signer's wallet — a credit-card
|
|
232
|
+
* buy in one step, with no Turbo Credits top-up in between. `address` defaults
|
|
233
|
+
* to the signer's native address; pass one to buy on another wallet's behalf.
|
|
234
|
+
*
|
|
235
|
+
* Complete the returned `paymentSession` with Stripe, then poll
|
|
236
|
+
* {@link getArNSPurchaseStatus} using `purchaseQuote.nonce`. Throws
|
|
237
|
+
* `FiatPaymentsDisabledError` when the service has Stripe switched off.
|
|
238
|
+
*/
|
|
239
|
+
getArNSFiatPurchaseQuote(params) {
|
|
240
|
+
return this.paymentService.getArNSFiatPurchaseQuote(params);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Buy a name. The ANT is minted straight to `owner`; Turbo never holds it.
|
|
244
|
+
* The only action that always needs the owner's signature — once, ever.
|
|
245
|
+
*/
|
|
246
|
+
buyArNSName(params) {
|
|
247
|
+
return this.paymentService.buyArNSName(params);
|
|
248
|
+
}
|
|
249
|
+
/** Extend a lease. No owner signature needed. */
|
|
250
|
+
extendArNSLease(params) {
|
|
251
|
+
return this.paymentService.extendArNSLease(params);
|
|
252
|
+
}
|
|
253
|
+
/** Raise the undername limit. No owner signature needed. */
|
|
254
|
+
increaseArNSUndernameLimit(params) {
|
|
255
|
+
return this.paymentService.increaseArNSUndernameLimit(params);
|
|
256
|
+
}
|
|
257
|
+
/** Upgrade a lease to a permanent name. No owner signature needed. */
|
|
258
|
+
upgradeArNSName(params) {
|
|
259
|
+
return this.paymentService.upgradeArNSName(params);
|
|
260
|
+
}
|
|
261
|
+
/** Point a name (or undername) at data. Free; handles both shapes. */
|
|
262
|
+
setArNSRecord(params) {
|
|
263
|
+
return this.paymentService.setArNSRecord(params);
|
|
264
|
+
}
|
|
265
|
+
/** Remove a record. Free; handles both shapes. */
|
|
266
|
+
removeArNSRecord(params) {
|
|
267
|
+
return this.paymentService.removeArNSRecord(params);
|
|
268
|
+
}
|
|
269
|
+
/** Grant controller rights — omit `target` for Turbo itself. Free. */
|
|
270
|
+
addArNSController(params) {
|
|
271
|
+
return this.paymentService.addArNSController(params);
|
|
272
|
+
}
|
|
273
|
+
/** Revoke controller rights. Always available, always free. */
|
|
274
|
+
removeArNSController(params) {
|
|
275
|
+
return this.paymentService.removeArNSController(params);
|
|
276
|
+
}
|
|
277
|
+
/** Hand the ANT to a new owner. Irreversible. Free. */
|
|
278
|
+
transferArNSAnt(params) {
|
|
279
|
+
return this.paymentService.transferArNSAnt(params);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Returns the ArNS names owned or controlled by the connected signer's
|
|
283
|
+
* wallet (or the given `userAddress`) via Turbo's custodial
|
|
284
|
+
* ArNS-with-credits feature.
|
|
285
|
+
*/
|
|
286
|
+
getArNSNames(userAddress) {
|
|
287
|
+
return this.paymentService.getArNSNames(userAddress);
|
|
288
|
+
}
|
|
158
289
|
/**
|
|
159
290
|
* Returns a list of all credit share approvals for the user.
|
|
160
291
|
*/
|
package/lib/esm/common/upload.js
CHANGED
|
@@ -22,7 +22,7 @@ import { FailedRequestError } from '../utils/errors.js';
|
|
|
22
22
|
import { ChunkedUploader } from './chunked.js';
|
|
23
23
|
import { TurboEventEmitter, createStreamWithUploadEvents } from './events.js';
|
|
24
24
|
import { defaultRetryConfig } from './http.js';
|
|
25
|
-
import { TurboHTTPService } from './http.js';
|
|
25
|
+
import { TurboHTTPService, x402UploadEndpoints } from './http.js';
|
|
26
26
|
import { exponentMap, tokenToBaseMap } from './index.js';
|
|
27
27
|
import { Logger } from './logger.js';
|
|
28
28
|
import { makeX402Signer } from './signer.js';
|
|
@@ -120,7 +120,9 @@ export class TurboUnauthenticatedUploadService {
|
|
|
120
120
|
};
|
|
121
121
|
return this.httpService.post({
|
|
122
122
|
data: dataBuffer,
|
|
123
|
-
|
|
123
|
+
// Only reached when no signer was supplied; the x402 path recomputes this
|
|
124
|
+
// from `unsignedData`. Both must name the same route.
|
|
125
|
+
endpoint: x402UploadEndpoints.unsigned,
|
|
124
126
|
signal,
|
|
125
127
|
headers: tags !== undefined
|
|
126
128
|
? { 'x-data-item-tags': JSON.stringify(tags) }
|
|
@@ -138,7 +140,6 @@ export class TurboAuthenticatedBaseUploadService extends TurboUnauthenticatedUpl
|
|
|
138
140
|
'solana',
|
|
139
141
|
'base-eth',
|
|
140
142
|
'base-usdc',
|
|
141
|
-
'base-ario',
|
|
142
143
|
];
|
|
143
144
|
this.signer = signer;
|
|
144
145
|
this.paymentService = paymentService;
|
package/lib/esm/node/factory.js
CHANGED
|
@@ -34,7 +34,7 @@ export class TurboFactory extends TurboBaseFactory {
|
|
|
34
34
|
// Import the TurboAuthenticatedUploadService class from the node upload module
|
|
35
35
|
return new TurboAuthenticatedUploadService(config);
|
|
36
36
|
}
|
|
37
|
-
static authenticated({ privateKey, signer: providedSigner, paymentServiceConfig = {}, uploadServiceConfig = {}, token, tokenMap, gatewayUrl, tokenTools, walletAdapter,
|
|
37
|
+
static authenticated({ privateKey, signer: providedSigner, paymentServiceConfig = {}, uploadServiceConfig = {}, token, tokenMap, gatewayUrl, tokenTools, walletAdapter, }) {
|
|
38
38
|
return new TurboFactory().getAuthenticatedTurbo({
|
|
39
39
|
privateKey,
|
|
40
40
|
signer: providedSigner,
|
|
@@ -45,8 +45,6 @@ export class TurboFactory extends TurboBaseFactory {
|
|
|
45
45
|
gatewayUrl,
|
|
46
46
|
tokenTools,
|
|
47
47
|
walletAdapter,
|
|
48
|
-
processId,
|
|
49
|
-
cuUrl,
|
|
50
48
|
logger: this.logger,
|
|
51
49
|
});
|
|
52
50
|
}
|
package/lib/esm/types.js
CHANGED
|
@@ -17,7 +17,6 @@ export function isCurrency(currency) {
|
|
|
17
17
|
export const tokenTypes = [
|
|
18
18
|
'arweave',
|
|
19
19
|
'ario',
|
|
20
|
-
'base-ario',
|
|
21
20
|
'solana',
|
|
22
21
|
'ethereum',
|
|
23
22
|
'kyve',
|
|
@@ -36,7 +35,6 @@ export const supportedEvmSignerTokens = new Set([
|
|
|
36
35
|
'polygon-usdc',
|
|
37
36
|
'usdc',
|
|
38
37
|
'base-usdc',
|
|
39
|
-
'base-ario',
|
|
40
38
|
]);
|
|
41
39
|
export class ExistingBalanceFunding {
|
|
42
40
|
}
|
|
@@ -94,3 +92,46 @@ export function isEthereumWalletAdapter(walletAdapter) {
|
|
|
94
92
|
return 'getSigner' in walletAdapter;
|
|
95
93
|
}
|
|
96
94
|
export const validChunkingModes = ['force', 'disabled', 'auto'];
|
|
95
|
+
// ===== ArNS purchases paid with Turbo credits (via the bundler REST API) =====
|
|
96
|
+
export const arNSPurchaseIntents = [
|
|
97
|
+
'Buy-Name',
|
|
98
|
+
'Extend-Lease',
|
|
99
|
+
'Increase-Undername-Limit',
|
|
100
|
+
'Upgrade-Name',
|
|
101
|
+
];
|
|
102
|
+
// ===== ArNS actions (sponsored — the current bundler surface) =====
|
|
103
|
+
/**
|
|
104
|
+
* The nine sponsored ArNS actions.
|
|
105
|
+
*
|
|
106
|
+
* NOT included, because the bundler does not sponsor them: `primary-name`,
|
|
107
|
+
* `release-name`, `reassign`, and ANT metadata (name/description/keywords/logo).
|
|
108
|
+
* Those stay on the direct-signer path and cost the user SOL.
|
|
109
|
+
*/
|
|
110
|
+
export const arNSActions = [
|
|
111
|
+
'buy-name',
|
|
112
|
+
'extend-lease',
|
|
113
|
+
'upgrade-name',
|
|
114
|
+
'increase-undername-limit',
|
|
115
|
+
'set-record',
|
|
116
|
+
'remove-record',
|
|
117
|
+
'add-controller',
|
|
118
|
+
'remove-controller',
|
|
119
|
+
'transfer',
|
|
120
|
+
];
|
|
121
|
+
// ===== ArNS purchases paid with fiat (Stripe) — no Turbo Credits in between ====
|
|
122
|
+
/**
|
|
123
|
+
* Stripe integration mode for a fiat ArNS purchase quote.
|
|
124
|
+
*
|
|
125
|
+
* - `payment-intent` — returns a Stripe PaymentIntent. Confirm it client-side
|
|
126
|
+
* with `stripe.confirmCardPayment(paymentSession.client_secret, ...)`.
|
|
127
|
+
* - `checkout-session` — returns a Stripe Checkout Session to redirect to
|
|
128
|
+
* (`uiMode: 'hosted'`) or embed (`uiMode: 'embedded'`).
|
|
129
|
+
*
|
|
130
|
+
* Widened with `string & Record<never, never>` so a method added service-side is
|
|
131
|
+
* still callable without an SDK bump, while the known values keep autocomplete.
|
|
132
|
+
* (`string & {}` is the usual idiom but trips the `ban-types` lint rule.)
|
|
133
|
+
*/
|
|
134
|
+
export const arNSFiatPurchaseMethods = [
|
|
135
|
+
'payment-intent',
|
|
136
|
+
'checkout-session',
|
|
137
|
+
];
|
package/lib/esm/utils/common.js
CHANGED
|
@@ -34,8 +34,7 @@ const polygonTestnetRpc = 'https://rpc-amoy.polygon.technology';
|
|
|
34
34
|
const baseMainnetRpc = 'https://mainnet.base.org';
|
|
35
35
|
export const tokenToDevGatewayMap = {
|
|
36
36
|
arweave: 'https://turbo-gateway.com', // No arweave test net
|
|
37
|
-
ario: 'https://
|
|
38
|
-
'base-ario': baseMainnetRpc, // No base-ario test net contract deployed
|
|
37
|
+
ario: 'https://api.devnet.solana.com',
|
|
39
38
|
solana: 'https://api.devnet.solana.com',
|
|
40
39
|
ethereum: ethTestnetRpc,
|
|
41
40
|
'base-eth': baseTestnetRpc,
|
|
@@ -46,16 +45,9 @@ export const tokenToDevGatewayMap = {
|
|
|
46
45
|
'base-usdc': baseTestnetRpc,
|
|
47
46
|
'polygon-usdc': polygonTestnetRpc,
|
|
48
47
|
};
|
|
49
|
-
export const tokenToDevAoConfigMap = {
|
|
50
|
-
ario: {
|
|
51
|
-
processId: 'agYcCFJtrMG6cqMuZfskIkFTGvUPddICmtQSBIoPdiA',
|
|
52
|
-
cuUrl: 'https://cu.ardrive.io',
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
48
|
export const defaultProdGatewayUrls = {
|
|
56
49
|
arweave: 'https://turbo-gateway.com',
|
|
57
|
-
ario: 'https://
|
|
58
|
-
'base-ario': baseMainnetRpc,
|
|
50
|
+
ario: 'https://api.mainnet-beta.solana.com',
|
|
59
51
|
solana: 'https://api.mainnet-beta.solana.com',
|
|
60
52
|
ethereum: 'https://cloudflare-eth.com/',
|
|
61
53
|
'base-eth': baseMainnetRpc,
|
|
@@ -66,12 +58,6 @@ export const defaultProdGatewayUrls = {
|
|
|
66
58
|
'base-usdc': baseMainnetRpc,
|
|
67
59
|
'polygon-usdc': 'https://polygon-rpc.com/',
|
|
68
60
|
};
|
|
69
|
-
export const defaultProdAoConfigs = {
|
|
70
|
-
ario: {
|
|
71
|
-
processId: 'qNvAoz0TgcH7DMg8BCVn8jF32QH5L6T29VjHxhHqqGE',
|
|
72
|
-
cuUrl: 'https://cu.ardrive.io',
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
61
|
export function createTurboSigner({ signer: clientProvidedSigner, privateKey: clientProvidedPrivateKey, token = 'arweave', }) {
|
|
76
62
|
if (clientProvidedSigner !== undefined) {
|
|
77
63
|
if (clientProvidedSigner instanceof InjectedEthereumSigner) {
|
|
@@ -91,6 +77,7 @@ export function createTurboSigner({ signer: clientProvidedSigner, privateKey: cl
|
|
|
91
77
|
}
|
|
92
78
|
switch (token) {
|
|
93
79
|
case 'solana':
|
|
80
|
+
case 'ario':
|
|
94
81
|
return new HexSolanaSigner(clientProvidedPrivateKey);
|
|
95
82
|
case 'ethereum':
|
|
96
83
|
case 'pol':
|
|
@@ -98,7 +85,6 @@ export function createTurboSigner({ signer: clientProvidedSigner, privateKey: cl
|
|
|
98
85
|
case 'base-eth':
|
|
99
86
|
case 'usdc':
|
|
100
87
|
case 'base-usdc':
|
|
101
|
-
case 'base-ario':
|
|
102
88
|
case 'polygon-usdc':
|
|
103
89
|
if (!isEthPrivateKey(clientProvidedPrivateKey)) {
|
|
104
90
|
throw new Error('A valid Ethereum private key must be provided for EthereumSigner.');
|
|
@@ -110,7 +96,6 @@ export function createTurboSigner({ signer: clientProvidedSigner, privateKey: cl
|
|
|
110
96
|
}
|
|
111
97
|
return signerFromKyvePrivateKey(clientProvidedPrivateKey);
|
|
112
98
|
case 'arweave':
|
|
113
|
-
case 'ario':
|
|
114
99
|
if (!isJWK(clientProvidedPrivateKey)) {
|
|
115
100
|
throw new Error('A JWK must be provided for ArweaveSigner.');
|
|
116
101
|
}
|
|
@@ -155,8 +140,8 @@ export function isValidKyveAddress(address) {
|
|
|
155
140
|
export function isValidUserAddress(address, type) {
|
|
156
141
|
switch (type) {
|
|
157
142
|
case 'arweave':
|
|
158
|
-
case 'ario':
|
|
159
143
|
return isValidArweaveBase64URL(address);
|
|
144
|
+
case 'ario':
|
|
160
145
|
case 'solana':
|
|
161
146
|
return isValidSolanaAddress(address);
|
|
162
147
|
case 'ethereum':
|
|
@@ -164,7 +149,6 @@ export function isValidUserAddress(address, type) {
|
|
|
164
149
|
case 'matic':
|
|
165
150
|
case 'pol':
|
|
166
151
|
case 'base-usdc':
|
|
167
|
-
case 'base-ario':
|
|
168
152
|
case 'usdc':
|
|
169
153
|
case 'polygon-usdc':
|
|
170
154
|
return isValidECDSAAddress(address);
|
package/lib/esm/utils/errors.js
CHANGED
|
@@ -35,6 +35,41 @@ export class ProvidedInputError extends BaseError {
|
|
|
35
35
|
super(message ?? `User has provided an invalid input`);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Raised when a credit-paid operation (e.g. an ArNS purchase) is rejected by the
|
|
40
|
+
* service because the paying wallet does not hold enough Turbo credits. Maps the
|
|
41
|
+
* bundler's HTTP `402 Payment Required` response to a typed, catchable error so
|
|
42
|
+
* callers can prompt a top-up without string-matching on messages.
|
|
43
|
+
*
|
|
44
|
+
* Recovery: top up the balance, then retry the SAME operation reusing the
|
|
45
|
+
* captured `nonce` (the nonce is the idempotency key), or mint a fresh request.
|
|
46
|
+
*/
|
|
47
|
+
export class InsufficientCreditsError extends BaseError {
|
|
48
|
+
constructor(message) {
|
|
49
|
+
super(message ??
|
|
50
|
+
'Insufficient Turbo credits to complete this purchase. Top up your balance and retry.');
|
|
51
|
+
/** Always the HTTP status that produced this error. */
|
|
52
|
+
this.status = 402;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Raised when the payment service has fiat (Stripe) payments switched off, which
|
|
57
|
+
* it signals with `503` and the body "Fiat (Stripe) ArNS payments are disabled".
|
|
58
|
+
* This is a normal state in the testnet sandbox, not an outage.
|
|
59
|
+
*
|
|
60
|
+
* Distinguished from a generic `503` deliberately: the same status is also used
|
|
61
|
+
* for internal errors (body "Internal Server Error: ..."), so status alone is
|
|
62
|
+
* ambiguous. Recovery: fall back to the credit-paid path (`buyArNSName` and
|
|
63
|
+
* friends), or surface fiat checkout as unavailable.
|
|
64
|
+
*/
|
|
65
|
+
export class FiatPaymentsDisabledError extends BaseError {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message ??
|
|
68
|
+
'Fiat (Stripe) payments are disabled on this payment service. Use the credit-paid purchase path instead.');
|
|
69
|
+
/** Always the HTTP status that produced this error. */
|
|
70
|
+
this.status = 503;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
38
73
|
export class AbortError extends BaseError {
|
|
39
74
|
constructor(message = 'Request was aborted') {
|
|
40
75
|
super(message);
|