@autonomys/auto-drive 1.6.8 → 1.6.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/README.md +102 -0
- package/dist/api/calls/index.d.ts +10 -0
- package/dist/api/calls/index.d.ts.map +1 -1
- package/dist/api/calls/index.js +12 -2
- package/dist/api/calls/payment.d.ts +66 -0
- package/dist/api/calls/payment.d.ts.map +1 -0
- package/dist/api/calls/payment.js +145 -0
- package/dist/api/models/index.d.ts +1 -0
- package/dist/api/models/index.d.ts.map +1 -1
- package/dist/api/models/index.js +1 -0
- package/dist/api/models/payment.d.ts +54 -0
- package/dist/api/models/payment.d.ts.map +1 -0
- package/dist/api/models/payment.js +2 -0
- package/dist/api/types.d.ts +63 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/wrappers.d.ts.map +1 -1
- package/dist/api/wrappers.js +12 -0
- package/package.json +5 -5
- package/src/api/calls/index.ts +13 -0
- package/src/api/calls/payment.ts +179 -0
- package/src/api/models/index.ts +1 -0
- package/src/api/models/payment.ts +67 -0
- package/src/api/types.ts +81 -0
- package/src/api/wrappers.ts +23 -0
package/README.md
CHANGED
|
@@ -312,6 +312,108 @@ try {
|
|
|
312
312
|
}
|
|
313
313
|
```
|
|
314
314
|
|
|
315
|
+
### Pay with AI3 — purchasing storage credits
|
|
316
|
+
|
|
317
|
+
Storage on the Autonomys Network is paid for with AI3 tokens via an on-chain payment intent flow. The SDK handles all of the Auto Drive API interactions; you supply the on-chain transaction using your preferred EVM wallet library (wagmi, viem, ethers, etc.).
|
|
318
|
+
|
|
319
|
+
#### The flow
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
0. getStoragePrice(api) → optional: show live price estimate before payment
|
|
323
|
+
1. createPaymentIntent(api, sizeBytes) → locks price, returns amount + contract details
|
|
324
|
+
2. send ai3AmountWei to contractAddress → payIntent(intentId) on-chain (your wallet code)
|
|
325
|
+
3. watchPaymentTransaction(api, id, tx) → notifies Auto Drive of your tx hash
|
|
326
|
+
4. waitForPaymentCompletion(api, id) → polls until COMPLETED (credits applied)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### Important: keep your API key server-side
|
|
330
|
+
|
|
331
|
+
`createPaymentIntent`, `watchPaymentTransaction`, and `getPaymentIntentStatus` all require an API key. In a web application these calls must be made from your server (e.g. a Next.js API route, an Express handler), not from the browser. `getStoragePrice` and `getPaymentContractInfo` are public endpoints and can be called from anywhere.
|
|
332
|
+
|
|
333
|
+
#### Getting a live price estimate
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// Public endpoint — no API key required. Good for showing a cost estimate
|
|
337
|
+
// before the user connects a wallet or commits to a payment.
|
|
338
|
+
const publicApi = createAutoDriveApi({ apiKey: null, network: NetworkId.MAINNET })
|
|
339
|
+
const { shannonsPerByte, ai3PerGb } = await publicApi.getStoragePrice()
|
|
340
|
+
|
|
341
|
+
console.log(`Current price: ${ai3PerGb} AI3/GB`)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Server-side example (Node / Next.js API route)
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
import { createAutoDriveApi } from '@autonomys/auto-drive'
|
|
348
|
+
import { NetworkId } from '@autonomys/auto-utils'
|
|
349
|
+
|
|
350
|
+
// Run on your server — never expose your API key to the browser
|
|
351
|
+
const api = createAutoDriveApi({ apiKey: process.env.AUTO_DRIVE_API_KEY!, network: NetworkId.MAINNET })
|
|
352
|
+
|
|
353
|
+
// Step 1 — create a price-locked intent for the content you want to store
|
|
354
|
+
const intent = await api.createPaymentIntent(contentSizeBytes)
|
|
355
|
+
// intent.ai3AmountWei — exact amount to send (as a BigInt-safe string)
|
|
356
|
+
// intent.ai3Amount — human-readable amount, e.g. "0.00123"
|
|
357
|
+
// intent.contractAddress — Credits Receiver contract on Auto EVM
|
|
358
|
+
// intent.intentId — pass as the bytes32 arg to payIntent()
|
|
359
|
+
// intent.expiresAt — ISO timestamp, intent expires after 10 minutes
|
|
360
|
+
|
|
361
|
+
// Step 2 — your client sends the on-chain transaction (see below)
|
|
362
|
+
// const txHash = await walletClient.writeContract({ ... })
|
|
363
|
+
|
|
364
|
+
// Step 3 — submit the tx hash so Auto Drive can watch it
|
|
365
|
+
await api.watchPaymentTransaction(intent.intentId, txHash)
|
|
366
|
+
|
|
367
|
+
// Step 4 — poll until credits are applied (or intent expires/fails)
|
|
368
|
+
const result = await api.waitForPaymentCompletion(intent.intentId)
|
|
369
|
+
// result: 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'
|
|
370
|
+
|
|
371
|
+
if (result === 'COMPLETED') {
|
|
372
|
+
console.log('Credits applied — ready to upload')
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Client-side example (browser, using viem)
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
import { createAutoDriveApi } from '@autonomys/auto-drive'
|
|
380
|
+
import { NetworkId } from '@autonomys/auto-utils'
|
|
381
|
+
import { createWalletClient, custom, parseGwei } from 'viem'
|
|
382
|
+
|
|
383
|
+
// Step 1 — fetch contract details (public endpoint, no API key needed)
|
|
384
|
+
const publicApi = createAutoDriveApi({ apiKey: null, network: NetworkId.MAINNET })
|
|
385
|
+
const contractInfo = await publicApi.getPaymentContractInfo()
|
|
386
|
+
|
|
387
|
+
// Step 2 — send the on-chain transaction with your wallet
|
|
388
|
+
const walletClient = createWalletClient({ transport: custom(window.ethereum) })
|
|
389
|
+
const [account] = await walletClient.requestAddresses()
|
|
390
|
+
|
|
391
|
+
const txHash = await walletClient.writeContract({
|
|
392
|
+
address: contractInfo.contractAddress as `0x${string}`,
|
|
393
|
+
abi: contractInfo.payIntentAbi,
|
|
394
|
+
functionName: 'payIntent',
|
|
395
|
+
args: [intent.intentId as `0x${string}`],
|
|
396
|
+
value: BigInt(intent.ai3AmountWei),
|
|
397
|
+
})
|
|
398
|
+
// Then call your server route to run steps 3 and 4
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### Polling with custom options
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
const result = await api.waitForPaymentCompletion(intent.intentId, {
|
|
405
|
+
pollIntervalMs: 5_000, // check every 5 seconds (default: 3 000)
|
|
406
|
+
timeoutMs: 120_000, // give up after 2 minutes (default: 300 000)
|
|
407
|
+
})
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
#### Checking intent status manually
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
const { id, status } = await api.getPaymentIntentStatus(intent.intentId)
|
|
414
|
+
// status: 'PENDING' | 'CONFIRMED' | 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'
|
|
415
|
+
```
|
|
416
|
+
|
|
315
417
|
## License
|
|
316
418
|
|
|
317
419
|
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
@@ -73,6 +73,15 @@ export declare const apiCalls: {
|
|
|
73
73
|
}>) => Promise<import("..").ObjectInformation["metadata"]>;
|
|
74
74
|
getMe: (api: import("..").AutoDriveApiHandler) => Promise<import("../models/user").UserInfo>;
|
|
75
75
|
getToBeReviewedList: (api: import("..").AutoDriveApiHandler, query: import("../../utils").ArgsWithPagination) => Promise<import("..").ObjectSummary[]>;
|
|
76
|
+
getStoragePrice: (api: import("..").AutoDriveApiHandler) => Promise<import("..").StoragePrice>;
|
|
77
|
+
getPaymentContractInfo: (api: import("..").AutoDriveApiHandler) => Promise<import("..").PaymentContractInfo>;
|
|
78
|
+
createPaymentIntent: (api: import("..").AutoDriveApiHandler, sizeBytes: number) => Promise<import("..").PaymentIntent>;
|
|
79
|
+
watchPaymentTransaction: (api: import("..").AutoDriveApiHandler, intentId: string, txHash: string) => Promise<void>;
|
|
80
|
+
getPaymentIntentStatus: (api: import("..").AutoDriveApiHandler, intentId: string) => Promise<{
|
|
81
|
+
id: string;
|
|
82
|
+
status: import("..").PaymentIntentStatus;
|
|
83
|
+
}>;
|
|
84
|
+
waitForPaymentCompletion: (api: import("..").AutoDriveApiHandler, intentId: string, { pollIntervalMs, timeoutMs }?: import("..").PollOptions) => Promise<import("..").PaymentIntentTerminalStatus>;
|
|
76
85
|
downloadObject: (api: import("..").AutoDriveApiHandler, query: import("../../utils").ArgsWithoutPagination<{
|
|
77
86
|
cid: string;
|
|
78
87
|
ignoreBackendEncoding?: boolean;
|
|
@@ -86,4 +95,5 @@ export declare const apiCalls: {
|
|
|
86
95
|
status: import("../models/asyncDownloads").DownloadStatus;
|
|
87
96
|
}>;
|
|
88
97
|
};
|
|
98
|
+
export { getStoragePrice, getPaymentContractInfo, createPaymentIntent, watchPaymentTransaction, getPaymentIntentStatus, waitForPaymentCompletion, } from './payment';
|
|
89
99
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/calls/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/calls/index.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,QAAQ;kBAkByJ,qCAA2B,EAAC;;;MAAkE;0BAAqiC,qCAA2B,EAAC;;MAAgD;oBAAo7B,qCAA2B,EAAC;;MAAgD;oBAAy6B,qCAA2B,EAAC;;MAAgD;;;mBAAq3B,qCAA2B,EAAC;;MAAgD;gBAAuzB,qCAA2B,EAAC;;MAAgD;oBAAy3B,qCAA2B,EAAC;;MAAgD;uBAAjxL,qCAA2B,EAAC;gBAAkG,CAAC;;;MAA8E;yBAA4iC,qCAA2B,EAAC;;qBAA2G,CAAC;MAAsB;yCAA+1C,qCAA2B,EAAC;;;gBAAkK,CAAC;;;MAAyE;sBAAm1C,qCAA2B,EAAC;;;;MAAuH;qBAA6qC,qCAA2B,EAAC;;MAA4D;eAAz7L,qCAA2B,EAAC;;MAA8C;sBAA89B,qCAA2B,EAAC,+CAA4B;wBAA0X,qCAA2B,EAAC;;;MAAgE;iBAAg8B,qCAA2B,EAAC,+CAA4B;gBAA88B,qCAA2B,EAAC;;MAAgD;uBAAo1B,qCAA2B,EAAC;;MAAgD;4BAAi+B,qCAA2B,EAAC;;MAAgD;sBAAq+B,qCAA2B,EAAC;;MAAgD;wBAAggC,qCAA2B,EAAC;;MAAgD;YAA+jB,qCAAwB;0BAA4yB,qCAA2B,EAAC,+CAA4B;sBAAlmS,qCAAwB;6BAAooB,qCAA2B;0BAAgwC,qCAA2B,EAAC,iBAAoB;8BAAshC,qCAA2B,EAAC,gBAAmB,EAAC,cAAiB;6BAA6kB,qCAA2B,EAAC,gBAAmB;;;;+BAAy5B,qCAA2B,EAAC,gBAAmB,EAAC,wDAAoE;qBAlB7zJ,qCACC,EAAC;;6BAIL,CAAC;MAGR;0BAUqN,qCAA2B,EAAC,WAAc;uBAAgV,qCAA2B,EAAC,kBAAqB;wBAAoV,qCAAwB;2BAAgV,qCAA2B,EAAC,kBAAqB;wBAA6R,qCAAwB,EAAC,WAAY;qBAA+G,qCAA2B,EAAC,WAAc;;;CAZ50D,CAAA;AAID,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,WAAW,CAAA"}
|
package/dist/api/calls/index.js
CHANGED
|
@@ -33,9 +33,19 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.apiCalls = void 0;
|
|
36
|
+
exports.waitForPaymentCompletion = exports.getPaymentIntentStatus = exports.watchPaymentTransaction = exports.createPaymentIntent = exports.getPaymentContractInfo = exports.getStoragePrice = exports.apiCalls = void 0;
|
|
37
37
|
const downloadCalls = __importStar(require("./download"));
|
|
38
|
+
const paymentCalls = __importStar(require("./payment"));
|
|
38
39
|
const readCalls = __importStar(require("./read"));
|
|
39
40
|
const uploadCalls = __importStar(require("./upload"));
|
|
40
41
|
const writeCalls = __importStar(require("./write"));
|
|
41
|
-
exports.apiCalls = Object.assign(Object.assign(Object.assign(Object.assign({}, downloadCalls), readCalls), uploadCalls), writeCalls);
|
|
42
|
+
exports.apiCalls = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, downloadCalls), paymentCalls), readCalls), uploadCalls), writeCalls);
|
|
43
|
+
// Re-export payment utilities as named exports so callers can use them
|
|
44
|
+
// as standalone functions without going through the apiCalls object.
|
|
45
|
+
var payment_1 = require("./payment");
|
|
46
|
+
Object.defineProperty(exports, "getStoragePrice", { enumerable: true, get: function () { return payment_1.getStoragePrice; } });
|
|
47
|
+
Object.defineProperty(exports, "getPaymentContractInfo", { enumerable: true, get: function () { return payment_1.getPaymentContractInfo; } });
|
|
48
|
+
Object.defineProperty(exports, "createPaymentIntent", { enumerable: true, get: function () { return payment_1.createPaymentIntent; } });
|
|
49
|
+
Object.defineProperty(exports, "watchPaymentTransaction", { enumerable: true, get: function () { return payment_1.watchPaymentTransaction; } });
|
|
50
|
+
Object.defineProperty(exports, "getPaymentIntentStatus", { enumerable: true, get: function () { return payment_1.getPaymentIntentStatus; } });
|
|
51
|
+
Object.defineProperty(exports, "waitForPaymentCompletion", { enumerable: true, get: function () { return payment_1.waitForPaymentCompletion; } });
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { PaymentContractInfo, PaymentIntent, PaymentIntentStatus, PaymentIntentTerminalStatus, PollOptions, StoragePrice } from '../models/payment';
|
|
2
|
+
import { AutoDriveApiHandler } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the current live storage price without creating a price-locked intent.
|
|
5
|
+
*
|
|
6
|
+
* This is a public endpoint — no API key is required.
|
|
7
|
+
* Use it to show a cost estimate to users before they commit to a payment.
|
|
8
|
+
*
|
|
9
|
+
* @returns `shannonsPerByte` — the raw on-chain price, and `ai3PerGb` — a
|
|
10
|
+
* pre-computed display value in AI3 per gigabyte.
|
|
11
|
+
*/
|
|
12
|
+
export declare const getStoragePrice: (api: AutoDriveApiHandler) => Promise<StoragePrice>;
|
|
13
|
+
/**
|
|
14
|
+
* Fetches the EVM chain ID, contract address, and ABI needed to call `payIntent(bytes32)`.
|
|
15
|
+
*
|
|
16
|
+
* This is a public endpoint — no API key is required. The result is stable
|
|
17
|
+
* per network and safe to cache for the lifetime of the application.
|
|
18
|
+
*/
|
|
19
|
+
export declare const getPaymentContractInfo: (api: AutoDriveApiHandler) => Promise<PaymentContractInfo>;
|
|
20
|
+
/**
|
|
21
|
+
* Creates a price-locked payment intent for a given upload size in bytes.
|
|
22
|
+
*
|
|
23
|
+
* The intent locks the current `shannonsPerByte` price for 10 minutes.
|
|
24
|
+
* The returned `ai3AmountWei` is the exact value to pass as `msg.value`
|
|
25
|
+
* when calling `payIntent(intentId)` on the Credits Receiver contract.
|
|
26
|
+
*
|
|
27
|
+
* Note: `sizeBytes` is **not** sent to the Auto Drive API. The POST `/intents`
|
|
28
|
+
* endpoint accepts no request body — it returns the current `shannonsPerByte`
|
|
29
|
+
* rate. The SDK multiplies that rate by `sizeBytes` to produce `ai3AmountWei`,
|
|
30
|
+
* saving the caller from doing the BigInt arithmetic themselves.
|
|
31
|
+
*
|
|
32
|
+
* Flow:
|
|
33
|
+
* 1. Call `createPaymentIntent(api, sizeBytes)` — locks the price
|
|
34
|
+
* 2. Send `intent.ai3AmountWei` to `intent.contractAddress` via `payIntent(intent.intentId)`
|
|
35
|
+
* 3. Call `watchPaymentTransaction(api, intent.intentId, txHash)` — submit the tx hash
|
|
36
|
+
* 4. Call `waitForPaymentCompletion(api, intent.intentId)` — poll until COMPLETED
|
|
37
|
+
*/
|
|
38
|
+
export declare const createPaymentIntent: (api: AutoDriveApiHandler, sizeBytes: number) => Promise<PaymentIntent>;
|
|
39
|
+
/**
|
|
40
|
+
* Notifies Auto Drive that an on-chain transaction has been submitted for a payment intent.
|
|
41
|
+
*
|
|
42
|
+
* Auto Drive will watch the transaction on-chain and automatically apply storage
|
|
43
|
+
* credits to your account once the transaction is confirmed.
|
|
44
|
+
*/
|
|
45
|
+
export declare const watchPaymentTransaction: (api: AutoDriveApiHandler, intentId: string, txHash: string) => Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the current status of a payment intent.
|
|
48
|
+
*
|
|
49
|
+
* Possible statuses: PENDING | CONFIRMED | COMPLETED | EXPIRED | FAILED | OVER_CAP
|
|
50
|
+
*/
|
|
51
|
+
export declare const getPaymentIntentStatus: (api: AutoDriveApiHandler, intentId: string) => Promise<{
|
|
52
|
+
id: string;
|
|
53
|
+
status: PaymentIntentStatus;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Polls a payment intent at regular intervals until it reaches a terminal state.
|
|
57
|
+
*
|
|
58
|
+
* Returns the terminal status: COMPLETED | EXPIRED | FAILED | OVER_CAP.
|
|
59
|
+
* Throws if the timeout is exceeded before a terminal state is reached.
|
|
60
|
+
*
|
|
61
|
+
* @param api - An authenticated AutoDriveApiHandler
|
|
62
|
+
* @param intentId - The intent ID returned by `createPaymentIntent`
|
|
63
|
+
* @param options - Optional poll interval and timeout (defaults: 3 s / 5 min)
|
|
64
|
+
*/
|
|
65
|
+
export declare const waitForPaymentCompletion: (api: AutoDriveApiHandler, intentId: string, { pollIntervalMs, timeoutMs }?: PollOptions) => Promise<PaymentIntentTerminalStatus>;
|
|
66
|
+
//# sourceMappingURL=payment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../../src/api/calls/payment.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,2BAA2B,EAC3B,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAS9C;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAU,KAAK,mBAAmB,KAAG,OAAO,CAAC,YAAY,CASpF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GACjC,KAAK,mBAAmB,KACvB,OAAO,CAAC,mBAAmB,CAQ7B,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,mBAAmB,EACxB,WAAW,MAAM,KAChB,OAAO,CAAC,aAAa,CAuBvB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,mBAAmB,EACxB,UAAU,MAAM,EAChB,QAAQ,MAAM,KACb,OAAO,CAAC,IAAI,CAcd,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,KAAK,mBAAmB,EACxB,UAAU,MAAM,KACf,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAUrD,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,GACnC,KAAK,mBAAmB,EACxB,UAAU,MAAM,EAChB,gCAAiD,WAAgB,KAChE,OAAO,CAAC,2BAA2B,CAgBrC,CAAA"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.waitForPaymentCompletion = exports.getPaymentIntentStatus = exports.watchPaymentTransaction = exports.createPaymentIntent = exports.getPaymentContractInfo = exports.getStoragePrice = void 0;
|
|
13
|
+
const auto_utils_1 = require("@autonomys/auto-utils");
|
|
14
|
+
const TERMINAL_STATUSES = [
|
|
15
|
+
'COMPLETED',
|
|
16
|
+
'EXPIRED',
|
|
17
|
+
'FAILED',
|
|
18
|
+
'OVER_CAP',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Returns the current live storage price without creating a price-locked intent.
|
|
22
|
+
*
|
|
23
|
+
* This is a public endpoint — no API key is required.
|
|
24
|
+
* Use it to show a cost estimate to users before they commit to a payment.
|
|
25
|
+
*
|
|
26
|
+
* @returns `shannonsPerByte` — the raw on-chain price, and `ai3PerGb` — a
|
|
27
|
+
* pre-computed display value in AI3 per gigabyte.
|
|
28
|
+
*/
|
|
29
|
+
const getStoragePrice = (api) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
const response = yield api.sendAPIRequest('/intents/price', { method: 'GET' });
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(`Failed to fetch storage price: ${response.status} ${response.statusText}`);
|
|
33
|
+
}
|
|
34
|
+
const { price, pricePerGB } = yield response.json();
|
|
35
|
+
return { shannonsPerByte: price, ai3PerGb: pricePerGB };
|
|
36
|
+
});
|
|
37
|
+
exports.getStoragePrice = getStoragePrice;
|
|
38
|
+
/**
|
|
39
|
+
* Fetches the EVM chain ID, contract address, and ABI needed to call `payIntent(bytes32)`.
|
|
40
|
+
*
|
|
41
|
+
* This is a public endpoint — no API key is required. The result is stable
|
|
42
|
+
* per network and safe to cache for the lifetime of the application.
|
|
43
|
+
*/
|
|
44
|
+
const getPaymentContractInfo = (api) => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
const response = yield api.sendAPIRequest('/intents/contract', { method: 'GET' });
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error(`Failed to fetch payment contract info: ${response.status} ${response.statusText}`);
|
|
48
|
+
}
|
|
49
|
+
return response.json();
|
|
50
|
+
});
|
|
51
|
+
exports.getPaymentContractInfo = getPaymentContractInfo;
|
|
52
|
+
/**
|
|
53
|
+
* Creates a price-locked payment intent for a given upload size in bytes.
|
|
54
|
+
*
|
|
55
|
+
* The intent locks the current `shannonsPerByte` price for 10 minutes.
|
|
56
|
+
* The returned `ai3AmountWei` is the exact value to pass as `msg.value`
|
|
57
|
+
* when calling `payIntent(intentId)` on the Credits Receiver contract.
|
|
58
|
+
*
|
|
59
|
+
* Note: `sizeBytes` is **not** sent to the Auto Drive API. The POST `/intents`
|
|
60
|
+
* endpoint accepts no request body — it returns the current `shannonsPerByte`
|
|
61
|
+
* rate. The SDK multiplies that rate by `sizeBytes` to produce `ai3AmountWei`,
|
|
62
|
+
* saving the caller from doing the BigInt arithmetic themselves.
|
|
63
|
+
*
|
|
64
|
+
* Flow:
|
|
65
|
+
* 1. Call `createPaymentIntent(api, sizeBytes)` — locks the price
|
|
66
|
+
* 2. Send `intent.ai3AmountWei` to `intent.contractAddress` via `payIntent(intent.intentId)`
|
|
67
|
+
* 3. Call `watchPaymentTransaction(api, intent.intentId, txHash)` — submit the tx hash
|
|
68
|
+
* 4. Call `waitForPaymentCompletion(api, intent.intentId)` — poll until COMPLETED
|
|
69
|
+
*/
|
|
70
|
+
const createPaymentIntent = (api, sizeBytes) => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
const [contractInfo, intentRes] = yield Promise.all([
|
|
72
|
+
(0, exports.getPaymentContractInfo)(api),
|
|
73
|
+
api.sendAPIRequest('/intents', { method: 'POST' }),
|
|
74
|
+
]);
|
|
75
|
+
if (!intentRes.ok) {
|
|
76
|
+
const body = yield intentRes.text();
|
|
77
|
+
throw new Error(`Failed to create payment intent: ${intentRes.status} ${body}`);
|
|
78
|
+
}
|
|
79
|
+
const intent = yield intentRes.json();
|
|
80
|
+
const shannonsPerByte = BigInt(intent.shannonsPerByte);
|
|
81
|
+
const ai3AmountWei = shannonsPerByte * BigInt(sizeBytes);
|
|
82
|
+
return {
|
|
83
|
+
intentId: intent.id,
|
|
84
|
+
ai3AmountWei: ai3AmountWei.toString(),
|
|
85
|
+
ai3Amount: (0, auto_utils_1.shannonsToAi3)(ai3AmountWei),
|
|
86
|
+
contractAddress: contractInfo.contractAddress,
|
|
87
|
+
shannonsPerByte: intent.shannonsPerByte,
|
|
88
|
+
expiresAt: intent.expiresAt,
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
exports.createPaymentIntent = createPaymentIntent;
|
|
92
|
+
/**
|
|
93
|
+
* Notifies Auto Drive that an on-chain transaction has been submitted for a payment intent.
|
|
94
|
+
*
|
|
95
|
+
* Auto Drive will watch the transaction on-chain and automatically apply storage
|
|
96
|
+
* credits to your account once the transaction is confirmed.
|
|
97
|
+
*/
|
|
98
|
+
const watchPaymentTransaction = (api, intentId, txHash) => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
|
+
const response = yield api.sendAPIRequest(`/intents/${intentId}/watch`, {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
headers: new Headers({ 'Content-Type': 'application/json' }),
|
|
102
|
+
}, JSON.stringify({ txHash }));
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const body = yield response.text();
|
|
105
|
+
throw new Error(`Failed to watch payment transaction: ${response.status} ${body}`);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
exports.watchPaymentTransaction = watchPaymentTransaction;
|
|
109
|
+
/**
|
|
110
|
+
* Returns the current status of a payment intent.
|
|
111
|
+
*
|
|
112
|
+
* Possible statuses: PENDING | CONFIRMED | COMPLETED | EXPIRED | FAILED | OVER_CAP
|
|
113
|
+
*/
|
|
114
|
+
const getPaymentIntentStatus = (api, intentId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
115
|
+
const response = yield api.sendAPIRequest(`/intents/${intentId}`, { method: 'GET' });
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
const body = yield response.text();
|
|
118
|
+
throw new Error(`Failed to get payment intent status: ${response.status} ${body}`);
|
|
119
|
+
}
|
|
120
|
+
const data = yield response.json();
|
|
121
|
+
return { id: data.id, status: data.status.toUpperCase() };
|
|
122
|
+
});
|
|
123
|
+
exports.getPaymentIntentStatus = getPaymentIntentStatus;
|
|
124
|
+
/**
|
|
125
|
+
* Polls a payment intent at regular intervals until it reaches a terminal state.
|
|
126
|
+
*
|
|
127
|
+
* Returns the terminal status: COMPLETED | EXPIRED | FAILED | OVER_CAP.
|
|
128
|
+
* Throws if the timeout is exceeded before a terminal state is reached.
|
|
129
|
+
*
|
|
130
|
+
* @param api - An authenticated AutoDriveApiHandler
|
|
131
|
+
* @param intentId - The intent ID returned by `createPaymentIntent`
|
|
132
|
+
* @param options - Optional poll interval and timeout (defaults: 3 s / 5 min)
|
|
133
|
+
*/
|
|
134
|
+
const waitForPaymentCompletion = (api_1, intentId_1, ...args_1) => __awaiter(void 0, [api_1, intentId_1, ...args_1], void 0, function* (api, intentId, { pollIntervalMs = 3000, timeoutMs = 300000 } = {}) {
|
|
135
|
+
const deadline = Date.now() + timeoutMs;
|
|
136
|
+
while (Date.now() < deadline) {
|
|
137
|
+
const { status } = yield (0, exports.getPaymentIntentStatus)(api, intentId);
|
|
138
|
+
if (TERMINAL_STATUSES.includes(status)) {
|
|
139
|
+
return status;
|
|
140
|
+
}
|
|
141
|
+
yield new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
142
|
+
}
|
|
143
|
+
throw new Error(`Timed out waiting for payment intent "${intentId}" to complete after ${timeoutMs}ms`);
|
|
144
|
+
});
|
|
145
|
+
exports.waitForPaymentCompletion = waitForPaymentCompletion;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/models/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA"}
|
package/dist/api/models/index.js
CHANGED
|
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./objects"), exports);
|
|
18
|
+
__exportStar(require("./payment"), exports);
|
|
18
19
|
__exportStar(require("./uploads"), exports);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Current storage price, returned by `getStoragePrice`.
|
|
3
|
+
* This is a live read of the on-chain byte fee — no API key required.
|
|
4
|
+
* Use it to display a cost estimate before creating a price-locked intent.
|
|
5
|
+
*/
|
|
6
|
+
export type StoragePrice = {
|
|
7
|
+
/** Current price per byte in shannons */
|
|
8
|
+
shannonsPerByte: number;
|
|
9
|
+
/** Pre-computed display price in AI3 per gigabyte */
|
|
10
|
+
ai3PerGb: number;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Information about the EVM smart contract used to pay for storage intents.
|
|
14
|
+
* Returned by the public `/intents/contract` endpoint — no API key required.
|
|
15
|
+
*/
|
|
16
|
+
export type PaymentContractInfo = {
|
|
17
|
+
/** Auto EVM chain ID (870 for mainnet) */
|
|
18
|
+
chainId: number;
|
|
19
|
+
/** Address of the Credits Receiver contract */
|
|
20
|
+
contractAddress: string;
|
|
21
|
+
/** ABI fragment for the payIntent(bytes32) function */
|
|
22
|
+
payIntentAbi: readonly unknown[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* A price-locked payment intent returned by `createPaymentIntent`.
|
|
26
|
+
* The intent expires after 10 minutes. Send exactly `ai3AmountWei` to
|
|
27
|
+
* the Credits Receiver contract via `payIntent(intentId)`.
|
|
28
|
+
*/
|
|
29
|
+
export type PaymentIntent = {
|
|
30
|
+
/** Unique intent identifier — pass as the `bytes32` arg to `payIntent()` */
|
|
31
|
+
intentId: string;
|
|
32
|
+
/** Amount to send, in shannons/wei, as a decimal string (safe for BigInt conversion) */
|
|
33
|
+
ai3AmountWei: string;
|
|
34
|
+
/** Human-readable amount, e.g. "0.00123" */
|
|
35
|
+
ai3Amount: string;
|
|
36
|
+
/** The Credits Receiver contract address (convenience copy from PaymentContractInfo) */
|
|
37
|
+
contractAddress: string;
|
|
38
|
+
/** Current price per byte in shannons */
|
|
39
|
+
shannonsPerByte: string;
|
|
40
|
+
/** ISO 8601 timestamp when this intent expires */
|
|
41
|
+
expiresAt: string;
|
|
42
|
+
};
|
|
43
|
+
/** All possible states a payment intent can be in */
|
|
44
|
+
export type PaymentIntentStatus = 'PENDING' | 'CONFIRMED' | 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP';
|
|
45
|
+
/** States that indicate the intent lifecycle has ended */
|
|
46
|
+
export type PaymentIntentTerminalStatus = Extract<PaymentIntentStatus, 'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'>;
|
|
47
|
+
/** Options for `waitForPaymentCompletion` */
|
|
48
|
+
export type PollOptions = {
|
|
49
|
+
/** How often to check intent status. Default: 3 000 ms */
|
|
50
|
+
pollIntervalMs?: number;
|
|
51
|
+
/** Maximum time to wait before throwing. Default: 300 000 ms (5 minutes) */
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=payment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment.d.ts","sourceRoot":"","sources":["../../../src/api/models/payment.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAA;IACvB,uDAAuD;IACvD,YAAY,EAAE,SAAS,OAAO,EAAE,CAAA;CACjC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAA;IAChB,wFAAwF;IACxF,YAAY,EAAE,MAAM,CAAA;IACpB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAA;IACjB,wFAAwF;IACxF,eAAe,EAAE,MAAM,CAAA;IACvB,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,qDAAqD;AACrD,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,WAAW,GACX,WAAW,GACX,SAAS,GACT,QAAQ,GACR,UAAU,CAAA;AAEd,0DAA0D;AAC1D,MAAM,MAAM,2BAA2B,GAAG,OAAO,CAC/C,mBAAmB,EACnB,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAChD,CAAA;AAED,6CAA6C;AAC7C,MAAM,MAAM,WAAW,GAAG;IACxB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA"}
|
package/dist/api/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ObjectSummary } from './models';
|
|
|
2
2
|
import { AsyncDownload } from './models/asyncDownloads';
|
|
3
3
|
import { PaginatedResult } from './models/common';
|
|
4
4
|
import { GenericFile, GenericFileWithinFolder } from './models/file';
|
|
5
|
+
import { PaymentContractInfo, PaymentIntent, PaymentIntentStatus, PaymentIntentTerminalStatus, PollOptions, StoragePrice } from './models/payment';
|
|
5
6
|
import { SubscriptionInfo, UserInfo } from './models/user';
|
|
6
7
|
import { AutoDriveNetwork } from './networks';
|
|
7
8
|
export interface AutoDriveApi extends AutoDriveApiHandler {
|
|
@@ -137,6 +138,68 @@ export interface AutoDriveApi extends AutoDriveApiHandler {
|
|
|
137
138
|
* @returns {Promise<SubscriptionInfo>} A promise that resolves to the subscription info.
|
|
138
139
|
*/
|
|
139
140
|
getSubscriptionInfo: () => Promise<SubscriptionInfo>;
|
|
141
|
+
/**
|
|
142
|
+
* Returns the current live storage price without creating a price-locked intent.
|
|
143
|
+
*
|
|
144
|
+
* This is a public endpoint — no API key required.
|
|
145
|
+
* Use it to display a cost estimate to users before they commit to a payment.
|
|
146
|
+
*
|
|
147
|
+
* @returns {Promise<StoragePrice>} Current price per byte and a pre-computed AI3/GB display value.
|
|
148
|
+
*/
|
|
149
|
+
getStoragePrice: () => Promise<StoragePrice>;
|
|
150
|
+
/**
|
|
151
|
+
* Fetches the EVM chain ID, contract address, and ABI for the Credits Receiver contract.
|
|
152
|
+
*
|
|
153
|
+
* This is a public endpoint — no API key required. The result is stable per network
|
|
154
|
+
* and safe to cache for the lifetime of the application.
|
|
155
|
+
*
|
|
156
|
+
* @returns {Promise<PaymentContractInfo>} Chain details needed to call `payIntent(bytes32)`.
|
|
157
|
+
*/
|
|
158
|
+
getPaymentContractInfo: () => Promise<PaymentContractInfo>;
|
|
159
|
+
/**
|
|
160
|
+
* Creates a price-locked payment intent for a given upload size.
|
|
161
|
+
*
|
|
162
|
+
* The intent locks the current storage price for 10 minutes. Send exactly
|
|
163
|
+
* `intent.ai3AmountWei` to the Credits Receiver contract via `payIntent(intent.intentId)`,
|
|
164
|
+
* then call `watchPaymentTransaction` to notify Auto Drive.
|
|
165
|
+
*
|
|
166
|
+
* @param sizeBytes - Upload size in bytes. Used **by the SDK** to compute
|
|
167
|
+
* `ai3AmountWei = shannonsPerByte × sizeBytes`. It is not sent to the server —
|
|
168
|
+
* the POST `/intents` endpoint accepts no request body.
|
|
169
|
+
* @returns {Promise<PaymentIntent>} Intent details including amount, contract address, and expiry.
|
|
170
|
+
*/
|
|
171
|
+
createPaymentIntent: (sizeBytes: number) => Promise<PaymentIntent>;
|
|
172
|
+
/**
|
|
173
|
+
* Notifies Auto Drive that an on-chain transaction has been submitted for a payment intent.
|
|
174
|
+
*
|
|
175
|
+
* Auto Drive will watch the transaction and automatically apply storage credits
|
|
176
|
+
* to your account once confirmed on-chain.
|
|
177
|
+
*
|
|
178
|
+
* @param intentId - The intent ID from `createPaymentIntent`.
|
|
179
|
+
* @param txHash - The on-chain transaction hash.
|
|
180
|
+
*/
|
|
181
|
+
watchPaymentTransaction: (intentId: string, txHash: string) => Promise<void>;
|
|
182
|
+
/**
|
|
183
|
+
* Returns the current status of a payment intent.
|
|
184
|
+
*
|
|
185
|
+
* Possible statuses: PENDING | CONFIRMED | COMPLETED | EXPIRED | FAILED | OVER_CAP
|
|
186
|
+
*
|
|
187
|
+
* @param intentId - The intent ID from `createPaymentIntent`.
|
|
188
|
+
*/
|
|
189
|
+
getPaymentIntentStatus: (intentId: string) => Promise<{
|
|
190
|
+
id: string;
|
|
191
|
+
status: PaymentIntentStatus;
|
|
192
|
+
}>;
|
|
193
|
+
/**
|
|
194
|
+
* Polls a payment intent until it reaches a terminal state.
|
|
195
|
+
*
|
|
196
|
+
* Returns the terminal status: COMPLETED | EXPIRED | FAILED | OVER_CAP.
|
|
197
|
+
* Throws if the timeout is exceeded before a terminal state is reached.
|
|
198
|
+
*
|
|
199
|
+
* @param intentId - The intent ID from `createPaymentIntent`.
|
|
200
|
+
* @param options - Optional poll interval and timeout (defaults: 3 s / 5 min).
|
|
201
|
+
*/
|
|
202
|
+
waitForPaymentCompletion: (intentId: string, options?: PollOptions) => Promise<PaymentIntentTerminalStatus>;
|
|
140
203
|
/**
|
|
141
204
|
* Publishes an object by sending a request to the server.
|
|
142
205
|
*
|
package/dist/api/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AACpE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,WAAW,YAAa,SAAQ,mBAAmB;IACvD;;;;OAIG;IACH,EAAE,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAA;IAE3B;;;;;OAKG;IACH,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAE/C;;;;;;;;;;;;;;;;OAgBG;IACH,mBAAmB,EAAE,CACnB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,iBAAiB,EAC1B,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,EAAE,CACV,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,iBAAiB,EAC1B,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB;;;;;;;;;;OAUG;IACH,oBAAoB,EAAE,CACpB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB;;;;;;;;;;;;;;OAcG;IACH,kBAAkB,EAAE,CAClB,MAAM,EAAE,OAAO,EACf,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,CAAC,EAAE,iBAAiB,EAC3B,eAAe,CAAC,EAAE,MAAM,KACrB,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB;;;;;;;;;;;;;;;;OAgBG;IACH,qBAAqB,EAAE,CACrB,QAAQ,EAAE,QAAQ,GAAG,IAAI,EAAE,EAC3B,OAAO,EAAE;QACP,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;KACxC,KACE,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB;;;;;;;;OAQG;IACH,4BAA4B,EAAE,CAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,uBAAuB,EAC7B,eAAe,CAAC,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC,KAC5C,OAAO,CAAC,MAAM,CAAC,CAAA;IACpB;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;IAChF;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtE;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrappers.d.ts","sourceRoot":"","sources":["../../src/api/wrappers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wrappers.d.ts","sourceRoot":"","sources":["../../src/api/wrappers.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAqB,MAAM,SAAS,CAAA;AA6B9E,eAAO,MAAM,kBAAkB,GAAI,KAAK,mBAAmB,KAAG,YAkX7D,CAAA"}
|
package/dist/api/wrappers.js
CHANGED
|
@@ -246,6 +246,12 @@ const createApiInterface = (api) => {
|
|
|
246
246
|
const me = yield index_1.apiCalls.getMe(api);
|
|
247
247
|
return me.subscription;
|
|
248
248
|
});
|
|
249
|
+
const getStoragePrice = () => index_1.apiCalls.getStoragePrice(api);
|
|
250
|
+
const getPaymentContractInfo = () => index_1.apiCalls.getPaymentContractInfo(api);
|
|
251
|
+
const createPaymentIntent = (sizeBytes) => index_1.apiCalls.createPaymentIntent(api, sizeBytes);
|
|
252
|
+
const watchPaymentTransaction = (intentId, txHash) => index_1.apiCalls.watchPaymentTransaction(api, intentId, txHash);
|
|
253
|
+
const getPaymentIntentStatus = (intentId) => index_1.apiCalls.getPaymentIntentStatus(api, intentId);
|
|
254
|
+
const waitForPaymentCompletion = (intentId, options) => index_1.apiCalls.waitForPaymentCompletion(api, intentId, options);
|
|
249
255
|
const publishObject = (cid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
250
256
|
const result = yield index_1.apiCalls.publishObject(api, { cid });
|
|
251
257
|
return (0, download_1.publicDownloadUrl)(api, result.result);
|
|
@@ -280,6 +286,12 @@ const createApiInterface = (api) => {
|
|
|
280
286
|
downloadFile,
|
|
281
287
|
getPendingCredits,
|
|
282
288
|
getSubscriptionInfo,
|
|
289
|
+
getStoragePrice,
|
|
290
|
+
getPaymentContractInfo,
|
|
291
|
+
createPaymentIntent,
|
|
292
|
+
watchPaymentTransaction,
|
|
293
|
+
getPaymentIntentStatus,
|
|
294
|
+
waitForPaymentCompletion,
|
|
283
295
|
publishObject,
|
|
284
296
|
getMyFiles,
|
|
285
297
|
searchByNameOrCIDInMyFiles,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autonomys/auto-drive",
|
|
3
3
|
"packageManager": "yarn@4.7.0",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.10",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"typescript": "^5.8.3"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@autonomys/asynchronous": "^1.6.
|
|
46
|
-
"@autonomys/auto-dag-data": "^1.6.
|
|
47
|
-
"@autonomys/auto-utils": "^1.6.
|
|
45
|
+
"@autonomys/asynchronous": "^1.6.10",
|
|
46
|
+
"@autonomys/auto-dag-data": "^1.6.10",
|
|
47
|
+
"@autonomys/auto-utils": "^1.6.10",
|
|
48
48
|
"blockstore-core": "^5.0.2",
|
|
49
49
|
"jszip": "^3.10.1",
|
|
50
50
|
"mime-types": "^3.0.2",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"stream": "^0.0.3",
|
|
53
53
|
"zod": "^3.24.2"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "ff14841a080170350d57df19327f484c8b95f874"
|
|
56
56
|
}
|
package/src/api/calls/index.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import * as downloadCalls from './download'
|
|
2
|
+
import * as paymentCalls from './payment'
|
|
2
3
|
import * as readCalls from './read'
|
|
3
4
|
import * as uploadCalls from './upload'
|
|
4
5
|
import * as writeCalls from './write'
|
|
5
6
|
|
|
6
7
|
export const apiCalls = {
|
|
7
8
|
...downloadCalls,
|
|
9
|
+
...paymentCalls,
|
|
8
10
|
...readCalls,
|
|
9
11
|
...uploadCalls,
|
|
10
12
|
...writeCalls,
|
|
11
13
|
}
|
|
14
|
+
|
|
15
|
+
// Re-export payment utilities as named exports so callers can use them
|
|
16
|
+
// as standalone functions without going through the apiCalls object.
|
|
17
|
+
export {
|
|
18
|
+
getStoragePrice,
|
|
19
|
+
getPaymentContractInfo,
|
|
20
|
+
createPaymentIntent,
|
|
21
|
+
watchPaymentTransaction,
|
|
22
|
+
getPaymentIntentStatus,
|
|
23
|
+
waitForPaymentCompletion,
|
|
24
|
+
} from './payment'
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { shannonsToAi3 } from '@autonomys/auto-utils'
|
|
2
|
+
import {
|
|
3
|
+
PaymentContractInfo,
|
|
4
|
+
PaymentIntent,
|
|
5
|
+
PaymentIntentStatus,
|
|
6
|
+
PaymentIntentTerminalStatus,
|
|
7
|
+
PollOptions,
|
|
8
|
+
StoragePrice,
|
|
9
|
+
} from '../models/payment'
|
|
10
|
+
import { AutoDriveApiHandler } from '../types'
|
|
11
|
+
|
|
12
|
+
const TERMINAL_STATUSES: PaymentIntentTerminalStatus[] = [
|
|
13
|
+
'COMPLETED',
|
|
14
|
+
'EXPIRED',
|
|
15
|
+
'FAILED',
|
|
16
|
+
'OVER_CAP',
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns the current live storage price without creating a price-locked intent.
|
|
21
|
+
*
|
|
22
|
+
* This is a public endpoint — no API key is required.
|
|
23
|
+
* Use it to show a cost estimate to users before they commit to a payment.
|
|
24
|
+
*
|
|
25
|
+
* @returns `shannonsPerByte` — the raw on-chain price, and `ai3PerGb` — a
|
|
26
|
+
* pre-computed display value in AI3 per gigabyte.
|
|
27
|
+
*/
|
|
28
|
+
export const getStoragePrice = async (api: AutoDriveApiHandler): Promise<StoragePrice> => {
|
|
29
|
+
const response = await api.sendAPIRequest('/intents/price', { method: 'GET' })
|
|
30
|
+
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new Error(`Failed to fetch storage price: ${response.status} ${response.statusText}`)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { price, pricePerGB } = await response.json()
|
|
36
|
+
return { shannonsPerByte: price, ai3PerGb: pricePerGB }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Fetches the EVM chain ID, contract address, and ABI needed to call `payIntent(bytes32)`.
|
|
41
|
+
*
|
|
42
|
+
* This is a public endpoint — no API key is required. The result is stable
|
|
43
|
+
* per network and safe to cache for the lifetime of the application.
|
|
44
|
+
*/
|
|
45
|
+
export const getPaymentContractInfo = async (
|
|
46
|
+
api: AutoDriveApiHandler,
|
|
47
|
+
): Promise<PaymentContractInfo> => {
|
|
48
|
+
const response = await api.sendAPIRequest('/intents/contract', { method: 'GET' })
|
|
49
|
+
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw new Error(`Failed to fetch payment contract info: ${response.status} ${response.statusText}`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return response.json()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Creates a price-locked payment intent for a given upload size in bytes.
|
|
59
|
+
*
|
|
60
|
+
* The intent locks the current `shannonsPerByte` price for 10 minutes.
|
|
61
|
+
* The returned `ai3AmountWei` is the exact value to pass as `msg.value`
|
|
62
|
+
* when calling `payIntent(intentId)` on the Credits Receiver contract.
|
|
63
|
+
*
|
|
64
|
+
* Note: `sizeBytes` is **not** sent to the Auto Drive API. The POST `/intents`
|
|
65
|
+
* endpoint accepts no request body — it returns the current `shannonsPerByte`
|
|
66
|
+
* rate. The SDK multiplies that rate by `sizeBytes` to produce `ai3AmountWei`,
|
|
67
|
+
* saving the caller from doing the BigInt arithmetic themselves.
|
|
68
|
+
*
|
|
69
|
+
* Flow:
|
|
70
|
+
* 1. Call `createPaymentIntent(api, sizeBytes)` — locks the price
|
|
71
|
+
* 2. Send `intent.ai3AmountWei` to `intent.contractAddress` via `payIntent(intent.intentId)`
|
|
72
|
+
* 3. Call `watchPaymentTransaction(api, intent.intentId, txHash)` — submit the tx hash
|
|
73
|
+
* 4. Call `waitForPaymentCompletion(api, intent.intentId)` — poll until COMPLETED
|
|
74
|
+
*/
|
|
75
|
+
export const createPaymentIntent = async (
|
|
76
|
+
api: AutoDriveApiHandler,
|
|
77
|
+
sizeBytes: number,
|
|
78
|
+
): Promise<PaymentIntent> => {
|
|
79
|
+
const [contractInfo, intentRes] = await Promise.all([
|
|
80
|
+
getPaymentContractInfo(api),
|
|
81
|
+
api.sendAPIRequest('/intents', { method: 'POST' }),
|
|
82
|
+
])
|
|
83
|
+
|
|
84
|
+
if (!intentRes.ok) {
|
|
85
|
+
const body = await intentRes.text()
|
|
86
|
+
throw new Error(`Failed to create payment intent: ${intentRes.status} ${body}`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const intent = await intentRes.json()
|
|
90
|
+
const shannonsPerByte = BigInt(intent.shannonsPerByte)
|
|
91
|
+
const ai3AmountWei = shannonsPerByte * BigInt(sizeBytes)
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
intentId: intent.id,
|
|
95
|
+
ai3AmountWei: ai3AmountWei.toString(),
|
|
96
|
+
ai3Amount: shannonsToAi3(ai3AmountWei),
|
|
97
|
+
contractAddress: contractInfo.contractAddress,
|
|
98
|
+
shannonsPerByte: intent.shannonsPerByte,
|
|
99
|
+
expiresAt: intent.expiresAt,
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Notifies Auto Drive that an on-chain transaction has been submitted for a payment intent.
|
|
105
|
+
*
|
|
106
|
+
* Auto Drive will watch the transaction on-chain and automatically apply storage
|
|
107
|
+
* credits to your account once the transaction is confirmed.
|
|
108
|
+
*/
|
|
109
|
+
export const watchPaymentTransaction = async (
|
|
110
|
+
api: AutoDriveApiHandler,
|
|
111
|
+
intentId: string,
|
|
112
|
+
txHash: string,
|
|
113
|
+
): Promise<void> => {
|
|
114
|
+
const response = await api.sendAPIRequest(
|
|
115
|
+
`/intents/${intentId}/watch`,
|
|
116
|
+
{
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: new Headers({ 'Content-Type': 'application/json' }),
|
|
119
|
+
},
|
|
120
|
+
JSON.stringify({ txHash }),
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const body = await response.text()
|
|
125
|
+
throw new Error(`Failed to watch payment transaction: ${response.status} ${body}`)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Returns the current status of a payment intent.
|
|
131
|
+
*
|
|
132
|
+
* Possible statuses: PENDING | CONFIRMED | COMPLETED | EXPIRED | FAILED | OVER_CAP
|
|
133
|
+
*/
|
|
134
|
+
export const getPaymentIntentStatus = async (
|
|
135
|
+
api: AutoDriveApiHandler,
|
|
136
|
+
intentId: string,
|
|
137
|
+
): Promise<{ id: string; status: PaymentIntentStatus }> => {
|
|
138
|
+
const response = await api.sendAPIRequest(`/intents/${intentId}`, { method: 'GET' })
|
|
139
|
+
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
const body = await response.text()
|
|
142
|
+
throw new Error(`Failed to get payment intent status: ${response.status} ${body}`)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const data = await response.json()
|
|
146
|
+
return { id: data.id, status: data.status.toUpperCase() as PaymentIntentStatus }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Polls a payment intent at regular intervals until it reaches a terminal state.
|
|
151
|
+
*
|
|
152
|
+
* Returns the terminal status: COMPLETED | EXPIRED | FAILED | OVER_CAP.
|
|
153
|
+
* Throws if the timeout is exceeded before a terminal state is reached.
|
|
154
|
+
*
|
|
155
|
+
* @param api - An authenticated AutoDriveApiHandler
|
|
156
|
+
* @param intentId - The intent ID returned by `createPaymentIntent`
|
|
157
|
+
* @param options - Optional poll interval and timeout (defaults: 3 s / 5 min)
|
|
158
|
+
*/
|
|
159
|
+
export const waitForPaymentCompletion = async (
|
|
160
|
+
api: AutoDriveApiHandler,
|
|
161
|
+
intentId: string,
|
|
162
|
+
{ pollIntervalMs = 3_000, timeoutMs = 300_000 }: PollOptions = {},
|
|
163
|
+
): Promise<PaymentIntentTerminalStatus> => {
|
|
164
|
+
const deadline = Date.now() + timeoutMs
|
|
165
|
+
|
|
166
|
+
while (Date.now() < deadline) {
|
|
167
|
+
const { status } = await getPaymentIntentStatus(api, intentId)
|
|
168
|
+
|
|
169
|
+
if ((TERMINAL_STATUSES as string[]).includes(status)) {
|
|
170
|
+
return status as PaymentIntentTerminalStatus
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
throw new Error(
|
|
177
|
+
`Timed out waiting for payment intent "${intentId}" to complete after ${timeoutMs}ms`,
|
|
178
|
+
)
|
|
179
|
+
}
|
package/src/api/models/index.ts
CHANGED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Current storage price, returned by `getStoragePrice`.
|
|
3
|
+
* This is a live read of the on-chain byte fee — no API key required.
|
|
4
|
+
* Use it to display a cost estimate before creating a price-locked intent.
|
|
5
|
+
*/
|
|
6
|
+
export type StoragePrice = {
|
|
7
|
+
/** Current price per byte in shannons */
|
|
8
|
+
shannonsPerByte: number
|
|
9
|
+
/** Pre-computed display price in AI3 per gigabyte */
|
|
10
|
+
ai3PerGb: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Information about the EVM smart contract used to pay for storage intents.
|
|
15
|
+
* Returned by the public `/intents/contract` endpoint — no API key required.
|
|
16
|
+
*/
|
|
17
|
+
export type PaymentContractInfo = {
|
|
18
|
+
/** Auto EVM chain ID (870 for mainnet) */
|
|
19
|
+
chainId: number
|
|
20
|
+
/** Address of the Credits Receiver contract */
|
|
21
|
+
contractAddress: string
|
|
22
|
+
/** ABI fragment for the payIntent(bytes32) function */
|
|
23
|
+
payIntentAbi: readonly unknown[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A price-locked payment intent returned by `createPaymentIntent`.
|
|
28
|
+
* The intent expires after 10 minutes. Send exactly `ai3AmountWei` to
|
|
29
|
+
* the Credits Receiver contract via `payIntent(intentId)`.
|
|
30
|
+
*/
|
|
31
|
+
export type PaymentIntent = {
|
|
32
|
+
/** Unique intent identifier — pass as the `bytes32` arg to `payIntent()` */
|
|
33
|
+
intentId: string
|
|
34
|
+
/** Amount to send, in shannons/wei, as a decimal string (safe for BigInt conversion) */
|
|
35
|
+
ai3AmountWei: string
|
|
36
|
+
/** Human-readable amount, e.g. "0.00123" */
|
|
37
|
+
ai3Amount: string
|
|
38
|
+
/** The Credits Receiver contract address (convenience copy from PaymentContractInfo) */
|
|
39
|
+
contractAddress: string
|
|
40
|
+
/** Current price per byte in shannons */
|
|
41
|
+
shannonsPerByte: string
|
|
42
|
+
/** ISO 8601 timestamp when this intent expires */
|
|
43
|
+
expiresAt: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** All possible states a payment intent can be in */
|
|
47
|
+
export type PaymentIntentStatus =
|
|
48
|
+
| 'PENDING'
|
|
49
|
+
| 'CONFIRMED'
|
|
50
|
+
| 'COMPLETED'
|
|
51
|
+
| 'EXPIRED'
|
|
52
|
+
| 'FAILED'
|
|
53
|
+
| 'OVER_CAP'
|
|
54
|
+
|
|
55
|
+
/** States that indicate the intent lifecycle has ended */
|
|
56
|
+
export type PaymentIntentTerminalStatus = Extract<
|
|
57
|
+
PaymentIntentStatus,
|
|
58
|
+
'COMPLETED' | 'EXPIRED' | 'FAILED' | 'OVER_CAP'
|
|
59
|
+
>
|
|
60
|
+
|
|
61
|
+
/** Options for `waitForPaymentCompletion` */
|
|
62
|
+
export type PollOptions = {
|
|
63
|
+
/** How often to check intent status. Default: 3 000 ms */
|
|
64
|
+
pollIntervalMs?: number
|
|
65
|
+
/** Maximum time to wait before throwing. Default: 300 000 ms (5 minutes) */
|
|
66
|
+
timeoutMs?: number
|
|
67
|
+
}
|
package/src/api/types.ts
CHANGED
|
@@ -2,6 +2,14 @@ import { ObjectSummary } from './models'
|
|
|
2
2
|
import { AsyncDownload } from './models/asyncDownloads'
|
|
3
3
|
import { PaginatedResult } from './models/common'
|
|
4
4
|
import { GenericFile, GenericFileWithinFolder } from './models/file'
|
|
5
|
+
import {
|
|
6
|
+
PaymentContractInfo,
|
|
7
|
+
PaymentIntent,
|
|
8
|
+
PaymentIntentStatus,
|
|
9
|
+
PaymentIntentTerminalStatus,
|
|
10
|
+
PollOptions,
|
|
11
|
+
StoragePrice,
|
|
12
|
+
} from './models/payment'
|
|
5
13
|
import { SubscriptionInfo, UserInfo } from './models/user'
|
|
6
14
|
import { AutoDriveNetwork } from './networks'
|
|
7
15
|
|
|
@@ -163,6 +171,79 @@ export interface AutoDriveApi extends AutoDriveApiHandler {
|
|
|
163
171
|
* @returns {Promise<SubscriptionInfo>} A promise that resolves to the subscription info.
|
|
164
172
|
*/
|
|
165
173
|
getSubscriptionInfo: () => Promise<SubscriptionInfo>
|
|
174
|
+
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Pay with AI3 — credit purchase via on-chain payment intent
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Returns the current live storage price without creating a price-locked intent.
|
|
181
|
+
*
|
|
182
|
+
* This is a public endpoint — no API key required.
|
|
183
|
+
* Use it to display a cost estimate to users before they commit to a payment.
|
|
184
|
+
*
|
|
185
|
+
* @returns {Promise<StoragePrice>} Current price per byte and a pre-computed AI3/GB display value.
|
|
186
|
+
*/
|
|
187
|
+
getStoragePrice: () => Promise<StoragePrice>
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Fetches the EVM chain ID, contract address, and ABI for the Credits Receiver contract.
|
|
191
|
+
*
|
|
192
|
+
* This is a public endpoint — no API key required. The result is stable per network
|
|
193
|
+
* and safe to cache for the lifetime of the application.
|
|
194
|
+
*
|
|
195
|
+
* @returns {Promise<PaymentContractInfo>} Chain details needed to call `payIntent(bytes32)`.
|
|
196
|
+
*/
|
|
197
|
+
getPaymentContractInfo: () => Promise<PaymentContractInfo>
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Creates a price-locked payment intent for a given upload size.
|
|
201
|
+
*
|
|
202
|
+
* The intent locks the current storage price for 10 minutes. Send exactly
|
|
203
|
+
* `intent.ai3AmountWei` to the Credits Receiver contract via `payIntent(intent.intentId)`,
|
|
204
|
+
* then call `watchPaymentTransaction` to notify Auto Drive.
|
|
205
|
+
*
|
|
206
|
+
* @param sizeBytes - Upload size in bytes. Used **by the SDK** to compute
|
|
207
|
+
* `ai3AmountWei = shannonsPerByte × sizeBytes`. It is not sent to the server —
|
|
208
|
+
* the POST `/intents` endpoint accepts no request body.
|
|
209
|
+
* @returns {Promise<PaymentIntent>} Intent details including amount, contract address, and expiry.
|
|
210
|
+
*/
|
|
211
|
+
createPaymentIntent: (sizeBytes: number) => Promise<PaymentIntent>
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Notifies Auto Drive that an on-chain transaction has been submitted for a payment intent.
|
|
215
|
+
*
|
|
216
|
+
* Auto Drive will watch the transaction and automatically apply storage credits
|
|
217
|
+
* to your account once confirmed on-chain.
|
|
218
|
+
*
|
|
219
|
+
* @param intentId - The intent ID from `createPaymentIntent`.
|
|
220
|
+
* @param txHash - The on-chain transaction hash.
|
|
221
|
+
*/
|
|
222
|
+
watchPaymentTransaction: (intentId: string, txHash: string) => Promise<void>
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Returns the current status of a payment intent.
|
|
226
|
+
*
|
|
227
|
+
* Possible statuses: PENDING | CONFIRMED | COMPLETED | EXPIRED | FAILED | OVER_CAP
|
|
228
|
+
*
|
|
229
|
+
* @param intentId - The intent ID from `createPaymentIntent`.
|
|
230
|
+
*/
|
|
231
|
+
getPaymentIntentStatus: (intentId: string) => Promise<{ id: string; status: PaymentIntentStatus }>
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Polls a payment intent until it reaches a terminal state.
|
|
235
|
+
*
|
|
236
|
+
* Returns the terminal status: COMPLETED | EXPIRED | FAILED | OVER_CAP.
|
|
237
|
+
* Throws if the timeout is exceeded before a terminal state is reached.
|
|
238
|
+
*
|
|
239
|
+
* @param intentId - The intent ID from `createPaymentIntent`.
|
|
240
|
+
* @param options - Optional poll interval and timeout (defaults: 3 s / 5 min).
|
|
241
|
+
*/
|
|
242
|
+
waitForPaymentCompletion: (
|
|
243
|
+
intentId: string,
|
|
244
|
+
options?: PollOptions,
|
|
245
|
+
) => Promise<PaymentIntentTerminalStatus>
|
|
246
|
+
|
|
166
247
|
/**
|
|
167
248
|
* Publishes an object by sending a request to the server.
|
|
168
249
|
*
|
package/src/api/wrappers.ts
CHANGED
|
@@ -10,6 +10,7 @@ import mime from 'mime-types'
|
|
|
10
10
|
import { progressToPercentage } from '../utils/misc'
|
|
11
11
|
import { publicDownloadUrl } from './calls/download'
|
|
12
12
|
import { apiCalls } from './calls/index'
|
|
13
|
+
import { PollOptions } from './models/payment'
|
|
13
14
|
import { ObjectSummary, Scope } from './models'
|
|
14
15
|
import { DownloadStatus } from './models/asyncDownloads'
|
|
15
16
|
import { PaginatedResult } from './models/common'
|
|
@@ -320,6 +321,22 @@ export const createApiInterface = (api: AutoDriveApiHandler): AutoDriveApi => {
|
|
|
320
321
|
return me.subscription
|
|
321
322
|
}
|
|
322
323
|
|
|
324
|
+
const getStoragePrice = () => apiCalls.getStoragePrice(api)
|
|
325
|
+
|
|
326
|
+
const getPaymentContractInfo = () => apiCalls.getPaymentContractInfo(api)
|
|
327
|
+
|
|
328
|
+
const createPaymentIntent = (sizeBytes: number) =>
|
|
329
|
+
apiCalls.createPaymentIntent(api, sizeBytes)
|
|
330
|
+
|
|
331
|
+
const watchPaymentTransaction = (intentId: string, txHash: string) =>
|
|
332
|
+
apiCalls.watchPaymentTransaction(api, intentId, txHash)
|
|
333
|
+
|
|
334
|
+
const getPaymentIntentStatus = (intentId: string) =>
|
|
335
|
+
apiCalls.getPaymentIntentStatus(api, intentId)
|
|
336
|
+
|
|
337
|
+
const waitForPaymentCompletion = (intentId: string, options?: PollOptions) =>
|
|
338
|
+
apiCalls.waitForPaymentCompletion(api, intentId, options)
|
|
339
|
+
|
|
323
340
|
const publishObject = async (cid: string): Promise<string> => {
|
|
324
341
|
const result = await apiCalls.publishObject(api, { cid })
|
|
325
342
|
|
|
@@ -372,6 +389,12 @@ export const createApiInterface = (api: AutoDriveApiHandler): AutoDriveApi => {
|
|
|
372
389
|
downloadFile,
|
|
373
390
|
getPendingCredits,
|
|
374
391
|
getSubscriptionInfo,
|
|
392
|
+
getStoragePrice,
|
|
393
|
+
getPaymentContractInfo,
|
|
394
|
+
createPaymentIntent,
|
|
395
|
+
watchPaymentTransaction,
|
|
396
|
+
getPaymentIntentStatus,
|
|
397
|
+
waitForPaymentCompletion,
|
|
375
398
|
publishObject,
|
|
376
399
|
getMyFiles,
|
|
377
400
|
searchByNameOrCIDInMyFiles,
|