@ardrive/turbo-sdk 1.33.1 → 1.34.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +49 -6
  2. package/bundles/web.bundle.min.js +103598 -103276
  3. package/lib/cjs/cli/cli.js +1 -1
  4. package/lib/cjs/cli/commands/cryptoFund.js +3 -1
  5. package/lib/cjs/common/payment.js +17 -4
  6. package/lib/cjs/common/signer.js +16 -1
  7. package/lib/cjs/common/token/ario.js +27 -19
  8. package/lib/cjs/common/token/arweave.js +4 -1
  9. package/lib/cjs/common/token/baseEth.js +7 -6
  10. package/lib/cjs/common/token/erc20.js +91 -0
  11. package/lib/cjs/common/token/ethereum.js +38 -18
  12. package/lib/cjs/common/token/index.js +11 -0
  13. package/lib/cjs/common/token/polygon.js +7 -6
  14. package/lib/cjs/common/token/solana.js +11 -2
  15. package/lib/cjs/common/token/usdc.js +83 -0
  16. package/lib/cjs/common/upload.js +6 -1
  17. package/lib/cjs/types.js +3 -0
  18. package/lib/cjs/utils/common.js +71 -4
  19. package/lib/cjs/version.js +1 -1
  20. package/lib/esm/cli/cli.js +1 -1
  21. package/lib/esm/cli/commands/cryptoFund.js +3 -1
  22. package/lib/esm/common/payment.js +17 -4
  23. package/lib/esm/common/signer.js +17 -2
  24. package/lib/esm/common/token/ario.js +27 -19
  25. package/lib/esm/common/token/arweave.js +4 -1
  26. package/lib/esm/common/token/baseEth.js +6 -5
  27. package/lib/esm/common/token/erc20.js +87 -0
  28. package/lib/esm/common/token/ethereum.js +37 -18
  29. package/lib/esm/common/token/index.js +11 -0
  30. package/lib/esm/common/token/polygon.js +6 -5
  31. package/lib/esm/common/token/solana.js +11 -2
  32. package/lib/esm/common/token/usdc.js +76 -0
  33. package/lib/esm/common/upload.js +6 -1
  34. package/lib/esm/types.js +3 -0
  35. package/lib/esm/utils/common.js +66 -5
  36. package/lib/esm/version.js +1 -1
  37. package/lib/types/cli/commands/cryptoFund.d.ts.map +1 -1
  38. package/lib/types/cli/types.d.ts +1 -0
  39. package/lib/types/cli/types.d.ts.map +1 -1
  40. package/lib/types/common/payment.d.ts +1 -1
  41. package/lib/types/common/payment.d.ts.map +1 -1
  42. package/lib/types/common/signer.d.ts +2 -2
  43. package/lib/types/common/signer.d.ts.map +1 -1
  44. package/lib/types/common/token/ario.d.ts +1 -1
  45. package/lib/types/common/token/ario.d.ts.map +1 -1
  46. package/lib/types/common/token/arweave.d.ts +1 -1
  47. package/lib/types/common/token/arweave.d.ts.map +1 -1
  48. package/lib/types/common/token/baseEth.d.ts +5 -0
  49. package/lib/types/common/token/baseEth.d.ts.map +1 -1
  50. package/lib/types/common/token/erc20.d.ts +19 -0
  51. package/lib/types/common/token/erc20.d.ts.map +1 -0
  52. package/lib/types/common/token/ethereum.d.ts +4 -2
  53. package/lib/types/common/token/ethereum.d.ts.map +1 -1
  54. package/lib/types/common/token/index.d.ts.map +1 -1
  55. package/lib/types/common/token/polygon.d.ts +5 -0
  56. package/lib/types/common/token/polygon.d.ts.map +1 -1
  57. package/lib/types/common/token/solana.d.ts +2 -1
  58. package/lib/types/common/token/solana.d.ts.map +1 -1
  59. package/lib/types/common/token/usdc.d.ts +36 -0
  60. package/lib/types/common/token/usdc.d.ts.map +1 -0
  61. package/lib/types/common/upload.d.ts.map +1 -1
  62. package/lib/types/types.d.ts +8 -2
  63. package/lib/types/types.d.ts.map +1 -1
  64. package/lib/types/utils/common.d.ts +6 -0
  65. package/lib/types/utils/common.d.ts.map +1 -1
  66. package/lib/types/version.d.ts +1 -1
  67. package/lib/types/version.d.ts.map +1 -1
  68. package/package.json +1 -1
@@ -41,7 +41,7 @@ const utils_js_1 = require("./utils.js");
41
41
  (0, utils_js_1.applyOptions)(commander_1.program.command('top-up').description('Top up a Turbo address with Fiat'), [...options_js_1.walletOptions, options_js_1.optionMap.address, options_js_1.optionMap.value, options_js_1.optionMap.currency]).action(async (_commandOptions, command) => {
42
42
  await (0, utils_js_1.runCommand)(command, index_js_1.topUp);
43
43
  });
44
- (0, utils_js_1.applyOptions)(commander_1.program.command('crypto-fund').description('Top up a wallet with crypto'), [...options_js_1.walletOptions, options_js_1.optionMap.value, options_js_1.optionMap.txId]).action(async (_commandOptions, command) => {
44
+ (0, utils_js_1.applyOptions)(commander_1.program.command('crypto-fund').description('Top up a wallet with crypto'), [...options_js_1.walletOptions, options_js_1.optionMap.value, options_js_1.optionMap.txId, options_js_1.optionMap.address]).action(async (_commandOptions, command) => {
45
45
  await (0, utils_js_1.runCommand)(command, index_js_1.cryptoFund);
46
46
  });
47
47
  (0, utils_js_1.applyOptions)(commander_1.program.command('upload-folder').description('Upload a folder using Turbo'), options_js_1.uploadFolderOptions).action(async (_commandOptions, command) => {
@@ -28,6 +28,7 @@ const utils_js_1 = require("../utils.js");
28
28
  async function cryptoFund(options) {
29
29
  const value = options.value;
30
30
  const txId = options.txId;
31
+ const address = options.address;
31
32
  if (txId !== undefined) {
32
33
  const turbo = factory_js_1.TurboFactory.unauthenticated((0, utils_js_1.configFromOptions)(options));
33
34
  const result = await turbo.submitFundTransaction({ txId: txId });
@@ -47,7 +48,7 @@ async function cryptoFund(options) {
47
48
  const { confirm } = await (0, prompts_1.default)({
48
49
  type: 'confirm',
49
50
  name: 'confirm',
50
- message: `\nTransaction details:\n\n Amount: ${value} ${token}\n Target: ${targetWallet}\n Est Credits to receive: ${credits}\n Credit recipient: ${await turbo.signer.getNativeAddress()}\n Note: Network Dependent Gas Fees May Apply\n\nThis payment is non-refundable. Proceed with transaction?`,
51
+ message: `\nTransaction details:\n\n Amount: ${value} ${token}\n Target: ${targetWallet}\n Est Credits to receive: ${credits}\n Credit recipient: ${address ?? (await turbo.signer.getNativeAddress())}\n Note: Network Dependent Gas Fees May Apply\n\nThis payment is non-refundable. Proceed with transaction?`,
51
52
  initial: true,
52
53
  });
53
54
  if (!confirm) {
@@ -57,6 +58,7 @@ async function cryptoFund(options) {
57
58
  }
58
59
  const result = await turbo.topUpWithTokens({
59
60
  tokenAmount,
61
+ turboCreditDestinationAddress: address,
60
62
  });
61
63
  console.log('Sent crypto fund transaction: \n', JSON.stringify(result, null, 2));
62
64
  }
@@ -18,6 +18,7 @@ exports.TurboAuthenticatedPaymentService = exports.TurboUnauthenticatedPaymentSe
18
18
  */
19
19
  const bignumber_js_1 = require("bignumber.js");
20
20
  const axiosClient_js_1 = require("../utils/axiosClient.js");
21
+ const common_js_1 = require("../utils/common.js");
21
22
  const http_js_1 = require("./http.js");
22
23
  const logger_js_1 = require("./logger.js");
23
24
  const index_js_1 = require("./token/index.js");
@@ -151,31 +152,37 @@ class TurboUnauthenticatedPaymentService {
151
152
  return {
152
153
  id: response.creditedTransaction.transactionId,
153
154
  quantity: response.creditedTransaction.transactionQuantity,
154
- owner: response.creditedTransaction.destinationAddress,
155
+ owner: response.creditedTransaction.transactionSenderAddress ??
156
+ response.creditedTransaction.destinationAddress,
155
157
  winc: response.creditedTransaction.winstonCreditAmount,
156
158
  token: response.creditedTransaction.tokenType,
157
159
  status: 'confirmed',
158
160
  block: response.creditedTransaction.blockHeight,
161
+ recipient: response.creditedTransaction.destinationAddress,
159
162
  };
160
163
  }
161
164
  else if ('pendingTransaction' in response) {
162
165
  return {
163
166
  id: response.pendingTransaction.transactionId,
164
167
  quantity: response.pendingTransaction.transactionQuantity,
165
- owner: response.pendingTransaction.destinationAddress,
168
+ owner: response.pendingTransaction.transactionSenderAddress ??
169
+ response.pendingTransaction.destinationAddress,
166
170
  winc: response.pendingTransaction.winstonCreditAmount,
167
171
  token: response.pendingTransaction.tokenType,
168
172
  status: 'pending',
173
+ recipient: response.pendingTransaction.destinationAddress,
169
174
  };
170
175
  }
171
176
  else if ('failedTransaction' in response) {
172
177
  return {
173
178
  id: response.failedTransaction.transactionId,
174
179
  quantity: response.failedTransaction.transactionQuantity,
175
- owner: response.failedTransaction.destinationAddress,
180
+ owner: response.failedTransaction.transactionSenderAddress ??
181
+ response.failedTransaction.destinationAddress,
176
182
  winc: response.failedTransaction.winstonCreditAmount,
177
183
  token: response.failedTransaction.tokenType,
178
184
  status: 'failed',
185
+ recipient: response.failedTransaction.destinationAddress,
179
186
  };
180
187
  }
181
188
  throw new Error('Unknown response from payment service: ' + response);
@@ -271,10 +278,15 @@ class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentServic
271
278
  }
272
279
  return walletAddress;
273
280
  }
274
- async topUpWithTokens({ feeMultiplier = 1, tokenAmount: tokenAmountV, }) {
281
+ async topUpWithTokens({ feeMultiplier = 1, tokenAmount: tokenAmountV, turboCreditDestinationAddress, }) {
275
282
  if (!this.tokenTools) {
276
283
  throw new Error(`Token type not supported for crypto fund ${this.token}`);
277
284
  }
285
+ if (turboCreditDestinationAddress !== undefined) {
286
+ if ((0, common_js_1.isAnyValidUserAddress)(turboCreditDestinationAddress) === false) {
287
+ throw new Error(`Invalid turboCreditDestinationAddress provided: ${turboCreditDestinationAddress}`);
288
+ }
289
+ }
278
290
  const tokenAmount = new bignumber_js_1.BigNumber(tokenAmountV);
279
291
  const target = await this.getTargetWalletForFund();
280
292
  this.logger.debug('Funding account...', {
@@ -287,6 +299,7 @@ class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentServic
287
299
  tokenAmount,
288
300
  feeMultiplier,
289
301
  signer: this.signer,
302
+ turboCreditDestinationAddress,
290
303
  });
291
304
  const txId = fundTx.id;
292
305
  try {
@@ -34,6 +34,8 @@ const tweetnacl_1 = __importDefault(require("tweetnacl"));
34
34
  const types_js_1 = require("../types.js");
35
35
  const base64_js_1 = require("../utils/base64.js");
36
36
  const logger_js_1 = require("./logger.js");
37
+ const ethereum_js_1 = require("./token/ethereum.js");
38
+ const solana_js_1 = require("./token/solana.js");
37
39
  /**
38
40
  * Abstract class for signing TurboDataItems.
39
41
  */
@@ -52,6 +54,9 @@ class TurboDataItemAbstractSigner {
52
54
  case 'matic':
53
55
  case 'pol':
54
56
  case 'base-eth':
57
+ case 'usdc':
58
+ case 'base-usdc':
59
+ case 'polygon-usdc':
55
60
  return (0, ethers_2.computeAddress)((0, signing_key_1.computePublicKey)((0, base64_js_1.fromB64Url)(owner)));
56
61
  case 'kyve':
57
62
  return (0, amino_1.pubkeyToAddress)({
@@ -81,7 +86,7 @@ class TurboDataItemAbstractSigner {
81
86
  return this.ownerToNativeAddress((0, base64_js_1.toB64Url)(await this.getPublicKey()), this.token);
82
87
  }
83
88
  /** Let the signer handle sending tx for better compat with cross chain libraries/web wallets */
84
- async sendTransaction({ target, amount, gatewayUrl, }) {
89
+ async sendTransaction({ target, amount, gatewayUrl, turboCreditDestinationAddress, }) {
85
90
  if (this.walletAdapter) {
86
91
  if ((0, types_js_1.isSolanaWalletAdapter)(this.walletAdapter)) {
87
92
  const connection = new web3_js_1.Connection(gatewayUrl, 'confirmed');
@@ -95,6 +100,14 @@ class TurboDataItemAbstractSigner {
95
100
  toPubkey: new web3_js_1.PublicKey(target),
96
101
  lamports: +new bignumber_js_1.BigNumber(amount),
97
102
  }));
103
+ if (turboCreditDestinationAddress !== undefined) {
104
+ tx.add(new web3_js_1.TransactionInstruction({
105
+ programId: new web3_js_1.PublicKey(solana_js_1.memoProgramId),
106
+ keys: [],
107
+ data: Buffer.from('turboCreditDestinationAddress=' +
108
+ turboCreditDestinationAddress),
109
+ }));
110
+ }
98
111
  const signedTx = await this.walletAdapter.signTransaction(tx);
99
112
  const id = await connection.sendRawTransaction(signedTx.serialize());
100
113
  return id;
@@ -109,6 +122,7 @@ class TurboDataItemAbstractSigner {
109
122
  const { hash } = await signer.sendTransaction({
110
123
  to: target,
111
124
  value: (0, ethers_1.parseEther)(amount.toFixed(18)),
125
+ data: (0, ethereum_js_1.ethDataFromTurboCreditDestinationAddress)(turboCreditDestinationAddress),
112
126
  });
113
127
  return hash;
114
128
  }
@@ -121,6 +135,7 @@ class TurboDataItemAbstractSigner {
121
135
  const tx = await ethWalletAndProvider.sendTransaction({
122
136
  to: target,
123
137
  value: (0, ethers_1.parseEther)(amount.toFixed(18)),
138
+ data: (0, ethereum_js_1.ethDataFromTurboCreditDestinationAddress)(turboCreditDestinationAddress),
124
139
  });
125
140
  this.logger.debug('Sent transaction', { tx });
126
141
  return tx.hash;
@@ -35,34 +35,42 @@ class ARIOToken {
35
35
  this.pollingOptions = pollingOptions;
36
36
  this.logger = logger;
37
37
  }
38
- async createAndSubmitTx({ target, signer: { signer }, tokenAmount, }) {
38
+ async createAndSubmitTx({ target, signer: { signer }, tokenAmount, turboCreditDestinationAddress, }) {
39
+ const tags = [
40
+ {
41
+ name: 'Action',
42
+ value: 'Transfer',
43
+ },
44
+ {
45
+ name: 'Recipient',
46
+ value: target,
47
+ },
48
+ {
49
+ name: 'Quantity',
50
+ value: tokenAmount.toString(),
51
+ },
52
+ {
53
+ name: 'Turbo-SDK',
54
+ value: version_js_1.version,
55
+ },
56
+ ];
57
+ if (turboCreditDestinationAddress !== undefined) {
58
+ tags.push({
59
+ name: 'Turbo-Credit-Destination-Address',
60
+ value: turboCreditDestinationAddress,
61
+ });
62
+ }
39
63
  const txId = await this.ao.message({
40
64
  signer: createAoSigner(signer),
41
65
  process: this.processId,
42
- tags: [
43
- {
44
- name: 'Action',
45
- value: 'Transfer',
46
- },
47
- {
48
- name: 'Recipient',
49
- value: target,
50
- },
51
- {
52
- name: 'Quantity',
53
- value: tokenAmount.toString(),
54
- },
55
- {
56
- name: 'Turbo-SDK',
57
- value: version_js_1.version,
58
- },
59
- ],
66
+ tags,
60
67
  });
61
68
  this.logger.debug('Submitted Transfer message to ARIO process...', {
62
69
  id: txId,
63
70
  target,
64
71
  tokenAmount,
65
72
  processId: this.processId,
73
+ tags,
66
74
  });
67
75
  return { id: txId, target, reward: '0' };
68
76
  }
@@ -46,7 +46,7 @@ class ArweaveToken {
46
46
  this.mintU = mintU;
47
47
  this.pollingOptions = pollingOptions;
48
48
  }
49
- async createAndSubmitTx({ feeMultiplier, target, tokenAmount, signer, }) {
49
+ async createAndSubmitTx({ feeMultiplier, target, tokenAmount, signer, turboCreditDestinationAddress, }) {
50
50
  const tx = await this.arweave.createTransaction({
51
51
  target,
52
52
  quantity: tokenAmount.toString(),
@@ -63,6 +63,9 @@ class ArweaveToken {
63
63
  tx.addTag('Contract', 'KTzTXT_ANmF84fWEKHzWURD1LWd9QaFR9yfYUwH2Lxw'); // cspell:enable
64
64
  tx.addTag('Input', JSON.stringify({ function: 'mint' }));
65
65
  }
66
+ if (turboCreditDestinationAddress !== undefined) {
67
+ tx.addTag('Turbo-Credit-Destination-Address', turboCreditDestinationAddress);
68
+ }
66
69
  const publicKeyB64Url = (0, base64_js_1.toB64Url)(await signer.getPublicKey());
67
70
  tx.setOwner(publicKeyB64Url);
68
71
  const dataToSign = await tx.getSignatureData();
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BaseEthToken = void 0;
3
+ exports.BaseEthToken = exports.defaultBaseNetworkPollingOptions = void 0;
4
4
  const common_js_1 = require("../../utils/common.js");
5
5
  const ethereum_js_1 = require("./ethereum.js");
6
+ exports.defaultBaseNetworkPollingOptions = {
7
+ initialBackoffMs: 2_500,
8
+ maxAttempts: 10,
9
+ pollingIntervalMs: 750,
10
+ };
6
11
  class BaseEthToken extends ethereum_js_1.EthereumToken {
7
- constructor({ logger, gatewayUrl = common_js_1.defaultProdGatewayUrls['base-eth'], pollingOptions = {
8
- initialBackoffMs: 2_500,
9
- maxAttempts: 10,
10
- pollingIntervalMs: 2_500,
11
- }, } = {}) {
12
+ constructor({ logger, gatewayUrl = common_js_1.defaultProdGatewayUrls['base-eth'], pollingOptions = exports.defaultBaseNetworkPollingOptions, } = {}) {
12
13
  super({
13
14
  logger,
14
15
  gatewayUrl,
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ERC20Token = void 0;
4
+ /**
5
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ const arbundles_1 = require("@dha-team/arbundles");
20
+ const ethers_1 = require("ethers");
21
+ const types_js_1 = require("../../types.js");
22
+ const common_js_1 = require("../../utils/common.js");
23
+ const logger_js_1 = require("../logger.js");
24
+ const ethereum_js_1 = require("./ethereum.js");
25
+ class ERC20Token extends ethereum_js_1.EthereumToken {
26
+ constructor({ tokenContractAddress, logger = logger_js_1.TurboWinstonLogger.default, gatewayUrl = common_js_1.defaultProdGatewayUrls.ethereum, pollingOptions, }) {
27
+ super({ logger, gatewayUrl, pollingOptions });
28
+ this.tokenContract = new ethers_1.ethers.Contract(tokenContractAddress, [
29
+ 'function decimals() view returns (uint8)',
30
+ 'function balanceOf(address) view returns (uint256)',
31
+ 'function transfer(address to, uint256 value) returns (bool)',
32
+ ], this.rpcProvider);
33
+ }
34
+ async createAndSubmitTx({ target, tokenAmount, signer, turboCreditDestinationAddress, }) {
35
+ try {
36
+ let connected;
37
+ let walletOrSigner;
38
+ if (signer.signer instanceof arbundles_1.EthereumSigner) {
39
+ const provider = new ethers_1.JsonRpcProvider(this.gatewayUrl);
40
+ // 🧩 CLI / Node path
41
+ const keyHex = Buffer.from(signer.signer.key).toString('hex');
42
+ walletOrSigner = new ethers_1.Wallet(keyHex, provider);
43
+ connected = this.tokenContract.connect(walletOrSigner);
44
+ }
45
+ else if (signer.walletAdapter !== undefined &&
46
+ (0, types_js_1.isEthereumWalletAdapter)(signer.walletAdapter)) {
47
+ walletOrSigner = signer.walletAdapter.getSigner();
48
+ connected = this.tokenContract.connect(walletOrSigner);
49
+ }
50
+ else {
51
+ throw new Error('Unsupported signer -- must be EthereumSigner or have a walletAdapter implementing getSigner');
52
+ }
53
+ // Encode transfer data
54
+ const baseTransferData = connected.interface.encodeFunctionData('transfer', [target, tokenAmount.toString()]);
55
+ let finalData = baseTransferData;
56
+ // Append optional memo data with turbo credit destination address
57
+ const memoData = (0, ethereum_js_1.ethDataFromTurboCreditDestinationAddress)(turboCreditDestinationAddress);
58
+ if (memoData !== undefined) {
59
+ // remove the "0x" prefix and append
60
+ finalData += memoData.slice(2);
61
+ }
62
+ const txRequest = {
63
+ to: await connected.getAddress(),
64
+ data: finalData,
65
+ };
66
+ this.logger.debug('Submitting ERC20 transfer', {
67
+ target,
68
+ tokenAmount: tokenAmount.toString(),
69
+ rpcEndpoint: this.gatewayUrl,
70
+ txRequest,
71
+ });
72
+ const tx = await walletOrSigner.sendTransaction(txRequest);
73
+ this.logger.debug('ERC20 transfer submitted', {
74
+ txHash: tx.hash,
75
+ target,
76
+ tx,
77
+ });
78
+ return { id: tx.hash, target };
79
+ }
80
+ catch (e) {
81
+ this.logger.error('Error creating/submitting ERC20 tx', {
82
+ error: e instanceof Error ? e.message : e,
83
+ target,
84
+ tokenAmount,
85
+ rpcEndpoint: this.gatewayUrl,
86
+ });
87
+ throw e;
88
+ }
89
+ }
90
+ }
91
+ exports.ERC20Token = ERC20Token;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EthereumToken = exports.ETHToTokenAmount = exports.weiToTokenAmount = void 0;
3
+ exports.EthereumToken = exports.defaultEthereumPollingOptions = exports.ETHToTokenAmount = exports.weiToTokenAmount = void 0;
4
+ exports.ethDataFromTurboCreditDestinationAddress = ethDataFromTurboCreditDestinationAddress;
4
5
  /**
5
6
  * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
6
7
  *
@@ -24,29 +25,42 @@ const weiToTokenAmount = (wei) => wei;
24
25
  exports.weiToTokenAmount = weiToTokenAmount;
25
26
  const ETHToTokenAmount = (eth) => new bignumber_js_1.BigNumber(eth).times(1e18).valueOf();
26
27
  exports.ETHToTokenAmount = ETHToTokenAmount;
28
+ exports.defaultEthereumPollingOptions = {
29
+ initialBackoffMs: 25_000,
30
+ maxAttempts: 10,
31
+ pollingIntervalMs: 1_500,
32
+ };
27
33
  class EthereumToken {
28
- constructor({ logger = logger_js_1.TurboWinstonLogger.default, gatewayUrl = common_js_1.defaultProdGatewayUrls.ethereum, pollingOptions = {
29
- maxAttempts: 10,
30
- pollingIntervalMs: 4_000,
31
- initialBackoffMs: 10_000,
32
- }, } = {}) {
34
+ constructor({ logger = logger_js_1.TurboWinstonLogger.default, gatewayUrl = common_js_1.defaultProdGatewayUrls.ethereum, pollingOptions = exports.defaultEthereumPollingOptions, } = {}) {
33
35
  this.logger = logger;
34
36
  this.gatewayUrl = gatewayUrl;
35
37
  this.pollingOptions = pollingOptions;
36
38
  this.rpcProvider = new ethers_1.ethers.JsonRpcProvider(gatewayUrl);
37
39
  }
38
- async createAndSubmitTx({ target, tokenAmount, signer, }) {
39
- // convert wei to eth
40
- const eth = tokenAmount.shiftedBy(-18);
41
- const txId = await signer.sendTransaction({
42
- target,
43
- amount: eth,
44
- gatewayUrl: this.gatewayUrl,
45
- });
46
- return {
47
- id: txId,
48
- target,
49
- };
40
+ async createAndSubmitTx({ target, tokenAmount, signer, turboCreditDestinationAddress, }) {
41
+ try {
42
+ // convert wei to eth
43
+ const eth = tokenAmount.shiftedBy(-18);
44
+ const txId = await signer.sendTransaction({
45
+ target,
46
+ amount: eth,
47
+ gatewayUrl: this.gatewayUrl,
48
+ turboCreditDestinationAddress,
49
+ });
50
+ return {
51
+ id: txId,
52
+ target,
53
+ };
54
+ }
55
+ catch (e) {
56
+ this.logger.error('Error creating and submitting Ethereum tx', {
57
+ error: e instanceof Error ? e.message : e,
58
+ target,
59
+ tokenAmount,
60
+ rpcEndpoint: this.gatewayUrl,
61
+ });
62
+ throw e;
63
+ }
50
64
  }
51
65
  async getTxAvailability(txId) {
52
66
  const tx = await this.rpcProvider.getTransaction(txId);
@@ -77,3 +91,9 @@ class EthereumToken {
77
91
  }
78
92
  }
79
93
  exports.EthereumToken = EthereumToken;
94
+ function ethDataFromTurboCreditDestinationAddress(turboCreditDestinationAddress) {
95
+ if (turboCreditDestinationAddress !== undefined) {
96
+ return (0, ethers_1.hexlify)((0, ethers_1.toUtf8Bytes)('turboCreditDestinationAddress=' + turboCreditDestinationAddress));
97
+ }
98
+ return undefined;
99
+ }
@@ -24,6 +24,7 @@ const ethereum_js_1 = require("./ethereum.js");
24
24
  const kyve_js_1 = require("./kyve.js");
25
25
  const polygon_js_1 = require("./polygon.js");
26
26
  const solana_js_1 = require("./solana.js");
27
+ const usdc_js_1 = require("./usdc.js");
27
28
  exports.defaultTokenMap = {
28
29
  arweave: (config) => new arweave_js_1.ArweaveToken(config),
29
30
  ario: (config) => new ario_js_1.ARIOToken(config),
@@ -33,8 +34,12 @@ exports.defaultTokenMap = {
33
34
  kyve: (config) => new kyve_js_1.KyveToken(config),
34
35
  matic: (config) => new polygon_js_1.PolygonToken(config),
35
36
  pol: (config) => new polygon_js_1.PolygonToken(config),
37
+ usdc: (config) => new usdc_js_1.USDCToken({ network: 'ethereum', ...config }),
38
+ 'base-usdc': (config) => new usdc_js_1.USDCToken({ network: 'base', ...config }),
39
+ 'polygon-usdc': (config) => new usdc_js_1.USDCToken({ network: 'polygon', ...config }),
36
40
  };
37
41
  const ethExponent = 18;
42
+ const usdcExponent = 6;
38
43
  exports.exponentMap = {
39
44
  arweave: 12,
40
45
  ario: 6,
@@ -44,6 +49,9 @@ exports.exponentMap = {
44
49
  kyve: 6,
45
50
  matic: ethExponent,
46
51
  pol: ethExponent,
52
+ usdc: usdcExponent,
53
+ 'base-usdc': usdcExponent,
54
+ 'polygon-usdc': usdcExponent,
47
55
  };
48
56
  exports.tokenToBaseMap = {
49
57
  arweave: (a) => (0, arweave_js_1.ARToTokenAmount)(a),
@@ -54,6 +62,9 @@ exports.tokenToBaseMap = {
54
62
  kyve: (a) => (0, kyve_js_1.KYVEToTokenAmount)(a),
55
63
  matic: (a) => (0, polygon_js_1.POLToTokenAmount)(a),
56
64
  pol: (a) => (0, polygon_js_1.POLToTokenAmount)(a),
65
+ usdc: (a) => (0, usdc_js_1.USDCToTokenAmount)(a),
66
+ 'base-usdc': (a) => (0, usdc_js_1.USDCToTokenAmount)(a),
67
+ 'polygon-usdc': (a) => (0, usdc_js_1.USDCToTokenAmount)(a),
57
68
  };
58
69
  function isTokenType(token) {
59
70
  return types_js_1.tokenTypes.includes(token);
@@ -1,16 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PolygonToken = exports.POLToTokenAmount = void 0;
3
+ exports.PolygonToken = exports.defaultPolygonPollingOptions = exports.POLToTokenAmount = void 0;
4
4
  const common_js_1 = require("../../utils/common.js");
5
5
  const logger_js_1 = require("../logger.js");
6
6
  const ethereum_js_1 = require("./ethereum.js");
7
7
  exports.POLToTokenAmount = ethereum_js_1.ETHToTokenAmount;
8
+ exports.defaultPolygonPollingOptions = {
9
+ maxAttempts: 10,
10
+ initialBackoffMs: 5_000,
11
+ pollingIntervalMs: 1_000,
12
+ };
8
13
  class PolygonToken extends ethereum_js_1.EthereumToken {
9
- constructor({ logger = logger_js_1.TurboWinstonLogger.default, gatewayUrl = common_js_1.defaultProdGatewayUrls.pol, pollingOptions = {
10
- maxAttempts: 10,
11
- pollingIntervalMs: 4_000,
12
- initialBackoffMs: 5_000,
13
- }, } = {}) {
14
+ constructor({ logger = logger_js_1.TurboWinstonLogger.default, gatewayUrl = common_js_1.defaultProdGatewayUrls.pol, pollingOptions = exports.defaultPolygonPollingOptions, } = {}) {
14
15
  super({ logger, gatewayUrl, pollingOptions });
15
16
  }
16
17
  }
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SolanaToken = exports.SOLToTokenAmount = exports.lamportToTokenAmount = void 0;
6
+ exports.SolanaToken = exports.memoProgramId = exports.SOLToTokenAmount = exports.lamportToTokenAmount = void 0;
7
7
  /**
8
8
  * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
9
9
  *
@@ -30,6 +30,7 @@ const lamportToTokenAmount = (winston) => winston;
30
30
  exports.lamportToTokenAmount = lamportToTokenAmount;
31
31
  const SOLToTokenAmount = (sol) => new bignumber_js_1.BigNumber(sol).times(1e9).valueOf();
32
32
  exports.SOLToTokenAmount = SOLToTokenAmount;
33
+ exports.memoProgramId = 'MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr';
33
34
  class SolanaToken {
34
35
  constructor({ logger = logger_js_1.TurboWinstonLogger.default, gatewayUrl = common_js_1.defaultProdGatewayUrls.solana, pollingOptions = {
35
36
  maxAttempts: 10,
@@ -41,12 +42,13 @@ class SolanaToken {
41
42
  this.connection = new web3_js_1.Connection(gatewayUrl, 'confirmed');
42
43
  this.pollingOptions = pollingOptions;
43
44
  }
44
- async createAndSubmitTx({ target, tokenAmount, signer, }) {
45
+ async createAndSubmitTx({ target, tokenAmount, signer, turboCreditDestinationAddress, }) {
45
46
  if (signer.signer instanceof arbundles_1.HexInjectedSolanaSigner) {
46
47
  const id = await signer.sendTransaction({
47
48
  amount: tokenAmount,
48
49
  target,
49
50
  gatewayUrl: this.gatewayUrl,
51
+ turboCreditDestinationAddress,
50
52
  });
51
53
  return { target, id };
52
54
  }
@@ -60,6 +62,13 @@ class SolanaToken {
60
62
  toPubkey: new web3_js_1.PublicKey(target),
61
63
  lamports: +new bignumber_js_1.BigNumber(tokenAmount),
62
64
  }));
65
+ if (turboCreditDestinationAddress !== undefined) {
66
+ tx.add(new web3_js_1.TransactionInstruction({
67
+ programId: new web3_js_1.PublicKey(exports.memoProgramId),
68
+ keys: [],
69
+ data: Buffer.from('turboCreditDestinationAddress=' + turboCreditDestinationAddress),
70
+ }));
71
+ }
63
72
  const serializedTx = tx.serializeMessage();
64
73
  const signature = await signer.signData(Uint8Array.from(serializedTx));
65
74
  tx.addSignature(publicKey, Buffer.from(signature));
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.USDCToken = exports.USDCToTokenAmount = exports.mUSDCToTokenAmount = exports.usdcNetworks = void 0;
4
+ /**
5
+ * Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ const bignumber_js_1 = require("bignumber.js");
20
+ const common_js_1 = require("../../utils/common.js");
21
+ const baseEth_js_1 = require("./baseEth.js");
22
+ const erc20_js_1 = require("./erc20.js");
23
+ const ethereum_js_1 = require("./ethereum.js");
24
+ const polygon_js_1 = require("./polygon.js");
25
+ /**
26
+ * Known USDC contract addresses and default RPCs by network
27
+ */
28
+ const usdcNetworks = (useDevnet = false) => ({
29
+ ethereum: {
30
+ tokenContractAddress: useDevnet
31
+ ? ethSepoliaUsdcAddress
32
+ : ethMainnetUsdcAddress,
33
+ rpcEndpoint: useDevnet
34
+ ? common_js_1.tokenToDevGatewayMap.ethereum
35
+ : common_js_1.defaultProdGatewayUrls.ethereum,
36
+ defaultPollingOptions: ethereum_js_1.defaultEthereumPollingOptions,
37
+ },
38
+ base: {
39
+ tokenContractAddress: useDevnet
40
+ ? baseSepoliaUsdcAddress
41
+ : baseMainnetUsdcAddress,
42
+ rpcEndpoint: useDevnet
43
+ ? common_js_1.tokenToDevGatewayMap['base-eth']
44
+ : common_js_1.defaultProdGatewayUrls['base-eth'],
45
+ defaultPollingOptions: baseEth_js_1.defaultBaseNetworkPollingOptions,
46
+ },
47
+ polygon: {
48
+ tokenContractAddress: useDevnet
49
+ ? polygonAmoyUsdcAddress
50
+ : polygonMainnetUsdcAddress,
51
+ rpcEndpoint: useDevnet
52
+ ? common_js_1.tokenToDevGatewayMap.pol
53
+ : common_js_1.defaultProdGatewayUrls.pol,
54
+ defaultPollingOptions: polygon_js_1.defaultPolygonPollingOptions,
55
+ },
56
+ });
57
+ exports.usdcNetworks = usdcNetworks;
58
+ const ethMainnetUsdcAddress = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
59
+ const baseMainnetUsdcAddress = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
60
+ const polygonMainnetUsdcAddress = '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359';
61
+ const ethSepoliaUsdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238';
62
+ const baseSepoliaUsdcAddress = '0x036CbD53842c5426634e7929541eC2318f3dCF7e';
63
+ const polygonAmoyUsdcAddress = '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582';
64
+ const mUSDCToTokenAmount = (mUSDC) => mUSDC;
65
+ exports.mUSDCToTokenAmount = mUSDCToTokenAmount;
66
+ const USDCToTokenAmount = (usdc) => new bignumber_js_1.BigNumber(usdc).times(1e6).valueOf();
67
+ exports.USDCToTokenAmount = USDCToTokenAmount;
68
+ class USDCToken extends erc20_js_1.ERC20Token {
69
+ constructor({ network = 'ethereum', logger, gatewayUrl, tokenContractAddress, pollingOptions, useDevnet, } = {}) {
70
+ if (useDevnet === undefined) {
71
+ const keywords = ['sepolia', 'amoy'];
72
+ useDevnet = keywords.some((keyword) => (gatewayUrl ?? '').toLowerCase().includes(keyword));
73
+ }
74
+ const { tokenContractAddress: usdcContractAddress, rpcEndpoint, defaultPollingOptions, } = (0, exports.usdcNetworks)(useDevnet)[network];
75
+ super({
76
+ tokenContractAddress: tokenContractAddress ?? usdcContractAddress,
77
+ logger,
78
+ gatewayUrl: gatewayUrl ?? rpcEndpoint,
79
+ pollingOptions: pollingOptions ?? defaultPollingOptions,
80
+ });
81
+ }
82
+ }
83
+ exports.USDCToken = USDCToken;
@@ -94,7 +94,12 @@ exports.TurboUnauthenticatedUploadService = TurboUnauthenticatedUploadService;
94
94
  class TurboAuthenticatedBaseUploadService extends TurboUnauthenticatedUploadService {
95
95
  constructor({ url = exports.defaultUploadServiceURL, retryConfig, signer, logger, token, paymentService, }) {
96
96
  super({ url, retryConfig, logger, token });
97
- this.enabledOnDemandTokens = ['ario', 'solana', 'base-eth'];
97
+ this.enabledOnDemandTokens = [
98
+ 'ario',
99
+ 'solana',
100
+ 'base-eth',
101
+ 'base-usdc',
102
+ ];
98
103
  this.signer = signer;
99
104
  this.paymentService = paymentService;
100
105
  }
package/lib/cjs/types.js CHANGED
@@ -31,6 +31,9 @@ exports.tokenTypes = [
31
31
  'matic',
32
32
  'pol',
33
33
  'base-eth',
34
+ 'usdc',
35
+ 'base-usdc',
36
+ 'polygon-usdc',
34
37
  ];
35
38
  class ExistingBalanceFunding {
36
39
  }