@ardrive/turbo-sdk 1.19.2 → 1.20.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.
- package/README.md +123 -1
- package/bundles/web.bundle.min.js +148 -14
- package/lib/cjs/cli/cli.js +18 -0
- package/lib/cjs/cli/commands/balance.js +26 -15
- package/lib/cjs/cli/commands/cryptoFund.js +3 -1
- package/lib/cjs/cli/commands/listShares.js +58 -0
- package/lib/cjs/cli/commands/price.js +2 -1
- package/lib/cjs/cli/commands/revokeCredits.js +15 -0
- package/lib/cjs/cli/commands/shareCredits.js +39 -0
- package/lib/cjs/cli/commands/uploadFile.js +2 -1
- package/lib/cjs/cli/commands/uploadFolder.js +2 -1
- package/lib/cjs/cli/constants.js +2 -1
- package/lib/cjs/cli/options.js +43 -4
- package/lib/cjs/cli/utils.js +31 -0
- package/lib/cjs/common/payment.js +30 -4
- package/lib/cjs/common/token/solana.js +2 -2
- package/lib/cjs/common/turbo.js +31 -2
- package/lib/cjs/common/upload.js +73 -6
- package/lib/cjs/version.js +1 -1
- package/lib/esm/cli/cli.js +19 -1
- package/lib/esm/cli/commands/balance.js +26 -15
- package/lib/esm/cli/commands/cryptoFund.js +3 -1
- package/lib/esm/cli/commands/listShares.js +55 -0
- package/lib/esm/cli/commands/price.js +2 -1
- package/lib/esm/cli/commands/revokeCredits.js +12 -0
- package/lib/esm/cli/commands/shareCredits.js +36 -0
- package/lib/esm/cli/commands/uploadFile.js +3 -2
- package/lib/esm/cli/commands/uploadFolder.js +3 -2
- package/lib/esm/cli/constants.js +1 -0
- package/lib/esm/cli/options.js +42 -3
- package/lib/esm/cli/utils.js +30 -0
- package/lib/esm/common/payment.js +30 -4
- package/lib/esm/common/token/solana.js +2 -2
- package/lib/esm/common/turbo.js +31 -2
- package/lib/esm/common/upload.js +72 -5
- package/lib/esm/version.js +1 -1
- package/lib/types/cli/commands/balance.d.ts.map +1 -1
- package/lib/types/cli/commands/cryptoFund.d.ts.map +1 -1
- package/lib/types/cli/commands/listShares.d.ts +3 -0
- package/lib/types/cli/commands/listShares.d.ts.map +1 -0
- package/lib/types/cli/commands/price.d.ts.map +1 -1
- package/lib/types/cli/commands/revokeCredits.d.ts +18 -0
- package/lib/types/cli/commands/revokeCredits.d.ts.map +1 -0
- package/lib/types/cli/commands/shareCredits.d.ts +3 -0
- package/lib/types/cli/commands/shareCredits.d.ts.map +1 -0
- package/lib/types/cli/commands/uploadFile.d.ts.map +1 -1
- package/lib/types/cli/commands/uploadFolder.d.ts.map +1 -1
- package/lib/types/cli/constants.d.ts +1 -0
- package/lib/types/cli/constants.d.ts.map +1 -1
- package/lib/types/cli/options.d.ts +121 -2
- package/lib/types/cli/options.d.ts.map +1 -1
- package/lib/types/cli/types.d.ts +17 -2
- package/lib/types/cli/types.d.ts.map +1 -1
- package/lib/types/cli/utils.d.ts +2 -1
- package/lib/types/cli/utils.d.ts.map +1 -1
- package/lib/types/common/payment.d.ts +8 -2
- package/lib/types/common/payment.d.ts.map +1 -1
- package/lib/types/common/token/solana.d.ts.map +1 -1
- package/lib/types/common/turbo.d.ts +27 -2
- package/lib/types/common/turbo.d.ts.map +1 -1
- package/lib/types/common/upload.d.ts +9 -1
- package/lib/types/common/upload.d.ts.map +1 -1
- package/lib/types/types.d.ts +54 -3
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/utils/axiosClient.d.ts.map +1 -1
- package/lib/types/version.d.ts +1 -1
- package/package.json +4 -3
@@ -25,11 +25,12 @@ async function uploadFile(options) {
|
|
25
25
|
throw new Error('Must provide a --file-path to upload');
|
26
26
|
}
|
27
27
|
const turbo = await (0, utils_js_1.turboFromOptions)(options);
|
28
|
+
const paidBy = await (0, utils_js_1.paidByFromOptions)(options, turbo);
|
28
29
|
const fileSize = (0, fs_1.statSync)(filePath).size;
|
29
30
|
const result = await turbo.uploadFile({
|
30
31
|
fileStreamFactory: () => (0, fs_1.createReadStream)(filePath),
|
31
32
|
fileSizeFactory: () => fileSize,
|
32
|
-
dataItemOpts: { tags: [...constants_js_1.turboCliTags] }, // TODO: Inject user tags
|
33
|
+
dataItemOpts: { tags: [...constants_js_1.turboCliTags], paidBy }, // TODO: Inject user tags
|
33
34
|
});
|
34
35
|
console.log('Uploaded file:', JSON.stringify(result, null, 2));
|
35
36
|
}
|
@@ -20,10 +20,11 @@ const constants_js_1 = require("../constants.js");
|
|
20
20
|
const utils_js_1 = require("../utils.js");
|
21
21
|
async function uploadFolder(options) {
|
22
22
|
const turbo = await (0, utils_js_1.turboFromOptions)(options);
|
23
|
+
const paidBy = await (0, utils_js_1.paidByFromOptions)(options, turbo);
|
23
24
|
const { disableManifest, fallbackFile, folderPath, indexFile, maxConcurrentUploads, } = (0, utils_js_1.getUploadFolderOptions)(options);
|
24
25
|
const result = await turbo.uploadFolder({
|
25
26
|
folderPath: folderPath,
|
26
|
-
dataItemOpts: { tags: [...constants_js_1.turboCliTags] }, // TODO: Inject user tags
|
27
|
+
dataItemOpts: { tags: [...constants_js_1.turboCliTags], paidBy }, // TODO: Inject user tags
|
27
28
|
manifestOptions: {
|
28
29
|
disableManifest,
|
29
30
|
indexFile,
|
package/lib/cjs/cli/constants.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.turboCliTags = void 0;
|
3
|
+
exports.wincPerCredit = exports.turboCliTags = void 0;
|
4
4
|
/**
|
5
5
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
6
6
|
*
|
@@ -22,3 +22,4 @@ exports.turboCliTags = [
|
|
22
22
|
{ name: 'App-Version', value: version_js_1.version },
|
23
23
|
{ name: 'App-Platform', value: process.platform },
|
24
24
|
];
|
25
|
+
exports.wincPerCredit = 1_000_000_000_000;
|
package/lib/cjs/cli/options.js
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
* limitations under the License.
|
16
16
|
*/
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
|
-
exports.uploadFileOptions = exports.uploadFolderOptions = exports.globalOptions = exports.walletOptions = exports.optionMap = void 0;
|
18
|
+
exports.listSharesOptions = exports.revokeCreditsOptions = exports.shareCreditsOptions = exports.uploadFileOptions = exports.uploadFolderOptions = exports.uploadOptions = exports.globalOptions = exports.walletOptions = exports.optionMap = void 0;
|
19
19
|
exports.optionMap = {
|
20
20
|
token: {
|
21
21
|
alias: '-t, --token <type>',
|
@@ -73,7 +73,12 @@ exports.optionMap = {
|
|
73
73
|
},
|
74
74
|
dev: {
|
75
75
|
alias: '--dev',
|
76
|
-
description: 'Enable development endpoints',
|
76
|
+
description: 'Enable Turbo development endpoints',
|
77
|
+
default: false,
|
78
|
+
},
|
79
|
+
local: {
|
80
|
+
alias: '--local',
|
81
|
+
description: 'Enable local development endpoints',
|
77
82
|
default: false,
|
78
83
|
},
|
79
84
|
debug: {
|
@@ -118,6 +123,25 @@ exports.optionMap = {
|
|
118
123
|
alias: '--max-concurrency <maxConcurrency>',
|
119
124
|
description: 'Maximum number of concurrent uploads',
|
120
125
|
},
|
126
|
+
paidBy: {
|
127
|
+
alias: '--paid-by <paidBy...>',
|
128
|
+
description: 'Address to pay for the upload',
|
129
|
+
type: 'array',
|
130
|
+
},
|
131
|
+
expiresBySeconds: {
|
132
|
+
alias: '--expires-by-seconds <expiresBySeconds>',
|
133
|
+
description: 'Expiration time in seconds',
|
134
|
+
},
|
135
|
+
ignoreApprovals: {
|
136
|
+
alias: '--ignore-approvals',
|
137
|
+
description: "Ignore all credit share approvals, only use signing wallet's balance",
|
138
|
+
default: false,
|
139
|
+
},
|
140
|
+
useSignerBalanceFirst: {
|
141
|
+
alias: '--use-signer-balance-first',
|
142
|
+
description: 'Use the signer balance first before using credit share approvals',
|
143
|
+
default: false,
|
144
|
+
},
|
121
145
|
};
|
122
146
|
exports.walletOptions = [
|
123
147
|
exports.optionMap.walletFile,
|
@@ -126,6 +150,7 @@ exports.walletOptions = [
|
|
126
150
|
];
|
127
151
|
exports.globalOptions = [
|
128
152
|
exports.optionMap.dev,
|
153
|
+
exports.optionMap.local,
|
129
154
|
exports.optionMap.gateway,
|
130
155
|
exports.optionMap.debug,
|
131
156
|
exports.optionMap.quiet,
|
@@ -134,12 +159,26 @@ exports.globalOptions = [
|
|
134
159
|
exports.optionMap.paymentUrl,
|
135
160
|
exports.optionMap.uploadUrl,
|
136
161
|
];
|
137
|
-
exports.
|
162
|
+
exports.uploadOptions = [
|
138
163
|
...exports.walletOptions,
|
164
|
+
exports.optionMap.paidBy,
|
165
|
+
exports.optionMap.ignoreApprovals,
|
166
|
+
exports.optionMap.useSignerBalanceFirst,
|
167
|
+
];
|
168
|
+
exports.uploadFolderOptions = [
|
169
|
+
...exports.uploadOptions,
|
139
170
|
exports.optionMap.folderPath,
|
140
171
|
exports.optionMap.indexFile,
|
141
172
|
exports.optionMap.fallbackFile,
|
142
173
|
exports.optionMap.manifest,
|
143
174
|
exports.optionMap.maxConcurrency,
|
144
175
|
];
|
145
|
-
exports.uploadFileOptions = [...exports.
|
176
|
+
exports.uploadFileOptions = [...exports.uploadOptions, exports.optionMap.filePath];
|
177
|
+
exports.shareCreditsOptions = [
|
178
|
+
...exports.walletOptions,
|
179
|
+
exports.optionMap.value,
|
180
|
+
exports.optionMap.address,
|
181
|
+
exports.optionMap.expiresBySeconds,
|
182
|
+
];
|
183
|
+
exports.revokeCreditsOptions = [...exports.walletOptions, exports.optionMap.address];
|
184
|
+
exports.listSharesOptions = exports.revokeCreditsOptions;
|
package/lib/cjs/cli/utils.js
CHANGED
@@ -14,6 +14,7 @@ exports.optionalPrivateKeyFromOptions = optionalPrivateKeyFromOptions;
|
|
14
14
|
exports.privateKeyFromOptions = privateKeyFromOptions;
|
15
15
|
exports.configFromOptions = configFromOptions;
|
16
16
|
exports.turboFromOptions = turboFromOptions;
|
17
|
+
exports.paidByFromOptions = paidByFromOptions;
|
17
18
|
exports.getUploadFolderOptions = getUploadFolderOptions;
|
18
19
|
/**
|
19
20
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
@@ -138,12 +139,21 @@ function configFromOptions(options) {
|
|
138
139
|
let paymentUrl = undefined;
|
139
140
|
let uploadUrl = undefined;
|
140
141
|
let gatewayUrl = undefined;
|
142
|
+
if (options.local && options.dev) {
|
143
|
+
throw new Error('Cannot use both --local and --dev flags');
|
144
|
+
}
|
141
145
|
if (options.dev) {
|
142
146
|
// Use development endpoints
|
143
147
|
paymentUrl = index_js_1.developmentTurboConfiguration.paymentServiceConfig.url;
|
144
148
|
uploadUrl = index_js_1.developmentTurboConfiguration.uploadServiceConfig.url;
|
145
149
|
gatewayUrl = tokenToDevGatewayMap[token];
|
146
150
|
}
|
151
|
+
else if (options.local) {
|
152
|
+
// Use local endpoints
|
153
|
+
paymentUrl = 'http://localhost:4000';
|
154
|
+
uploadUrl = 'http://localhost:3000';
|
155
|
+
gatewayUrl = 'http://localhost:1984';
|
156
|
+
}
|
147
157
|
else {
|
148
158
|
// Use default endpoints
|
149
159
|
paymentUrl = index_js_1.defaultTurboConfiguration.paymentServiceConfig.url;
|
@@ -174,6 +184,27 @@ async function turboFromOptions(options) {
|
|
174
184
|
privateKey,
|
175
185
|
});
|
176
186
|
}
|
187
|
+
async function paidByFromOptions({ paidBy: paidByCliInput, ignoreApprovals, useSignerBalanceFirst, }, turbo) {
|
188
|
+
const paidBy = await (async () => {
|
189
|
+
if (paidByCliInput !== undefined && paidByCliInput.length > 0) {
|
190
|
+
return paidByCliInput;
|
191
|
+
}
|
192
|
+
if (ignoreApprovals) {
|
193
|
+
return undefined;
|
194
|
+
}
|
195
|
+
const { receivedApprovals } = await turbo.getBalance();
|
196
|
+
if (receivedApprovals !== undefined && receivedApprovals.length !== 0) {
|
197
|
+
// get unique paying addresses from any received approvals
|
198
|
+
return Array.from(new Set(receivedApprovals.map((approval) => approval.payingAddress)));
|
199
|
+
}
|
200
|
+
return undefined;
|
201
|
+
})();
|
202
|
+
if (paidBy !== undefined && useSignerBalanceFirst) {
|
203
|
+
// Add the signer's address to the front of the paidBy array
|
204
|
+
paidBy.unshift(await turbo.signer.getNativeAddress());
|
205
|
+
}
|
206
|
+
return paidBy;
|
207
|
+
}
|
177
208
|
function getUploadFolderOptions(options) {
|
178
209
|
if (options.folderPath === undefined) {
|
179
210
|
throw new Error('--folder-path is required');
|
@@ -37,7 +37,15 @@ class TurboUnauthenticatedPaymentService {
|
|
37
37
|
endpoint: `/account/balance/${this.token}?address=${address}`,
|
38
38
|
allowedStatuses: [200, 404],
|
39
39
|
});
|
40
|
-
return balance.winc
|
40
|
+
return balance.winc
|
41
|
+
? balance
|
42
|
+
: {
|
43
|
+
winc: '0',
|
44
|
+
controlledWinc: '0',
|
45
|
+
effectiveBalance: '0',
|
46
|
+
givenApprovals: [],
|
47
|
+
receivedApprovals: [],
|
48
|
+
};
|
41
49
|
}
|
42
50
|
getFiatRates() {
|
43
51
|
return this.httpService.get({
|
@@ -156,6 +164,20 @@ class TurboUnauthenticatedPaymentService {
|
|
156
164
|
}
|
157
165
|
throw new Error('Unknown response from payment service: ' + response);
|
158
166
|
}
|
167
|
+
async getCreditShareApprovals({ userAddress, }) {
|
168
|
+
const response = await this.httpService.get({
|
169
|
+
endpoint: `/account/approvals/get?userAddress=${userAddress}`,
|
170
|
+
allowedStatuses: [200, 404],
|
171
|
+
});
|
172
|
+
if (response?.givenApprovals === undefined &&
|
173
|
+
response?.receivedApprovals === undefined) {
|
174
|
+
return {
|
175
|
+
givenApprovals: [],
|
176
|
+
receivedApprovals: [],
|
177
|
+
};
|
178
|
+
}
|
179
|
+
return response;
|
180
|
+
}
|
159
181
|
}
|
160
182
|
exports.TurboUnauthenticatedPaymentService = TurboUnauthenticatedPaymentService;
|
161
183
|
// NOTE: to avoid redundancy, we use inheritance here - but generally prefer composition over inheritance
|
@@ -165,9 +187,13 @@ class TurboAuthenticatedPaymentService extends TurboUnauthenticatedPaymentServic
|
|
165
187
|
this.signer = signer;
|
166
188
|
this.tokenTools = tokenTools;
|
167
189
|
}
|
168
|
-
async getBalance(
|
169
|
-
|
170
|
-
return super.getBalance(
|
190
|
+
async getBalance(userAddress) {
|
191
|
+
userAddress ??= await this.signer.getNativeAddress();
|
192
|
+
return super.getBalance(userAddress);
|
193
|
+
}
|
194
|
+
async getCreditShareApprovals({ userAddress, }) {
|
195
|
+
userAddress ??= await this.signer.getNativeAddress();
|
196
|
+
return super.getCreditShareApprovals({ userAddress });
|
171
197
|
}
|
172
198
|
async getWincForFiat({ amount, promoCodes = [], }) {
|
173
199
|
return super.getWincForFiat({
|
@@ -41,7 +41,7 @@ class SolanaToken {
|
|
41
41
|
this.pollingOptions = pollingOptions;
|
42
42
|
}
|
43
43
|
async createAndSubmitTx({ target, tokenAmount, signer, }) {
|
44
|
-
const publicKey = new web3_js_1.PublicKey(bs58_1.default.encode(await signer.getPublicKey()));
|
44
|
+
const publicKey = new web3_js_1.PublicKey(bs58_1.default.encode(Uint8Array.from(await signer.getPublicKey())));
|
45
45
|
const tx = new web3_js_1.Transaction({
|
46
46
|
feePayer: publicKey,
|
47
47
|
...(await this.connection.getLatestBlockhash()),
|
@@ -52,7 +52,7 @@ class SolanaToken {
|
|
52
52
|
lamports: +new bignumber_js_1.BigNumber(tokenAmount),
|
53
53
|
}));
|
54
54
|
const serializedTx = tx.serializeMessage();
|
55
|
-
const signature = await signer.signData(serializedTx);
|
55
|
+
const signature = await signer.signData(Uint8Array.from(serializedTx));
|
56
56
|
tx.addSignature(publicKey, node_buffer_1.Buffer.from(signature));
|
57
57
|
const id = bs58_1.default.encode(signature);
|
58
58
|
await this.submitTx(tx, id);
|
package/lib/cjs/common/turbo.js
CHANGED
@@ -108,6 +108,12 @@ class TurboUnauthenticatedClient {
|
|
108
108
|
wallets.pol = wallets.matic;
|
109
109
|
return wallets;
|
110
110
|
}
|
111
|
+
/**
|
112
|
+
* Returns a list of all credit share approvals for the user.
|
113
|
+
*/
|
114
|
+
getCreditShareApprovals(p) {
|
115
|
+
return this.paymentService.getCreditShareApprovals(p);
|
116
|
+
}
|
111
117
|
}
|
112
118
|
exports.TurboUnauthenticatedClient = TurboUnauthenticatedClient;
|
113
119
|
class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
|
@@ -118,8 +124,14 @@ class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
|
|
118
124
|
/**
|
119
125
|
* Returns the current balance of the user's wallet in 'winc'.
|
120
126
|
*/
|
121
|
-
getBalance(
|
122
|
-
return this.paymentService.getBalance(
|
127
|
+
getBalance(userAddress) {
|
128
|
+
return this.paymentService.getBalance(userAddress);
|
129
|
+
}
|
130
|
+
/**
|
131
|
+
* Returns a list of all credit share approvals for the user.
|
132
|
+
*/
|
133
|
+
getCreditShareApprovals(p = {}) {
|
134
|
+
return this.paymentService.getCreditShareApprovals(p);
|
123
135
|
}
|
124
136
|
/**
|
125
137
|
* Signs and uploads raw data to the Turbo Upload Service.
|
@@ -142,5 +154,22 @@ class TurboAuthenticatedClient extends TurboUnauthenticatedClient {
|
|
142
154
|
topUpWithTokens(p) {
|
143
155
|
return this.paymentService.topUpWithTokens(p);
|
144
156
|
}
|
157
|
+
/**
|
158
|
+
* Creates a data item with tags that designate it as a credit share approval.
|
159
|
+
* Signs the data item and sends it to the Turbo Upload Service, which will verify
|
160
|
+
* the signature and forward the admin action towards the Turbo Payment Service.
|
161
|
+
*/
|
162
|
+
shareCredits(p) {
|
163
|
+
return this.uploadService.shareCredits(p);
|
164
|
+
}
|
165
|
+
/**
|
166
|
+
* Creates a data item with tags that designate it as a revoke action for credit
|
167
|
+
* share approvals for target revokedAddress. Signs the data item and sends it to
|
168
|
+
* the Turbo Upload Service, which will verify the signature and forward the admin
|
169
|
+
* action towards the Turbo Payment Service.
|
170
|
+
*/
|
171
|
+
revokeCredits(p) {
|
172
|
+
return this.uploadService.revokeCredits(p);
|
173
|
+
}
|
145
174
|
}
|
146
175
|
exports.TurboAuthenticatedClient = TurboAuthenticatedClient;
|
package/lib/cjs/common/upload.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.TurboAuthenticatedBaseUploadService = exports.TurboUnauthenticatedUploadService = exports.defaultUploadServiceURL = exports.developmentUploadServiceURL = void 0;
|
3
|
+
exports.TurboAuthenticatedBaseUploadService = exports.TurboUnauthenticatedUploadService = exports.defaultUploadServiceURL = exports.developmentUploadServiceURL = exports.creditSharingTagNames = void 0;
|
4
4
|
/**
|
5
5
|
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
6
6
|
*
|
@@ -17,9 +17,16 @@ exports.TurboAuthenticatedBaseUploadService = exports.TurboUnauthenticatedUpload
|
|
17
17
|
* limitations under the License.
|
18
18
|
*/
|
19
19
|
const node_buffer_1 = require("node:buffer");
|
20
|
+
const node_stream_1 = require("node:stream");
|
20
21
|
const plimit_lit_1 = require("plimit-lit");
|
21
22
|
const http_js_1 = require("./http.js");
|
22
23
|
const logger_js_1 = require("./logger.js");
|
24
|
+
exports.creditSharingTagNames = {
|
25
|
+
shareCredits: 'x-approve-payment',
|
26
|
+
sharedWincAmount: 'x-amount',
|
27
|
+
approvalExpiresBySeconds: 'x-expires-seconds',
|
28
|
+
revokeCredits: 'x-delete-payment-approval',
|
29
|
+
};
|
23
30
|
exports.developmentUploadServiceURL = 'https://upload.ardrive.dev';
|
24
31
|
exports.defaultUploadServiceURL = 'https://upload.ardrive.io';
|
25
32
|
class TurboUnauthenticatedUploadService {
|
@@ -61,17 +68,25 @@ class TurboAuthenticatedBaseUploadService extends TurboUnauthenticatedUploadServ
|
|
61
68
|
dataItemOpts,
|
62
69
|
});
|
63
70
|
const signedDataItem = dataItemStreamFactory();
|
64
|
-
const fileSize = dataItemSizeFactory();
|
65
71
|
this.logger.debug('Uploading signed data item...');
|
66
72
|
// TODO: add p-limit constraint or replace with separate upload class
|
73
|
+
const headers = {
|
74
|
+
'content-type': 'application/octet-stream',
|
75
|
+
'content-length': `${dataItemSizeFactory()}`,
|
76
|
+
};
|
77
|
+
if (dataItemOpts !== undefined && dataItemOpts.paidBy !== undefined) {
|
78
|
+
const paidBy = Array.isArray(dataItemOpts.paidBy)
|
79
|
+
? dataItemOpts.paidBy
|
80
|
+
: [dataItemOpts.paidBy];
|
81
|
+
if (dataItemOpts.paidBy.length > 0) {
|
82
|
+
headers['x-paid-by'] = paidBy;
|
83
|
+
}
|
84
|
+
}
|
67
85
|
return this.httpService.post({
|
68
86
|
endpoint: `/tx/${this.token}`,
|
69
87
|
signal,
|
70
88
|
data: signedDataItem,
|
71
|
-
headers
|
72
|
-
'content-type': 'application/octet-stream',
|
73
|
-
'content-length': `${fileSize}`,
|
74
|
-
},
|
89
|
+
headers,
|
75
90
|
});
|
76
91
|
}
|
77
92
|
async generateManifest({ paths, indexFile, fallbackFile, }) {
|
@@ -182,5 +197,57 @@ class TurboAuthenticatedBaseUploadService extends TurboUnauthenticatedUploadServ
|
|
182
197
|
manifestResponse,
|
183
198
|
};
|
184
199
|
}
|
200
|
+
async shareCredits({ approvedAddress, approvedWincAmount, expiresBySeconds, }) {
|
201
|
+
const dataItemOpts = {
|
202
|
+
tags: [
|
203
|
+
{
|
204
|
+
name: exports.creditSharingTagNames.shareCredits,
|
205
|
+
value: approvedAddress,
|
206
|
+
},
|
207
|
+
{
|
208
|
+
name: exports.creditSharingTagNames.sharedWincAmount,
|
209
|
+
value: approvedWincAmount.toString(),
|
210
|
+
},
|
211
|
+
],
|
212
|
+
};
|
213
|
+
if (expiresBySeconds !== undefined) {
|
214
|
+
dataItemOpts.tags.push({
|
215
|
+
name: exports.creditSharingTagNames.approvalExpiresBySeconds,
|
216
|
+
value: expiresBySeconds.toString(),
|
217
|
+
});
|
218
|
+
}
|
219
|
+
const nonceData = node_buffer_1.Buffer.from(approvedAddress + approvedWincAmount + Date.now());
|
220
|
+
const { createdApproval, ...uploadResponse } = await this.uploadFile({
|
221
|
+
fileStreamFactory: () => node_stream_1.Readable.from(nonceData),
|
222
|
+
fileSizeFactory: () => nonceData.byteLength,
|
223
|
+
dataItemOpts,
|
224
|
+
});
|
225
|
+
if (!createdApproval) {
|
226
|
+
throw new Error('Failed to create credit share approval but upload has succeeded\n' +
|
227
|
+
JSON.stringify(uploadResponse));
|
228
|
+
}
|
229
|
+
return createdApproval;
|
230
|
+
}
|
231
|
+
async revokeCredits({ revokedAddress, }) {
|
232
|
+
const dataItemOpts = {
|
233
|
+
tags: [
|
234
|
+
{
|
235
|
+
name: exports.creditSharingTagNames.revokeCredits,
|
236
|
+
value: revokedAddress,
|
237
|
+
},
|
238
|
+
],
|
239
|
+
};
|
240
|
+
const nonceData = node_buffer_1.Buffer.from(revokedAddress + Date.now());
|
241
|
+
const { revokedApprovals, ...uploadResponse } = await this.uploadFile({
|
242
|
+
fileStreamFactory: () => node_stream_1.Readable.from(nonceData),
|
243
|
+
fileSizeFactory: () => nonceData.byteLength,
|
244
|
+
dataItemOpts,
|
245
|
+
});
|
246
|
+
if (!revokedApprovals) {
|
247
|
+
throw new Error('Failed to revoke credit share approvals but upload has succeeded\n' +
|
248
|
+
JSON.stringify(uploadResponse));
|
249
|
+
}
|
250
|
+
return revokedApprovals;
|
251
|
+
}
|
185
252
|
}
|
186
253
|
exports.TurboAuthenticatedBaseUploadService = TurboAuthenticatedBaseUploadService;
|
package/lib/cjs/version.js
CHANGED
package/lib/esm/cli/cli.js
CHANGED
@@ -19,7 +19,10 @@
|
|
19
19
|
import { program } from 'commander';
|
20
20
|
import { version } from '../version.js';
|
21
21
|
import { balance, cryptoFund, price, topUp, uploadFile, uploadFolder, } from './commands/index.js';
|
22
|
-
import {
|
22
|
+
import { listShares } from './commands/listShares.js';
|
23
|
+
import { revokeCredits } from './commands/revokeCredits.js';
|
24
|
+
import { shareCredits } from './commands/shareCredits.js';
|
25
|
+
import { globalOptions, listSharesOptions, optionMap, revokeCreditsOptions, shareCreditsOptions, uploadFileOptions, uploadFolderOptions, walletOptions, } from './options.js';
|
23
26
|
import { applyOptions, runCommand } from './utils.js';
|
24
27
|
applyOptions(program
|
25
28
|
.name('turbo')
|
@@ -46,6 +49,21 @@ applyOptions(program
|
|
46
49
|
.description('Get the current Credits estimate for byte, crypto, or fiat value'), [optionMap.value, optionMap.type]).action(async (_commandOptions, command) => {
|
47
50
|
await runCommand(command, price);
|
48
51
|
});
|
52
|
+
applyOptions(program
|
53
|
+
.command('share-credits')
|
54
|
+
.description('Create a Turbo credit share approval'), shareCreditsOptions).action(async (_commandOptions, command) => {
|
55
|
+
await runCommand(command, shareCredits);
|
56
|
+
});
|
57
|
+
applyOptions(program
|
58
|
+
.command('revoke-credits')
|
59
|
+
.description('Revokes all Turbo credit share approvals for given address'), revokeCreditsOptions).action(async (_commandOptions, command) => {
|
60
|
+
await runCommand(command, revokeCredits);
|
61
|
+
});
|
62
|
+
applyOptions(program
|
63
|
+
.command('list-shares')
|
64
|
+
.description('Lists all given or received Turbo credit share approvals for specified address or connected wallet'), listSharesOptions).action(async (_commandOptions, command) => {
|
65
|
+
await runCommand(command, listShares);
|
66
|
+
});
|
49
67
|
if (process.argv[1].includes('bin/turbo') || // Running from global .bin
|
50
68
|
process.argv[1].includes('cli/cli') // Running from source
|
51
69
|
) {
|
@@ -13,24 +13,35 @@
|
|
13
13
|
* See the License for the specific language governing permissions and
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
|
+
import { BigNumber } from 'bignumber.js';
|
16
17
|
import { TurboFactory } from '../../node/factory.js';
|
18
|
+
import { wincPerCredit } from '../constants.js';
|
17
19
|
import { addressOrPrivateKeyFromOptions, configFromOptions } from '../utils.js';
|
18
20
|
export async function balance(options) {
|
19
21
|
const config = configFromOptions(options);
|
20
22
|
const { address, privateKey } = await addressOrPrivateKeyFromOptions(options);
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
const { effectiveBalance, nativeAddress, winc, controlledWinc } = await (async () => {
|
24
|
+
if (address !== undefined) {
|
25
|
+
return {
|
26
|
+
...(await TurboFactory.unauthenticated(config).getBalance(address)),
|
27
|
+
nativeAddress: address,
|
28
|
+
};
|
29
|
+
}
|
30
|
+
if (privateKey === undefined) {
|
31
|
+
throw new Error('Must provide an (--address) or use a valid wallet');
|
32
|
+
}
|
33
|
+
const turbo = TurboFactory.authenticated({
|
34
|
+
...config,
|
35
|
+
privateKey,
|
36
|
+
});
|
37
|
+
return {
|
38
|
+
...(await turbo.getBalance()),
|
39
|
+
nativeAddress: await turbo.signer.getNativeAddress(),
|
40
|
+
};
|
41
|
+
})();
|
42
|
+
console.log(`Turbo Balance for Native Address "${nativeAddress}"\nEffective Credits: ${+effectiveBalance / wincPerCredit}${winc === controlledWinc
|
43
|
+
? ''
|
44
|
+
: `\nCredits Shared to Other Wallets: ${BigNumber(controlledWinc)
|
45
|
+
.minus(winc)
|
46
|
+
.div(wincPerCredit)}`}`);
|
36
47
|
}
|
@@ -13,9 +13,11 @@
|
|
13
13
|
* See the License for the specific language governing permissions and
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
|
+
import { BigNumber } from 'bignumber.js';
|
16
17
|
import prompts from 'prompts';
|
17
18
|
import { tokenToBaseMap } from '../../common/index.js';
|
18
19
|
import { TurboFactory } from '../../node/factory.js';
|
20
|
+
import { wincPerCredit } from '../constants.js';
|
19
21
|
import { configFromOptions, tokenFromOptions, turboFromOptions, } from '../utils.js';
|
20
22
|
export async function cryptoFund(options) {
|
21
23
|
const value = options.value;
|
@@ -35,7 +37,7 @@ export async function cryptoFund(options) {
|
|
35
37
|
if (!options.skipConfirmation) {
|
36
38
|
const { winc } = await turbo.getWincForToken({ tokenAmount });
|
37
39
|
const targetWallet = (await turbo.getTurboCryptoWallets())[token];
|
38
|
-
const credits = (
|
40
|
+
const credits = BigNumber(winc).dividedBy(wincPerCredit).toFixed(12);
|
39
41
|
const { confirm } = await prompts({
|
40
42
|
type: 'confirm',
|
41
43
|
name: 'confirm',
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
import { TurboFactory } from '../../node/factory.js';
|
17
|
+
import { addressOrPrivateKeyFromOptions, configFromOptions } from '../utils.js';
|
18
|
+
export async function listShares(options) {
|
19
|
+
const config = configFromOptions(options);
|
20
|
+
const { address, privateKey } = await addressOrPrivateKeyFromOptions(options);
|
21
|
+
const { givenApprovals, receivedApprovals, nativeAddress } = await (async () => {
|
22
|
+
if (address !== undefined) {
|
23
|
+
const approvals = await TurboFactory.unauthenticated(config).getCreditShareApprovals({
|
24
|
+
userAddress: address,
|
25
|
+
});
|
26
|
+
return { ...approvals, nativeAddress: address };
|
27
|
+
}
|
28
|
+
if (privateKey === undefined) {
|
29
|
+
throw new Error('Must provide an (--address) or use a valid wallet');
|
30
|
+
}
|
31
|
+
const turbo = TurboFactory.authenticated({
|
32
|
+
...config,
|
33
|
+
privateKey,
|
34
|
+
});
|
35
|
+
const approvals = await turbo.getCreditShareApprovals();
|
36
|
+
return {
|
37
|
+
...approvals,
|
38
|
+
nativeAddress: await turbo.signer.getNativeAddress(),
|
39
|
+
};
|
40
|
+
})();
|
41
|
+
const hasApprovals = givenApprovals?.length === 0 && receivedApprovals?.length === 0;
|
42
|
+
const body = {
|
43
|
+
message: `${hasApprovals ? 'No ' : ''}` +
|
44
|
+
`Credit Share Approvals found for native address '${nativeAddress}'`,
|
45
|
+
givenApprovals,
|
46
|
+
receivedApprovals,
|
47
|
+
};
|
48
|
+
if (givenApprovals?.length > 0) {
|
49
|
+
body['givenApprovals'] = givenApprovals;
|
50
|
+
}
|
51
|
+
if (receivedApprovals?.length > 0) {
|
52
|
+
body['receivedApprovals'] = receivedApprovals;
|
53
|
+
}
|
54
|
+
console.log(JSON.stringify(body, null, 2));
|
55
|
+
}
|
@@ -17,6 +17,7 @@ import { currencyMap } from '../../common/currency.js';
|
|
17
17
|
import { isTokenType, tokenToBaseMap } from '../../common/index.js';
|
18
18
|
import { TurboFactory } from '../../node/factory.js';
|
19
19
|
import { fiatCurrencyTypes, isCurrency, tokenTypes } from '../../types.js';
|
20
|
+
import { wincPerCredit } from '../constants.js';
|
20
21
|
import { configFromOptions } from '../utils.js';
|
21
22
|
export async function price(options) {
|
22
23
|
const value = options.value;
|
@@ -45,5 +46,5 @@ export async function price(options) {
|
|
45
46
|
}
|
46
47
|
throw new Error(`Invalid price type!\nMust be one of: bytes, ${fiatCurrencyTypes.join(', ') + ' ' + tokenTypes.join(', ')}`);
|
47
48
|
})();
|
48
|
-
console.log(`Current price estimate for ${value} ${type} is ~${(+winc /
|
49
|
+
console.log(`Current price estimate for ${value} ${type} is ~${(+winc / wincPerCredit).toFixed(12)} Credits`);
|
49
50
|
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { turboFromOptions } from '../utils.js';
|
2
|
+
export async function revokeCredits(options) {
|
3
|
+
const { address: revokedAddress } = options;
|
4
|
+
if (revokedAddress === undefined) {
|
5
|
+
throw new Error('Must provide an approved --address to revoke approvals for');
|
6
|
+
}
|
7
|
+
const turbo = await turboFromOptions(options);
|
8
|
+
const revokedApprovals = await turbo.revokeCredits({
|
9
|
+
revokedAddress,
|
10
|
+
});
|
11
|
+
console.log(JSON.stringify({ message: 'Revoked credit share approvals!', revokedApprovals }, null, 2));
|
12
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
import { BigNumber } from 'bignumber.js';
|
17
|
+
import { turboFromOptions } from '../utils.js';
|
18
|
+
export async function shareCredits(options) {
|
19
|
+
const { address: approvedAddress, value: creditAmount, expiresBySeconds, } = options;
|
20
|
+
if (approvedAddress === undefined) {
|
21
|
+
throw new Error('Must provide an approved --address to create approval for');
|
22
|
+
}
|
23
|
+
if (creditAmount === undefined) {
|
24
|
+
throw new Error('Must provide a credit --value to create approval for');
|
25
|
+
}
|
26
|
+
const turbo = await turboFromOptions(options);
|
27
|
+
const approvedWincAmount = new BigNumber(creditAmount)
|
28
|
+
.shiftedBy(12)
|
29
|
+
.toFixed(0);
|
30
|
+
const result = await turbo.shareCredits({
|
31
|
+
approvedAddress,
|
32
|
+
approvedWincAmount,
|
33
|
+
expiresBySeconds,
|
34
|
+
});
|
35
|
+
console.log(JSON.stringify({ message: 'Created credit share approval!', ...result }, null, 2));
|
36
|
+
}
|