@ardrive/turbo-sdk 1.0.0-beta.1 → 1.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +58 -15
  2. package/bundles/web.bundle.min.js +171 -37
  3. package/lib/cjs/common/currency.js +42 -0
  4. package/lib/cjs/common/index.js +1 -0
  5. package/lib/cjs/common/payment.js +43 -9
  6. package/lib/cjs/common/turbo.js +45 -12
  7. package/lib/cjs/common/upload.js +13 -5
  8. package/lib/cjs/node/signer.js +33 -2
  9. package/lib/cjs/utils/readableStream.js +6 -4
  10. package/lib/cjs/web/signer.js +9 -4
  11. package/lib/esm/common/currency.js +27 -0
  12. package/lib/esm/common/index.js +1 -0
  13. package/lib/esm/common/payment.js +42 -8
  14. package/lib/esm/common/turbo.js +46 -13
  15. package/lib/esm/common/upload.js +12 -4
  16. package/lib/esm/node/signer.js +33 -2
  17. package/lib/esm/utils/readableStream.js +6 -4
  18. package/lib/esm/web/signer.js +9 -4
  19. package/lib/types/common/currency.d.ts +43 -0
  20. package/lib/types/common/currency.d.ts.map +1 -0
  21. package/lib/types/common/factory.d.ts +2 -2
  22. package/lib/types/common/factory.d.ts.map +1 -1
  23. package/lib/types/common/index.d.ts +1 -0
  24. package/lib/types/common/index.d.ts.map +1 -1
  25. package/lib/types/common/payment.d.ts +17 -7
  26. package/lib/types/common/payment.d.ts.map +1 -1
  27. package/lib/types/common/turbo.d.ts +32 -9
  28. package/lib/types/common/turbo.d.ts.map +1 -1
  29. package/lib/types/common/upload.d.ts +6 -4
  30. package/lib/types/common/upload.d.ts.map +1 -1
  31. package/lib/types/node/factory.d.ts +2 -2
  32. package/lib/types/node/factory.d.ts.map +1 -1
  33. package/lib/types/node/signer.d.ts +8 -3
  34. package/lib/types/node/signer.d.ts.map +1 -1
  35. package/lib/types/types.d.ts +52 -18
  36. package/lib/types/types.d.ts.map +1 -1
  37. package/lib/types/utils/readableStream.d.ts +2 -1
  38. package/lib/types/utils/readableStream.d.ts.map +1 -1
  39. package/lib/types/web/factory.d.ts +2 -2
  40. package/lib/types/web/factory.d.ts.map +1 -1
  41. package/lib/types/web/signer.d.ts +7 -3
  42. package/lib/types/web/signer.d.ts.map +1 -1
  43. package/package.json +1 -1
@@ -1,30 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TurboAuthenticatedPaymentService = exports.TurboUnauthenticatedPaymentService = void 0;
3
+ exports.TurboAuthenticatedPaymentService = exports.TurboUnauthenticatedPaymentService = exports.defaultPaymentServiceURL = exports.developmentPaymentServiceURL = void 0;
4
4
  const http_js_1 = require("./http.js");
5
+ exports.developmentPaymentServiceURL = 'https://payment.ardrive.dev';
6
+ exports.defaultPaymentServiceURL = 'https://payment.ardrive.io';
5
7
  class TurboUnauthenticatedPaymentService {
6
- constructor({ url = 'https://payment.ardrive.dev', retryConfig, }) {
8
+ constructor({ url = exports.defaultPaymentServiceURL, retryConfig, }) {
7
9
  this.httpService = new http_js_1.TurboHTTPService({
8
10
  url: `${url}/v1`,
9
11
  retryConfig,
10
12
  });
11
13
  }
12
- async getFiatRates() {
14
+ getFiatRates() {
13
15
  return this.httpService.get({
14
16
  endpoint: '/rates',
15
17
  });
16
18
  }
17
- async getFiatToAR({ currency, }) {
19
+ getFiatToAR({ currency, }) {
18
20
  return this.httpService.get({
19
21
  endpoint: `/rates/${currency}`,
20
22
  });
21
23
  }
22
- async getSupportedCountries() {
24
+ getSupportedCountries() {
23
25
  return this.httpService.get({
24
26
  endpoint: '/countries',
25
27
  });
26
28
  }
27
- async getSupportedCurrencies() {
29
+ getSupportedCurrencies() {
28
30
  return this.httpService.get({
29
31
  endpoint: '/currencies',
30
32
  });
@@ -36,16 +38,39 @@ class TurboUnauthenticatedPaymentService {
36
38
  const wincCostsForBytes = await Promise.all(fetchPricePromises);
37
39
  return wincCostsForBytes;
38
40
  }
39
- async getWincForFiat({ amount, currency }) {
41
+ getWincForFiat({ amount, }) {
42
+ const { amount: paymentAmount, type: currencyType } = amount;
40
43
  return this.httpService.get({
41
- endpoint: `/price/${currency}/${amount}`,
44
+ endpoint: `/price/${currencyType}/${paymentAmount}`,
42
45
  });
43
46
  }
47
+ appendPromoCodesToQuery(promoCodes) {
48
+ const promoCodesQuery = promoCodes.join(',');
49
+ return promoCodesQuery ? `?promoCode=${promoCodesQuery}` : '';
50
+ }
51
+ async getCheckout({ amount, owner, promoCodes = [] }, headers) {
52
+ const { amount: paymentAmount, type: currencyType } = amount;
53
+ const endpoint = `/top-up/checkout-session/${owner}/${currencyType}/${paymentAmount}${this.appendPromoCodesToQuery(promoCodes)}`;
54
+ const { adjustments, paymentSession, topUpQuote } = await this.httpService.get({
55
+ endpoint,
56
+ headers,
57
+ });
58
+ return {
59
+ winc: topUpQuote.winstonCreditAmount,
60
+ adjustments,
61
+ url: paymentSession.url,
62
+ paymentAmount: topUpQuote.paymentAmount,
63
+ quotedPaymentAmount: topUpQuote.quotedPaymentAmount,
64
+ };
65
+ }
66
+ createCheckoutSession(params) {
67
+ return this.getCheckout(params);
68
+ }
44
69
  }
45
70
  exports.TurboUnauthenticatedPaymentService = TurboUnauthenticatedPaymentService;
46
71
  // NOTE: to avoid redundancy, we use inheritance here - but generally prefer composition over inheritance
47
72
  class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentService {
48
- constructor({ url = 'https://payment.ardrive.dev', retryConfig, signer, }) {
73
+ constructor({ url = exports.defaultPaymentServiceURL, retryConfig, signer, }) {
49
74
  super({ url, retryConfig });
50
75
  this.signer = signer;
51
76
  }
@@ -59,5 +84,14 @@ class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentServic
59
84
  // 404's don't return a balance, so default to 0
60
85
  return balance.winc ? balance : { winc: '0' };
61
86
  }
87
+ async getWincForFiat({ amount, promoCodes = [], }) {
88
+ return this.httpService.get({
89
+ endpoint: `/price/${amount.type}/${amount.amount}${this.appendPromoCodesToQuery(promoCodes)}`,
90
+ headers: await this.signer.generateSignedRequestHeaders(),
91
+ });
92
+ }
93
+ async createCheckoutSession(params) {
94
+ return this.getCheckout(params, await this.signer.generateSignedRequestHeaders());
95
+ }
62
96
  }
63
97
  exports.TurboAuthenticatedPaymentService = TurboAuthenticatedPaymentService;
@@ -1,8 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TurboAuthenticatedClient = exports.TurboUnauthenticatedClient = void 0;
3
+ exports.TurboAuthenticatedClient = exports.TurboUnauthenticatedClient = exports.defaultTurboConfiguration = exports.developmentTurboConfiguration = void 0;
4
4
  const payment_js_1 = require("./payment.js");
5
5
  const upload_js_1 = require("./upload.js");
6
+ /**
7
+ * Testing configuration.
8
+ */
9
+ exports.developmentTurboConfiguration = {
10
+ paymentServiceConfig: {
11
+ url: payment_js_1.developmentPaymentServiceURL,
12
+ },
13
+ uploadServiceConfig: {
14
+ url: upload_js_1.developmentUploadServiceURL,
15
+ },
16
+ };
17
+ /**
18
+ * Production configuration.
19
+ */
20
+ exports.defaultTurboConfiguration = {
21
+ paymentServiceConfig: {
22
+ url: payment_js_1.defaultPaymentServiceURL,
23
+ },
24
+ uploadServiceConfig: {
25
+ url: upload_js_1.defaultUploadServiceURL,
26
+ },
27
+ };
6
28
  class TurboUnauthenticatedClient {
7
29
  constructor({ uploadService = new upload_js_1.TurboUnauthenticatedUploadService({}), paymentService = new payment_js_1.TurboUnauthenticatedPaymentService({}), }) {
8
30
  this.paymentService = paymentService;
@@ -11,7 +33,7 @@ class TurboUnauthenticatedClient {
11
33
  /**
12
34
  * Returns the supported fiat currency conversion rate for 1AR based on current market prices.
13
35
  */
14
- async getFiatToAR({ currency, }) {
36
+ getFiatToAR({ currency, }) {
15
37
  return this.paymentService.getFiatToAR({ currency });
16
38
  }
17
39
  /**
@@ -20,42 +42,49 @@ class TurboUnauthenticatedClient {
20
42
  * Note: this does not take into account varying adjustments and promotions for different sizes of data. If you want to calculate the total
21
43
  * cost in 'winc' for a given number of bytes, use getUploadCosts.
22
44
  */
23
- async getFiatRates() {
45
+ getFiatRates() {
24
46
  return this.paymentService.getFiatRates();
25
47
  }
26
48
  /**
27
49
  * Returns a comprehensive list of supported countries that can purchase credits through the Turbo Payment Service.
28
50
  */
29
- async getSupportedCountries() {
51
+ getSupportedCountries() {
30
52
  return this.paymentService.getSupportedCountries();
31
53
  }
32
54
  /**
33
55
  * Returns a list of all supported fiat currencies.
34
56
  */
35
- async getSupportedCurrencies() {
57
+ getSupportedCurrencies() {
36
58
  return this.paymentService.getSupportedCurrencies();
37
59
  }
38
60
  /**
39
61
  * Determines the price in 'winc' to upload one data item of a specific size in bytes, including all Turbo cost adjustments and fees.
40
62
  */
41
- async getUploadCosts({ bytes, }) {
63
+ getUploadCosts({ bytes, }) {
42
64
  return this.paymentService.getUploadCosts({ bytes });
43
65
  }
44
66
  /**
45
67
  * Determines the amount of 'winc' that would be returned for a given currency and amount, including all Turbo cost adjustments and fees.
46
68
  */
47
- async getWincForFiat({ amount, currency, }) {
48
- return this.paymentService.getWincForFiat({ amount, currency });
69
+ getWincForFiat(params) {
70
+ return this.paymentService.getWincForFiat(params);
49
71
  }
50
72
  /**
51
73
  * Uploads a signed data item to the Turbo Upload Service.
52
74
  */
53
- async uploadSignedDataItem({ dataItemStreamFactory, signal, }) {
75
+ uploadSignedDataItem({ dataItemStreamFactory, dataItemSizeFactory, signal, }) {
54
76
  return this.uploadService.uploadSignedDataItem({
55
77
  dataItemStreamFactory,
78
+ dataItemSizeFactory,
56
79
  signal,
57
80
  });
58
81
  }
82
+ /**
83
+ * Creates a Turbo Checkout Session for a given amount and currency.
84
+ */
85
+ createCheckoutSession(params) {
86
+ return this.paymentService.createCheckoutSession(params);
87
+ }
59
88
  }
60
89
  exports.TurboUnauthenticatedClient = TurboUnauthenticatedClient;
61
90
  class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
@@ -65,14 +94,18 @@ class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
65
94
  /**
66
95
  * Returns the current balance of the user's wallet in 'winc'.
67
96
  */
68
- async getBalance() {
97
+ getBalance() {
69
98
  return this.paymentService.getBalance();
70
99
  }
71
100
  /**
72
101
  * Signs and uploads raw data to the Turbo Upload Service.
73
102
  */
74
- async uploadFile({ fileStreamFactory, signal, }) {
75
- return this.uploadService.uploadFile({ fileStreamFactory, signal });
103
+ uploadFile({ fileStreamFactory, fileSizeFactory, signal, }) {
104
+ return this.uploadService.uploadFile({
105
+ fileStreamFactory,
106
+ fileSizeFactory,
107
+ signal,
108
+ });
76
109
  }
77
110
  }
78
111
  exports.TurboAuthenticatedClient = TurboAuthenticatedClient;
@@ -1,15 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TurboAuthenticatedUploadService = exports.TurboUnauthenticatedUploadService = void 0;
3
+ exports.TurboAuthenticatedUploadService = exports.TurboUnauthenticatedUploadService = exports.developmentUploadServiceURL = exports.defaultUploadServiceURL = void 0;
4
4
  const http_js_1 = require("./http.js");
5
+ exports.defaultUploadServiceURL = 'https://upload.ardrive.io';
6
+ exports.developmentUploadServiceURL = 'https://upload.ardrive.dev';
5
7
  class TurboUnauthenticatedUploadService {
6
- constructor({ url = 'https://upload.ardrive.dev', retryConfig, }) {
8
+ constructor({ url = exports.defaultUploadServiceURL, retryConfig, }) {
7
9
  this.httpService = new http_js_1.TurboHTTPService({
8
10
  url: `${url}/v1`,
9
11
  retryConfig,
10
12
  });
11
13
  }
12
- async uploadSignedDataItem({ dataItemStreamFactory, signal, }) {
14
+ async uploadSignedDataItem({ dataItemStreamFactory, dataItemSizeFactory, signal, }) {
15
+ const fileSize = dataItemSizeFactory();
13
16
  // TODO: add p-limit constraint or replace with separate upload class
14
17
  return this.httpService.post({
15
18
  endpoint: `/tx`,
@@ -17,6 +20,7 @@ class TurboUnauthenticatedUploadService {
17
20
  data: dataItemStreamFactory(),
18
21
  headers: {
19
22
  'content-type': 'application/octet-stream',
23
+ 'content-length': `${fileSize}`,
20
24
  },
21
25
  });
22
26
  }
@@ -28,10 +32,13 @@ class TurboAuthenticatedUploadService extends TurboUnauthenticatedUploadService
28
32
  super({ url, retryConfig });
29
33
  this.signer = signer;
30
34
  }
31
- async uploadFile({ fileStreamFactory, signal, }) {
32
- const signedDataItem = await this.signer.signDataItem({
35
+ async uploadFile({ fileStreamFactory, fileSizeFactory, signal, }) {
36
+ const { dataItemStreamFactory, dataItemSizeFactory } = await this.signer.signDataItem({
33
37
  fileStreamFactory,
38
+ fileSizeFactory,
34
39
  });
40
+ const signedDataItem = dataItemStreamFactory();
41
+ const fileSize = dataItemSizeFactory();
35
42
  // TODO: add p-limit constraint or replace with separate upload class
36
43
  return this.httpService.post({
37
44
  endpoint: `/tx`,
@@ -39,6 +46,7 @@ class TurboAuthenticatedUploadService extends TurboUnauthenticatedUploadService
39
46
  data: signedDataItem,
40
47
  headers: {
41
48
  'content-type': 'application/octet-stream',
49
+ 'content-length': `${fileSize}`,
42
50
  },
43
51
  });
44
52
  }
@@ -30,10 +30,18 @@ class TurboNodeArweaveSigner {
30
30
  this.privateKey = privateKey;
31
31
  this.signer = new arbundles_1.ArweaveSigner(this.privateKey);
32
32
  }
33
- signDataItem({ fileStreamFactory, }) {
33
+ async signDataItem({ fileStreamFactory, fileSizeFactory, }) {
34
34
  // TODO: replace with our own signer implementation
35
35
  const [stream1, stream2] = [fileStreamFactory(), fileStreamFactory()];
36
- return (0, arbundles_1.streamSigner)(stream1, stream2, this.signer);
36
+ const signedDataItem = await (0, arbundles_1.streamSigner)(stream1, stream2, this.signer);
37
+ // TODO: support target, anchor, and tags
38
+ const signedDataItemSize = this.calculateSignedDataHeadersSize({
39
+ dataSize: fileSizeFactory(),
40
+ });
41
+ return {
42
+ dataItemStreamFactory: () => signedDataItem,
43
+ dataItemSizeFactory: () => signedDataItemSize,
44
+ };
37
45
  }
38
46
  // NOTE: this might be better in a parent class or elsewhere - easy enough to leave in here now and does require specific environment version of crypto
39
47
  async generateSignedRequestHeaders() {
@@ -46,5 +54,28 @@ class TurboNodeArweaveSigner {
46
54
  'x-signature': (0, base64_js_1.toB64Url)(Buffer.from(signature)),
47
55
  };
48
56
  }
57
+ // TODO: make dynamic that accepts anchor and target and tags to return the size of the headers + data
58
+ // reference https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md#13-dataitem-format
59
+ calculateSignedDataHeadersSize({ dataSize }) {
60
+ const anchor = 1; // + whatever they provide (max of 33)
61
+ const target = 1; // + whatever they provide (max of 33)
62
+ const tags = 0;
63
+ const signatureLength = 512;
64
+ const ownerLength = 512;
65
+ const signatureTypeLength = 2;
66
+ const numOfTagsLength = 8; // https://github.com/Bundlr-Network/arbundles/blob/master/src/tags.ts#L191-L198
67
+ const numOfTagsBytesLength = 8;
68
+ return [
69
+ anchor,
70
+ target,
71
+ tags,
72
+ signatureLength,
73
+ ownerLength,
74
+ signatureTypeLength,
75
+ numOfTagsLength,
76
+ numOfTagsBytesLength,
77
+ dataSize,
78
+ ].reduce((totalSize, currentSize) => (totalSize += currentSize));
79
+ }
49
80
  }
50
81
  exports.TurboNodeArweaveSigner = TurboNodeArweaveSigner;
@@ -1,17 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.readableStreamToBuffer = void 0;
4
- async function readableStreamToBuffer({ stream, }) {
4
+ async function readableStreamToBuffer({ stream, size, }) {
5
5
  const reader = stream.getReader();
6
- const chunks = [];
6
+ const buffer = Buffer.alloc(size);
7
+ let offset = 0;
7
8
  let done = false;
8
9
  while (!done) {
9
10
  const { done: streamDone, value } = await reader.read();
10
11
  done = streamDone;
11
12
  if (!done) {
12
- chunks.push(value);
13
+ buffer.set(value, offset);
14
+ offset += value.byteLength;
13
15
  }
14
16
  }
15
- return Buffer.concat(chunks);
17
+ return buffer;
16
18
  }
17
19
  exports.readableStreamToBuffer = readableStreamToBuffer;
@@ -30,15 +30,20 @@ class TurboWebArweaveSigner {
30
30
  this.privateKey = privateKey;
31
31
  this.signer = new arbundles_1.ArweaveSigner(this.privateKey);
32
32
  }
33
- async signDataItem({ fileStreamFactory, }) {
33
+ async signDataItem({ fileStreamFactory, fileSizeFactory, }) {
34
34
  // TODO: converts the readable stream to a buffer bc incrementally signing ReadableStreams is not trivial
35
35
  const buffer = await (0, readableStream_js_1.readableStreamToBuffer)({
36
36
  stream: fileStreamFactory(),
37
- // TODO: add payload size to get performance improvements
37
+ size: fileSizeFactory(),
38
38
  });
39
- const signedDataItem = (0, arbundles_1.createData)(buffer, this.signer);
39
+ // TODO: support target, anchor and tags for upload
40
+ const signedDataItem = (0, arbundles_1.createData)(buffer, this.signer, {});
40
41
  await signedDataItem.sign(this.signer);
41
- return signedDataItem.getRaw();
42
+ return {
43
+ // while this returns a Buffer - it needs to match our return type for uploading
44
+ dataItemStreamFactory: () => signedDataItem.getRaw(),
45
+ dataItemSizeFactory: () => signedDataItem.getRaw().length,
46
+ };
42
47
  }
43
48
  // NOTE: this might be better in a parent class or elsewhere - easy enough to leave in here now and does require specific environment version of crypto
44
49
  async generateSignedRequestHeaders() {
@@ -0,0 +1,27 @@
1
+ export class ZeroDecimalCurrency {
2
+ constructor(amount, type) {
3
+ this.amount = amount;
4
+ this.type = type;
5
+ }
6
+ }
7
+ export class TwoDecimalCurrency {
8
+ constructor(a, type) {
9
+ this.a = a;
10
+ this.type = type;
11
+ }
12
+ get amount() {
13
+ return this.a * 100;
14
+ }
15
+ }
16
+ // Two decimal currencies that are supported by the Turbo API
17
+ export const USD = (usd) => new TwoDecimalCurrency(usd, 'usd');
18
+ export const EUR = (eur) => new TwoDecimalCurrency(eur, 'eur');
19
+ export const GBP = (gbp) => new TwoDecimalCurrency(gbp, 'gbp');
20
+ export const CAD = (cad) => new TwoDecimalCurrency(cad, 'cad');
21
+ export const AUD = (aud) => new TwoDecimalCurrency(aud, 'aud');
22
+ export const INR = (inr) => new TwoDecimalCurrency(inr, 'inr');
23
+ export const SGD = (sgd) => new TwoDecimalCurrency(sgd, 'sgd');
24
+ export const HKD = (hkd) => new TwoDecimalCurrency(hkd, 'hkd');
25
+ export const BRL = (brl) => new TwoDecimalCurrency(brl, 'brl');
26
+ // Zero decimal currencies that are supported by the Turbo API
27
+ export const JPY = (jpy) => new ZeroDecimalCurrency(jpy, 'jpy');
@@ -17,3 +17,4 @@
17
17
  export * from './upload.js';
18
18
  export * from './payment.js';
19
19
  export * from './turbo.js';
20
+ export * from './currency.js';
@@ -1,27 +1,29 @@
1
1
  import { TurboHTTPService } from './http.js';
2
+ export const developmentPaymentServiceURL = 'https://payment.ardrive.dev';
3
+ export const defaultPaymentServiceURL = 'https://payment.ardrive.io';
2
4
  export class TurboUnauthenticatedPaymentService {
3
- constructor({ url = 'https://payment.ardrive.dev', retryConfig, }) {
5
+ constructor({ url = defaultPaymentServiceURL, retryConfig, }) {
4
6
  this.httpService = new TurboHTTPService({
5
7
  url: `${url}/v1`,
6
8
  retryConfig,
7
9
  });
8
10
  }
9
- async getFiatRates() {
11
+ getFiatRates() {
10
12
  return this.httpService.get({
11
13
  endpoint: '/rates',
12
14
  });
13
15
  }
14
- async getFiatToAR({ currency, }) {
16
+ getFiatToAR({ currency, }) {
15
17
  return this.httpService.get({
16
18
  endpoint: `/rates/${currency}`,
17
19
  });
18
20
  }
19
- async getSupportedCountries() {
21
+ getSupportedCountries() {
20
22
  return this.httpService.get({
21
23
  endpoint: '/countries',
22
24
  });
23
25
  }
24
- async getSupportedCurrencies() {
26
+ getSupportedCurrencies() {
25
27
  return this.httpService.get({
26
28
  endpoint: '/currencies',
27
29
  });
@@ -33,15 +35,38 @@ export class TurboUnauthenticatedPaymentService {
33
35
  const wincCostsForBytes = await Promise.all(fetchPricePromises);
34
36
  return wincCostsForBytes;
35
37
  }
36
- async getWincForFiat({ amount, currency }) {
38
+ getWincForFiat({ amount, }) {
39
+ const { amount: paymentAmount, type: currencyType } = amount;
37
40
  return this.httpService.get({
38
- endpoint: `/price/${currency}/${amount}`,
41
+ endpoint: `/price/${currencyType}/${paymentAmount}`,
39
42
  });
40
43
  }
44
+ appendPromoCodesToQuery(promoCodes) {
45
+ const promoCodesQuery = promoCodes.join(',');
46
+ return promoCodesQuery ? `?promoCode=${promoCodesQuery}` : '';
47
+ }
48
+ async getCheckout({ amount, owner, promoCodes = [] }, headers) {
49
+ const { amount: paymentAmount, type: currencyType } = amount;
50
+ const endpoint = `/top-up/checkout-session/${owner}/${currencyType}/${paymentAmount}${this.appendPromoCodesToQuery(promoCodes)}`;
51
+ const { adjustments, paymentSession, topUpQuote } = await this.httpService.get({
52
+ endpoint,
53
+ headers,
54
+ });
55
+ return {
56
+ winc: topUpQuote.winstonCreditAmount,
57
+ adjustments,
58
+ url: paymentSession.url,
59
+ paymentAmount: topUpQuote.paymentAmount,
60
+ quotedPaymentAmount: topUpQuote.quotedPaymentAmount,
61
+ };
62
+ }
63
+ createCheckoutSession(params) {
64
+ return this.getCheckout(params);
65
+ }
41
66
  }
42
67
  // NOTE: to avoid redundancy, we use inheritance here - but generally prefer composition over inheritance
43
68
  export class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentService {
44
- constructor({ url = 'https://payment.ardrive.dev', retryConfig, signer, }) {
69
+ constructor({ url = defaultPaymentServiceURL, retryConfig, signer, }) {
45
70
  super({ url, retryConfig });
46
71
  this.signer = signer;
47
72
  }
@@ -55,4 +80,13 @@ export class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymen
55
80
  // 404's don't return a balance, so default to 0
56
81
  return balance.winc ? balance : { winc: '0' };
57
82
  }
83
+ async getWincForFiat({ amount, promoCodes = [], }) {
84
+ return this.httpService.get({
85
+ endpoint: `/price/${amount.type}/${amount.amount}${this.appendPromoCodesToQuery(promoCodes)}`,
86
+ headers: await this.signer.generateSignedRequestHeaders(),
87
+ });
88
+ }
89
+ async createCheckoutSession(params) {
90
+ return this.getCheckout(params, await this.signer.generateSignedRequestHeaders());
91
+ }
58
92
  }
@@ -1,5 +1,27 @@
1
- import { TurboUnauthenticatedPaymentService } from './payment.js';
2
- import { TurboUnauthenticatedUploadService } from './upload.js';
1
+ import { TurboUnauthenticatedPaymentService, defaultPaymentServiceURL, developmentPaymentServiceURL, } from './payment.js';
2
+ import { TurboUnauthenticatedUploadService, defaultUploadServiceURL, developmentUploadServiceURL, } from './upload.js';
3
+ /**
4
+ * Testing configuration.
5
+ */
6
+ export const developmentTurboConfiguration = {
7
+ paymentServiceConfig: {
8
+ url: developmentPaymentServiceURL,
9
+ },
10
+ uploadServiceConfig: {
11
+ url: developmentUploadServiceURL,
12
+ },
13
+ };
14
+ /**
15
+ * Production configuration.
16
+ */
17
+ export const defaultTurboConfiguration = {
18
+ paymentServiceConfig: {
19
+ url: defaultPaymentServiceURL,
20
+ },
21
+ uploadServiceConfig: {
22
+ url: defaultUploadServiceURL,
23
+ },
24
+ };
3
25
  export class TurboUnauthenticatedClient {
4
26
  constructor({ uploadService = new TurboUnauthenticatedUploadService({}), paymentService = new TurboUnauthenticatedPaymentService({}), }) {
5
27
  this.paymentService = paymentService;
@@ -8,7 +30,7 @@ export class TurboUnauthenticatedClient {
8
30
  /**
9
31
  * Returns the supported fiat currency conversion rate for 1AR based on current market prices.
10
32
  */
11
- async getFiatToAR({ currency, }) {
33
+ getFiatToAR({ currency, }) {
12
34
  return this.paymentService.getFiatToAR({ currency });
13
35
  }
14
36
  /**
@@ -17,42 +39,49 @@ export class TurboUnauthenticatedClient {
17
39
  * Note: this does not take into account varying adjustments and promotions for different sizes of data. If you want to calculate the total
18
40
  * cost in 'winc' for a given number of bytes, use getUploadCosts.
19
41
  */
20
- async getFiatRates() {
42
+ getFiatRates() {
21
43
  return this.paymentService.getFiatRates();
22
44
  }
23
45
  /**
24
46
  * Returns a comprehensive list of supported countries that can purchase credits through the Turbo Payment Service.
25
47
  */
26
- async getSupportedCountries() {
48
+ getSupportedCountries() {
27
49
  return this.paymentService.getSupportedCountries();
28
50
  }
29
51
  /**
30
52
  * Returns a list of all supported fiat currencies.
31
53
  */
32
- async getSupportedCurrencies() {
54
+ getSupportedCurrencies() {
33
55
  return this.paymentService.getSupportedCurrencies();
34
56
  }
35
57
  /**
36
58
  * Determines the price in 'winc' to upload one data item of a specific size in bytes, including all Turbo cost adjustments and fees.
37
59
  */
38
- async getUploadCosts({ bytes, }) {
60
+ getUploadCosts({ bytes, }) {
39
61
  return this.paymentService.getUploadCosts({ bytes });
40
62
  }
41
63
  /**
42
64
  * Determines the amount of 'winc' that would be returned for a given currency and amount, including all Turbo cost adjustments and fees.
43
65
  */
44
- async getWincForFiat({ amount, currency, }) {
45
- return this.paymentService.getWincForFiat({ amount, currency });
66
+ getWincForFiat(params) {
67
+ return this.paymentService.getWincForFiat(params);
46
68
  }
47
69
  /**
48
70
  * Uploads a signed data item to the Turbo Upload Service.
49
71
  */
50
- async uploadSignedDataItem({ dataItemStreamFactory, signal, }) {
72
+ uploadSignedDataItem({ dataItemStreamFactory, dataItemSizeFactory, signal, }) {
51
73
  return this.uploadService.uploadSignedDataItem({
52
74
  dataItemStreamFactory,
75
+ dataItemSizeFactory,
53
76
  signal,
54
77
  });
55
78
  }
79
+ /**
80
+ * Creates a Turbo Checkout Session for a given amount and currency.
81
+ */
82
+ createCheckoutSession(params) {
83
+ return this.paymentService.createCheckoutSession(params);
84
+ }
56
85
  }
57
86
  export class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
58
87
  constructor({ paymentService, uploadService, }) {
@@ -61,13 +90,17 @@ export class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
61
90
  /**
62
91
  * Returns the current balance of the user's wallet in 'winc'.
63
92
  */
64
- async getBalance() {
93
+ getBalance() {
65
94
  return this.paymentService.getBalance();
66
95
  }
67
96
  /**
68
97
  * Signs and uploads raw data to the Turbo Upload Service.
69
98
  */
70
- async uploadFile({ fileStreamFactory, signal, }) {
71
- return this.uploadService.uploadFile({ fileStreamFactory, signal });
99
+ uploadFile({ fileStreamFactory, fileSizeFactory, signal, }) {
100
+ return this.uploadService.uploadFile({
101
+ fileStreamFactory,
102
+ fileSizeFactory,
103
+ signal,
104
+ });
72
105
  }
73
106
  }
@@ -1,12 +1,15 @@
1
1
  import { TurboHTTPService } from './http.js';
2
+ export const defaultUploadServiceURL = 'https://upload.ardrive.io';
3
+ export const developmentUploadServiceURL = 'https://upload.ardrive.dev';
2
4
  export class TurboUnauthenticatedUploadService {
3
- constructor({ url = 'https://upload.ardrive.dev', retryConfig, }) {
5
+ constructor({ url = defaultUploadServiceURL, retryConfig, }) {
4
6
  this.httpService = new TurboHTTPService({
5
7
  url: `${url}/v1`,
6
8
  retryConfig,
7
9
  });
8
10
  }
9
- async uploadSignedDataItem({ dataItemStreamFactory, signal, }) {
11
+ async uploadSignedDataItem({ dataItemStreamFactory, dataItemSizeFactory, signal, }) {
12
+ const fileSize = dataItemSizeFactory();
10
13
  // TODO: add p-limit constraint or replace with separate upload class
11
14
  return this.httpService.post({
12
15
  endpoint: `/tx`,
@@ -14,6 +17,7 @@ export class TurboUnauthenticatedUploadService {
14
17
  data: dataItemStreamFactory(),
15
18
  headers: {
16
19
  'content-type': 'application/octet-stream',
20
+ 'content-length': `${fileSize}`,
17
21
  },
18
22
  });
19
23
  }
@@ -24,10 +28,13 @@ export class TurboAuthenticatedUploadService extends TurboUnauthenticatedUploadS
24
28
  super({ url, retryConfig });
25
29
  this.signer = signer;
26
30
  }
27
- async uploadFile({ fileStreamFactory, signal, }) {
28
- const signedDataItem = await this.signer.signDataItem({
31
+ async uploadFile({ fileStreamFactory, fileSizeFactory, signal, }) {
32
+ const { dataItemStreamFactory, dataItemSizeFactory } = await this.signer.signDataItem({
29
33
  fileStreamFactory,
34
+ fileSizeFactory,
30
35
  });
36
+ const signedDataItem = dataItemStreamFactory();
37
+ const fileSize = dataItemSizeFactory();
31
38
  // TODO: add p-limit constraint or replace with separate upload class
32
39
  return this.httpService.post({
33
40
  endpoint: `/tx`,
@@ -35,6 +42,7 @@ export class TurboAuthenticatedUploadService extends TurboUnauthenticatedUploadS
35
42
  data: signedDataItem,
36
43
  headers: {
37
44
  'content-type': 'application/octet-stream',
45
+ 'content-length': `${fileSize}`,
38
46
  },
39
47
  });
40
48
  }