@ethernity-cloud/sdk-js 1.1.0
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/LICENSE +661 -0
- package/README.md +185 -0
- package/build.js +22 -0
- package/init.js +301 -0
- package/nodenithy/build/las/Dockerfile +5 -0
- package/nodenithy/build/securelock/Dockerfile.tmpl +65 -0
- package/nodenithy/build/securelock/scripts/binary-fs-build.sh +28 -0
- package/nodenithy/build/securelock/src/.env +3 -0
- package/nodenithy/build/securelock/src/etny_crypto.js +201 -0
- package/nodenithy/build/securelock/src/etny_exec.js +65 -0
- package/nodenithy/build/securelock/src/image_registry_abi.js +808 -0
- package/nodenithy/build/securelock/src/models.js +261 -0
- package/nodenithy/build/securelock/src/package.json +40 -0
- package/nodenithy/build/securelock/src/pox_abi.js +1491 -0
- package/nodenithy/build/securelock/src/securelock.js.tmpl +421 -0
- package/nodenithy/build/securelock/src/swift_stream_service.js +147 -0
- package/nodenithy/build/securelock/src/task_status.js +15 -0
- package/nodenithy/build/securelock/src/wallet.js +29 -0
- package/nodenithy/build/squash/Dockerfile +7 -0
- package/nodenithy/build/trustedzone/Dockerfile.tmpl +57 -0
- package/nodenithy/build/trustedzone/scripts/binary-fs-build.sh +22 -0
- package/nodenithy/build/trustedzone/src/.env +3 -0
- package/nodenithy/build/trustedzone/src/etny_crypto.js +202 -0
- package/nodenithy/build/trustedzone/src/etny_exec.js +54 -0
- package/nodenithy/build/trustedzone/src/image_registry_abi.js +808 -0
- package/nodenithy/build/trustedzone/src/models.js +261 -0
- package/nodenithy/build/trustedzone/src/package.json +40 -0
- package/nodenithy/build/trustedzone/src/pox_abi.js +1491 -0
- package/nodenithy/build/trustedzone/src/swift_stream_service.js +147 -0
- package/nodenithy/build/trustedzone/src/task_status.js +15 -0
- package/nodenithy/build/trustedzone/src/test.js +44 -0
- package/nodenithy/build/trustedzone/src/trustedzone.js.tmpl +508 -0
- package/nodenithy/build/trustedzone/src/wallet.js +28 -0
- package/nodenithy/build/validator/Dockerfile +58 -0
- package/nodenithy/build/validator/package-lock.json +6 -0
- package/nodenithy/build/validator/scripts/binary-fs-build.sh +19 -0
- package/nodenithy/build/validator/src/.env +3 -0
- package/nodenithy/build/validator/src/cert.pem +5 -0
- package/nodenithy/build/validator/src/etny_crypto.js +204 -0
- package/nodenithy/build/validator/src/etny_exec.js +52 -0
- package/nodenithy/build/validator/src/image_registry_abi.js +808 -0
- package/nodenithy/build/validator/src/key.pem +6 -0
- package/nodenithy/build/validator/src/models.js +261 -0
- package/nodenithy/build/validator/src/package-lock.json +2498 -0
- package/nodenithy/build/validator/src/package.json +40 -0
- package/nodenithy/build/validator/src/pox_abi.js +1491 -0
- package/nodenithy/build/validator/src/swift_stream_service.js +147 -0
- package/nodenithy/build/validator/src/task_status.js +15 -0
- package/nodenithy/build/validator/src/test.js +44 -0
- package/nodenithy/build/validator/src/trustedzone.js +613 -0
- package/nodenithy/build/validator/src/validator_abi.js +834 -0
- package/nodenithy/build/validator/src/wallet.js +28 -0
- package/nodenithy/build.js +184 -0
- package/nodenithy/build.mjs +179 -0
- package/nodenithy/build.sh +161 -0
- package/nodenithy/ipfs.js +135 -0
- package/nodenithy/ipfs.mjs +551 -0
- package/nodenithy/public/favicon.ico +0 -0
- package/nodenithy/public/index.html +43 -0
- package/nodenithy/public/logo192.png +0 -0
- package/nodenithy/public/logo512.png +0 -0
- package/nodenithy/public/manifest.json +25 -0
- package/nodenithy/public/robots.txt +3 -0
- package/nodenithy/run/__pycache__/swift_stream_service.cpython-312.pyc +0 -0
- package/nodenithy/run/app/input.txt +4 -0
- package/nodenithy/run/app/payload.js +4 -0
- package/nodenithy/run/docker-compose-final.yml.tmpl +65 -0
- package/nodenithy/run/docker-compose-swift-stream.yml +17 -0
- package/nodenithy/run/docker-compose.yml.tmpl +76 -0
- package/nodenithy/run/etny-securelock-test.yaml.tpl +46 -0
- package/nodenithy/run/etny-trustedzone-test.yaml.tpl +45 -0
- package/nodenithy/run/git.sh +22 -0
- package/nodenithy/run/image_registry.abi +1 -0
- package/nodenithy/run/image_registry.js +372 -0
- package/nodenithy/run/image_registry.py +327 -0
- package/nodenithy/run/image_registry_runner.py +71 -0
- package/nodenithy/run/ipfs.sh +58 -0
- package/nodenithy/run/ipfs_pre.sh +75 -0
- package/nodenithy/run/public_key_service.js +90 -0
- package/nodenithy/run/public_key_service.py +107 -0
- package/nodenithy/run/swift_stream_service.py +212 -0
- package/nodenithy/run/swiftstream.py +37 -0
- package/nodenithy/run/swiftstream1.py +27 -0
- package/nodenithy/run.js +538 -0
- package/nodenithy/run.sh +277 -0
- package/nodenithy/scripts/build-ipfs-upload.sh +23 -0
- package/nodenithy/scripts/build.sh +40 -0
- package/nodenithy/scripts/ipfs-daemon.sh +7 -0
- package/nodenithy/scripts/run.sh +50 -0
- package/nodenithy/src/App.css +57 -0
- package/nodenithy/src/ec_helloworld_example.js +64 -0
- package/nodenithy/src/index.css +13 -0
- package/nodenithy/src/index.js +17 -0
- package/nodenithy/src/preStart.js +45 -0
- package/nodenithy/src/preStart.mjs +57 -0
- package/nodenithy/src/reportWebVitals.js +13 -0
- package/nodenithy/src/serverless/backend.js +5 -0
- package/package.json +48 -0
- package/postinstall.js +34 -0
- package/publish.js +126 -0
- package/pynithy/build/docker-compose.yml +68 -0
- package/pynithy/build/las/Dockerfile +11 -0
- package/pynithy/build/las/src/etny_entrypoint.sh +6 -0
- package/pynithy/build/las/src/las_entrypoint.sh +26 -0
- package/pynithy/build/scripts/binary-fs-build.sh +28 -0
- package/pynithy/build/securelock/Dockerfile.tmpl +78 -0
- package/pynithy/build/securelock/scripts/binary-fs-build.sh +41 -0
- package/pynithy/build/securelock/src/app/.env +5 -0
- package/pynithy/build/securelock/src/app/cert1-ca1-clean.crt +10 -0
- package/pynithy/build/securelock/src/app/cert1-ca1-clean.key +6 -0
- package/pynithy/build/securelock/src/app/enclave_pub_cert.pem +10 -0
- package/pynithy/build/securelock/src/app/input.txt +1 -0
- package/pynithy/build/securelock/src/app/payload.py +25 -0
- package/pynithy/build/securelock/src/app/public-cert-clean.pem +10 -0
- package/pynithy/build/securelock/src/app/result.txt +1 -0
- package/pynithy/build/securelock/src/app/transaction.txt +1 -0
- package/pynithy/build/securelock/src/etny_crypto.py +167 -0
- package/pynithy/build/securelock/src/etny_exec.py +79 -0
- package/pynithy/build/securelock/src/image_registry.abi +1 -0
- package/pynithy/build/securelock/src/key_generation.py +17 -0
- package/pynithy/build/securelock/src/models.py +176 -0
- package/pynithy/build/securelock/src/pox.abi +1489 -0
- package/pynithy/build/securelock/src/securelock.py.tmpl +411 -0
- package/pynithy/build/securelock/src/swift_stream_service.py +186 -0
- package/pynithy/build/trustedzone/Dockerfile.tmpl +56 -0
- package/pynithy/build/trustedzone/scripts/binary-fs-build.sh +32 -0
- package/pynithy/build/trustedzone/src/app/.env +5 -0
- package/pynithy/build/trustedzone/src/app/cert1-ca1-clean.crt +10 -0
- package/pynithy/build/trustedzone/src/app/cert1-ca1-clean.key +6 -0
- package/pynithy/build/trustedzone/src/app/enclave_pub_cert.pem +10 -0
- package/pynithy/build/trustedzone/src/app/input.txt +1 -0
- package/pynithy/build/trustedzone/src/app/payload.py +25 -0
- package/pynithy/build/trustedzone/src/app/public-cert-clean.pem +10 -0
- package/pynithy/build/trustedzone/src/app/result.txt +1 -0
- package/pynithy/build/trustedzone/src/app/securelock.crt +10 -0
- package/pynithy/build/trustedzone/src/app/transaction.txt +1 -0
- package/pynithy/build/trustedzone/src/app/trustedzone.crt +10 -0
- package/pynithy/build/trustedzone/src/etny_crypto.py +188 -0
- package/pynithy/build/trustedzone/src/etny_exec.py +56 -0
- package/pynithy/build/trustedzone/src/formatter.py +42 -0
- package/pynithy/build/trustedzone/src/image_registry.abi +1 -0
- package/pynithy/build/trustedzone/src/key_generation.py +17 -0
- package/pynithy/build/trustedzone/src/models.py +176 -0
- package/pynithy/build/trustedzone/src/pox.abi +1489 -0
- package/pynithy/build/trustedzone/src/swift_stream_service.py +186 -0
- package/pynithy/build/trustedzone/src/trustedzone.py.tmpl +460 -0
- package/pynithy/build.mjs +179 -0
- package/pynithy/docker-compose.yml +0 -0
- package/pynithy/ipfs.mjs +244 -0
- package/pynithy/public/favicon.ico +0 -0
- package/pynithy/public/index.html +43 -0
- package/pynithy/public/logo192.png +0 -0
- package/pynithy/public/logo512.png +0 -0
- package/pynithy/public/manifest.json +25 -0
- package/pynithy/public/robots.txt +3 -0
- package/pynithy/run/certs/cert.pem +31 -0
- package/pynithy/run/certs/challenge.crt +10 -0
- package/pynithy/run/certs/key.pem +52 -0
- package/pynithy/run/docker-compose-final.yml +59 -0
- package/pynithy/run/docker-compose-final.yml.tmpl +59 -0
- package/pynithy/run/docker-compose-swift-stream.yml +27 -0
- package/pynithy/run/docker-compose-swift-stream.yml.tmpl +27 -0
- package/pynithy/run/docker-compose.yml +55 -0
- package/pynithy/run/docker-compose.yml.tmpl +55 -0
- package/pynithy/run/etny-pynity-test.yaml.tpl +46 -0
- package/pynithy/run/etny-securelock-test.yaml.tpl +46 -0
- package/pynithy/run/etny-trustedzone-test.yaml.tpl +46 -0
- package/pynithy/run/git.sh +22 -0
- package/pynithy/run/image_registry.abi +1 -0
- package/pynithy/run/image_registry.js +372 -0
- package/pynithy/run/image_registry.py +139 -0
- package/pynithy/run/image_registry_runner.py +45 -0
- package/pynithy/run/ipfs.sh +89 -0
- package/pynithy/run/public_key_service.js +90 -0
- package/pynithy/run/swiftstream.py +28 -0
- package/pynithy/run.js +538 -0
- package/pynithy/src/App.css +57 -0
- package/pynithy/src/ec_helloworld_example.js +64 -0
- package/pynithy/src/index.css +13 -0
- package/pynithy/src/index.js +17 -0
- package/pynithy/src/preStart.mjs +57 -0
- package/pynithy/src/reportWebVitals.js +13 -0
- package/pynithy/src/serverless/__init__.py +0 -0
- package/pynithy/src/serverless/backend.py +2 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { create } from 'ipfs-http-client';
|
|
2
|
+
import { delay, getRetryDelay } from './utils';
|
|
3
|
+
import { ECError } from './enums';
|
|
4
|
+
|
|
5
|
+
let ipfs = null;
|
|
6
|
+
const writeFile = promisify(fs.writeFile);
|
|
7
|
+
|
|
8
|
+
export const initialize = (host, protocol, port, token) => {
|
|
9
|
+
if (host.search('http') !== -1) {
|
|
10
|
+
ipfs = create(host);
|
|
11
|
+
} else if (token === '') {
|
|
12
|
+
ipfs = create({
|
|
13
|
+
host,
|
|
14
|
+
protocol,
|
|
15
|
+
port
|
|
16
|
+
});
|
|
17
|
+
} else {
|
|
18
|
+
// example of authorization headers
|
|
19
|
+
// headers: {
|
|
20
|
+
// authorization: 'Bearer ' + TOKEN
|
|
21
|
+
// }
|
|
22
|
+
// const auth =
|
|
23
|
+
// 'Basic ' + Buffer.from(INFURA_ID + ':' + INFURA_SECRET_KEY).toString('base64');
|
|
24
|
+
ipfs = create({
|
|
25
|
+
host,
|
|
26
|
+
protocol,
|
|
27
|
+
port,
|
|
28
|
+
headers: { authorization: token }
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const uploadToIPFS = async (code) => {
|
|
34
|
+
try {
|
|
35
|
+
const response = await ipfs.add(code);
|
|
36
|
+
return response.path;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
console.log(e);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const uploadFileToIPFS = async (path) => {
|
|
44
|
+
try {
|
|
45
|
+
const response = await ipfs.add(path);
|
|
46
|
+
return response.path;
|
|
47
|
+
} catch (e) {
|
|
48
|
+
console.log(e);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const uploadFolderToIPFS = async (path) => {
|
|
54
|
+
try {
|
|
55
|
+
const response = await ipfs.add(path, { recursive: true });
|
|
56
|
+
return response.path;
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.log(e);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// export const getFromIPFS = async (hash) => {
|
|
64
|
+
// let res = '';
|
|
65
|
+
// try {
|
|
66
|
+
// // eslint-disable-next-line no-restricted-syntax
|
|
67
|
+
// for await (const file of ipfs.cat(hash)) {
|
|
68
|
+
// res += new TextDecoder().decode(file.buffer);
|
|
69
|
+
// }
|
|
70
|
+
//
|
|
71
|
+
// return res;
|
|
72
|
+
// } catch (error) {
|
|
73
|
+
// console.error(error.message);
|
|
74
|
+
// await delay(2000);
|
|
75
|
+
// return getFromIPFS(hash);
|
|
76
|
+
// }
|
|
77
|
+
// };
|
|
78
|
+
|
|
79
|
+
export const getFromIPFS = async (hash, filePath, maxRetries = process.env.REACT_APP_IPFS_RETRIES || 5) => {
|
|
80
|
+
let res = '';
|
|
81
|
+
let retryCount = 0;
|
|
82
|
+
|
|
83
|
+
while (retryCount < maxRetries) {
|
|
84
|
+
try {
|
|
85
|
+
// eslint-disable-next-line no-restricted-syntax,no-await-in-loop
|
|
86
|
+
for await (const file of ipfs.cat(hash)) {
|
|
87
|
+
res += new TextDecoder().decode(file.buffer);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Save the content to a file
|
|
91
|
+
await writeFile(filePath, res);
|
|
92
|
+
return res;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error(error.message);
|
|
95
|
+
retryCount += 1;
|
|
96
|
+
|
|
97
|
+
if (retryCount < maxRetries) {
|
|
98
|
+
// eslint-disable-next-line no-await-in-loop
|
|
99
|
+
await delay(getRetryDelay(retryCount));
|
|
100
|
+
// eslint-disable-next-line no-continue
|
|
101
|
+
continue;
|
|
102
|
+
} else {
|
|
103
|
+
throw new Error(ECError.IPFS_DOWNLOAD_ERROR);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export const getContentFromIPFS = async (hash, maxRetries = process.env.REACT_APP_IPFS_RETRIES || 5) => {
|
|
110
|
+
let res = '';
|
|
111
|
+
let retryCount = 0;
|
|
112
|
+
|
|
113
|
+
while (retryCount < maxRetries) {
|
|
114
|
+
try {
|
|
115
|
+
// eslint-disable-next-line no-restricted-syntax,no-await-in-loop
|
|
116
|
+
for await (const file of ipfs.cat(hash)) {
|
|
117
|
+
res += new TextDecoder().decode(file.buffer);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return res;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error(error.message);
|
|
123
|
+
retryCount += 1;
|
|
124
|
+
|
|
125
|
+
if (retryCount < maxRetries) {
|
|
126
|
+
// eslint-disable-next-line no-await-in-loop
|
|
127
|
+
await delay(getRetryDelay(retryCount));
|
|
128
|
+
// eslint-disable-next-line no-continue
|
|
129
|
+
continue;
|
|
130
|
+
} else {
|
|
131
|
+
throw new Error(ECError.IPFS_DOWNLOAD_ERROR);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
// ipfsClient.js
|
|
2
|
+
import { create, globSource } from 'kubo-rpc-client';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { promises as fss } from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { MultiBar, Presets } from 'cli-progress';
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
const writeFile = promisify(fs.writeFile);
|
|
12
|
+
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
|
|
13
|
+
const getRetryDelay = (retryCount, baseDelay = 1) => baseDelay * 2 ** retryCount;
|
|
14
|
+
|
|
15
|
+
let ipfs = null;
|
|
16
|
+
|
|
17
|
+
const initialize = (host, protocol, port, token) => {
|
|
18
|
+
if (host.search('http') !== -1) {
|
|
19
|
+
ipfs = create(host); //{ timeout: '4m' }
|
|
20
|
+
} else if (token === '') {
|
|
21
|
+
ipfs = create({
|
|
22
|
+
host,
|
|
23
|
+
protocol,
|
|
24
|
+
port,
|
|
25
|
+
// timeout: '4m'
|
|
26
|
+
});
|
|
27
|
+
} else {
|
|
28
|
+
ipfs = create({
|
|
29
|
+
host,
|
|
30
|
+
protocol,
|
|
31
|
+
port,
|
|
32
|
+
headers: { authorization: token },
|
|
33
|
+
// timeout: '4m'
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const uploadFileToIPFS = async (filePath) => {
|
|
39
|
+
try {
|
|
40
|
+
const fileContent = await fss.readFile(filePath);
|
|
41
|
+
const response = await ipfs.add({ path: filePath, content: fileContent });
|
|
42
|
+
await fss.writeFile(`./IPFS_DOCKER_COMPOSE_HASH.ipfs`, response.cid.toString());
|
|
43
|
+
return response.cid.toString();
|
|
44
|
+
} catch (e) {
|
|
45
|
+
console.error();
|
|
46
|
+
return "Failed to upload file to IPFS, please try again.";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const uploadFolderToIPFS2 = async (path) => {
|
|
51
|
+
try {
|
|
52
|
+
console.log(`Uploading folder to IPFS: ${path}`);
|
|
53
|
+
const response = await ipfs.add(path, { pin: true , recursive: true }).catch((e) => console.log(e));
|
|
54
|
+
// console.log(JSON.stringify(response, null, 2));
|
|
55
|
+
const { cid } = response;
|
|
56
|
+
// while (true) {
|
|
57
|
+
// const { cid } = response;
|
|
58
|
+
// if (response.path) {
|
|
59
|
+
// break;
|
|
60
|
+
// }
|
|
61
|
+
// // console.log(`Added file: ${cid}`);
|
|
62
|
+
// delay(50000);
|
|
63
|
+
// }
|
|
64
|
+
// console.log(`response: ${response}`);
|
|
65
|
+
return cid;
|
|
66
|
+
} catch (e) {
|
|
67
|
+
console.log(e);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const MAX_BATCH_SIZE = 20 * 1024 * 1024; // 100MB
|
|
73
|
+
|
|
74
|
+
const uploadFolderToIPFSBatch = async (folderPath) => {
|
|
75
|
+
try {
|
|
76
|
+
const files = [];
|
|
77
|
+
const readDirectory = (dir) => {
|
|
78
|
+
fs.readdirSync(dir).forEach((file) => {
|
|
79
|
+
const fullPath = path.join(dir, file);
|
|
80
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
81
|
+
readDirectory(fullPath);
|
|
82
|
+
} else {
|
|
83
|
+
files.push({
|
|
84
|
+
path: path.relative(folderPath, fullPath),
|
|
85
|
+
content: fs.readFileSync(fullPath),
|
|
86
|
+
size: fs.statSync(fullPath).size
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
readDirectory(folderPath);
|
|
93
|
+
console.log(`Uploading folder to IPFS: ${folderPath}`);
|
|
94
|
+
console.log(`Number of files: ${files.length}`);
|
|
95
|
+
|
|
96
|
+
const ipfsOptions = {
|
|
97
|
+
wrapWithDirectory: false,
|
|
98
|
+
pin: true,
|
|
99
|
+
progress: (prog) => console.log(`Added ${prog / 1024 / 1024} MB`),
|
|
100
|
+
timeout: '2m'
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const allCids = [];
|
|
104
|
+
let currentBatch = [];
|
|
105
|
+
let currentBatchSize = 0;
|
|
106
|
+
|
|
107
|
+
for (const file of files) {
|
|
108
|
+
if (file.size > MAX_BATCH_SIZE) {
|
|
109
|
+
// Upload large files individually
|
|
110
|
+
console.log(`Uploading large file individually: ${file.path}, size: ${file.size / 1024 / 1024} MB`);
|
|
111
|
+
for await (const result of ipfs.addAll([file], ipfsOptions)) {
|
|
112
|
+
allCids.push(result.cid);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
// Add file to current batch
|
|
116
|
+
if (currentBatchSize + file.size > MAX_BATCH_SIZE) {
|
|
117
|
+
// await delay(30000);
|
|
118
|
+
// Upload current batch, display in mb
|
|
119
|
+
console.log(`Uploading batch of size ${currentBatchSize / 1024 / 1024} MB`);
|
|
120
|
+
for await (const result of ipfs.addAll(currentBatch, ipfsOptions)) {
|
|
121
|
+
allCids.push(result.cid);
|
|
122
|
+
}
|
|
123
|
+
// Reset batch
|
|
124
|
+
currentBatch = [];
|
|
125
|
+
currentBatchSize = 0;
|
|
126
|
+
}
|
|
127
|
+
currentBatch.push(file);
|
|
128
|
+
currentBatchSize += file.size;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Upload any remaining files in the last batch
|
|
133
|
+
if (currentBatch.length > 0) {
|
|
134
|
+
console.log(`Uploading final batch of size ${currentBatchSize / 1024 / 1024} MB`);
|
|
135
|
+
for await (const result of ipfs.addAll(currentBatch, ipfsOptions)) {
|
|
136
|
+
allCids.push(result.cid);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Wrap all files into a single directory
|
|
141
|
+
const directory = await ipfs.addAll(allCids.map(cid => ({ path: cid.toString(), content: ipfs.cat(cid) })), {
|
|
142
|
+
wrapWithDirectory: true,
|
|
143
|
+
pin: true,
|
|
144
|
+
timeout: '2m'
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
console.log(`response: ${JSON.stringify(directory, null, 2)}`);
|
|
148
|
+
return directory.cid;
|
|
149
|
+
} catch (e) {
|
|
150
|
+
console.error(e);
|
|
151
|
+
return "error";
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const uploadFolderToIPFS3 = async (folderPath) => {
|
|
156
|
+
try {
|
|
157
|
+
const files = [];
|
|
158
|
+
|
|
159
|
+
const readDirectory = (dir) => {
|
|
160
|
+
const items = fs.readdirSync(dir);
|
|
161
|
+
items.forEach((item) => {
|
|
162
|
+
const fullPath = path.join(dir, item);
|
|
163
|
+
const stats = fs.statSync(fullPath);
|
|
164
|
+
if (stats.isDirectory()) {
|
|
165
|
+
readDirectory(fullPath);
|
|
166
|
+
} else {
|
|
167
|
+
files.push({
|
|
168
|
+
path: path.relative(folderPath, fullPath),
|
|
169
|
+
content: fs.readFileSync(fullPath)
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
readDirectory(folderPath);
|
|
176
|
+
console.log(`Uploading folder to IPFS: ${folderPath}`);
|
|
177
|
+
// console.log(`Files: ${JSON.stringify(files[0], null, 2)}`);
|
|
178
|
+
console.log(`number of files: ${files.length}`);
|
|
179
|
+
// const response = await ipfs.addAll(files, { wrapWithDirectory: true, pin: true, timeout: 600000, progress: (prog) => console.log(`Added ${prog} bytes`)});
|
|
180
|
+
// const response = await ipfs.addAll(files);
|
|
181
|
+
for await (const file of ipfs.addAll(files, { wrapWithDirectory: true, pin: true, timeout: 600000, progress: (prog) => console.log(`Added ${prog} bytes`)})) {
|
|
182
|
+
console.log(file)
|
|
183
|
+
}
|
|
184
|
+
console.log(`response: ${JSON.stringify(response, null, 2)}`);
|
|
185
|
+
return response.cid;
|
|
186
|
+
} catch (e) {
|
|
187
|
+
console.log(e);
|
|
188
|
+
return "error";
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// const uploadFolderToIPFS = async (folderPath) => {
|
|
193
|
+
// try {
|
|
194
|
+
// const addedFiles = [nume, continut];
|
|
195
|
+
// const ipfsOptions = {
|
|
196
|
+
// wrapWithDirectory: true,
|
|
197
|
+
// pin: true,
|
|
198
|
+
// progress: (prog) => console.log(`Added ${prog / 1024 / 1024} MB`),
|
|
199
|
+
// timeout: '5m'
|
|
200
|
+
// };
|
|
201
|
+
// console.log(`Uploading folder to IPFS: ${folderPath}`);
|
|
202
|
+
// for await (const file of ipfs.addAll(globSource(folderPath, '**/*'),{ ...ipfsOptions })) {
|
|
203
|
+
// addedFiles.push({
|
|
204
|
+
// cid: file.cid.toString(),
|
|
205
|
+
// path: file.path,
|
|
206
|
+
// size: file.size,
|
|
207
|
+
// });
|
|
208
|
+
// }
|
|
209
|
+
|
|
210
|
+
// // for await (const file of ipfs.addAll(
|
|
211
|
+
// // globSource(folderPath, '**/*', { hidden: true }),
|
|
212
|
+
// // { ...ipfsOptions, fileImportConcurrency: 1 }
|
|
213
|
+
// // )) {
|
|
214
|
+
// // // export each added file to a json file
|
|
215
|
+
// // await writeFile(`./files/addedFile${file.cid.toString()}.json`, JSON.stringify(file, null, 2));
|
|
216
|
+
// // console.log(`Added file: ${file.path} with CID: ${file.cid.toString()}`);
|
|
217
|
+
// // addedFiles.push({
|
|
218
|
+
// // cid: file.cid.toString(),
|
|
219
|
+
// // path: file.path,
|
|
220
|
+
// // size: file.size,
|
|
221
|
+
// // });
|
|
222
|
+
// // }
|
|
223
|
+
// // // export added files to a json file
|
|
224
|
+
// // await writeFile('addedFiles, json', JSON.stringify(addedFiles, null, 2));
|
|
225
|
+
|
|
226
|
+
// // console.log("addedFiles: ", JSON.stringify(addedFiles, null, 2));
|
|
227
|
+
|
|
228
|
+
// // Return the CID of the root directory
|
|
229
|
+
// return addedFiles.find(file => file.path === '').cid;
|
|
230
|
+
// // return;
|
|
231
|
+
// } catch (e) {
|
|
232
|
+
// console.error(e);
|
|
233
|
+
// return "err";
|
|
234
|
+
// }
|
|
235
|
+
// };
|
|
236
|
+
|
|
237
|
+
const uploadFolderToIPFS = async (folderPath) => {
|
|
238
|
+
try {
|
|
239
|
+
const addedFiles = [];
|
|
240
|
+
const ipfsOptions = {
|
|
241
|
+
wrapWithDirectory: true,
|
|
242
|
+
pin: true,
|
|
243
|
+
hidden: true,
|
|
244
|
+
timeout: '5m'
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
console.log(`Uploading folder to IPFS: ${folderPath}`);
|
|
248
|
+
|
|
249
|
+
const multiBar = new MultiBar({
|
|
250
|
+
clearOnComplete: false,
|
|
251
|
+
hideCursor: true,
|
|
252
|
+
format: 'Progress [{bar}] {percentage}% | {value}/{total} MB'
|
|
253
|
+
}, Presets.shades_classic);
|
|
254
|
+
|
|
255
|
+
const files = [];
|
|
256
|
+
const readDirectory = (dir) => {
|
|
257
|
+
fs.readdirSync(dir).forEach((file) => {
|
|
258
|
+
const fullPath = path.join(dir, file);
|
|
259
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
260
|
+
readDirectory(fullPath);
|
|
261
|
+
} else {
|
|
262
|
+
files.push({
|
|
263
|
+
path: path.relative(folderPath, fullPath),
|
|
264
|
+
size: fs.statSync(fullPath).size
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
readDirectory(folderPath);
|
|
271
|
+
const totalSize = files.reduce((acc, file) => acc + file.size, 0);
|
|
272
|
+
|
|
273
|
+
const progressBar = multiBar.create(totalSize / 1024 / 1024, 0);
|
|
274
|
+
|
|
275
|
+
for await (const file of ipfs.addAll(files.map(file => ({
|
|
276
|
+
path: file.path.replace(/\\/g, '/'),
|
|
277
|
+
content: fs.createReadStream(path.join(folderPath, file.path))
|
|
278
|
+
})), { ...ipfsOptions })) {
|
|
279
|
+
addedFiles.push({
|
|
280
|
+
cid: file.cid.toString(),
|
|
281
|
+
path: file.path,
|
|
282
|
+
size: file.size,
|
|
283
|
+
});
|
|
284
|
+
progressBar.increment(file.size / 1024 / 1024);
|
|
285
|
+
}
|
|
286
|
+
progressBar.update(totalSize / 1024 / 1024);
|
|
287
|
+
multiBar.stop();
|
|
288
|
+
const _hash = addedFiles.find(file => file.path === '').cid;
|
|
289
|
+
// Return the CID of the root directory
|
|
290
|
+
await fss.writeFile(`./IPFS_HASH.ipfs`, _hash);
|
|
291
|
+
return _hash;
|
|
292
|
+
} catch (e) {
|
|
293
|
+
return "Upload failed.";
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const getFromIPFS = async (hhash, filePath, maxRetries = process.env.REACT_APP_IPFS_RETRIES || 5) => {
|
|
298
|
+
let res = '';
|
|
299
|
+
let retryCount = 0;
|
|
300
|
+
// console.log('Downloading file from IPFS...');
|
|
301
|
+
// console.log(`Hash: ${hhash}`);
|
|
302
|
+
// console.log(`Max Retries: ${maxRetries}`);
|
|
303
|
+
|
|
304
|
+
while (retryCount < maxRetries) {
|
|
305
|
+
try {
|
|
306
|
+
for await (const file of ipfs.cat(hhash)) {
|
|
307
|
+
res += new TextDecoder().decode(file.buffer);
|
|
308
|
+
}
|
|
309
|
+
await writeFile(filePath, res);
|
|
310
|
+
return;
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error(`Error: ${error.message}`);
|
|
313
|
+
retryCount += 1;
|
|
314
|
+
|
|
315
|
+
if (retryCount < maxRetries) {
|
|
316
|
+
console.log(`Retrying... (${retryCount}/${maxRetries})`);
|
|
317
|
+
await delay(getRetryDelay(retryCount));
|
|
318
|
+
continue;
|
|
319
|
+
} else {
|
|
320
|
+
throw new Error("ECError.IPFS_DOWNLOAD_ERROR");
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const downloadFromIPFS = async (hash, folderPath, maxRetries = process.env.REACT_APP_IPFS_RETRIES || 5) => {
|
|
327
|
+
let retryCount = 0;
|
|
328
|
+
console.log(`Hash: ${hash}`);
|
|
329
|
+
console.log(`Folder Path: ${folderPath}`);
|
|
330
|
+
console.log(`Max Retries: ${maxRetries}`);
|
|
331
|
+
|
|
332
|
+
while (retryCount < maxRetries) {
|
|
333
|
+
try {
|
|
334
|
+
for await (const file of ipfs.get(hash)) {
|
|
335
|
+
console.log(`file: ${JSON.stringify(file, null, 2)}`);
|
|
336
|
+
const filePathToWrite = path.join(folderPath, file.path);
|
|
337
|
+
|
|
338
|
+
if (file.type === 'dir') {
|
|
339
|
+
await fs.mkdir(filePathToWrite, { recursive: true });
|
|
340
|
+
} else {
|
|
341
|
+
const content = new TextDecoder().decode(file.content);
|
|
342
|
+
await fs.mkdir(path.dirname(filePathToWrite), { recursive: true });
|
|
343
|
+
await fs.writeFile(filePathToWrite, content);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
console.log(`Download complete. Files saved to ${folderPath}`);
|
|
347
|
+
return;
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.error(`Error: ${error.message}`);
|
|
350
|
+
retryCount += 1;
|
|
351
|
+
|
|
352
|
+
if (retryCount < maxRetries) {
|
|
353
|
+
console.log(`Retrying... (${retryCount}/${maxRetries})`);
|
|
354
|
+
await delay(getRetryDelay(retryCount));
|
|
355
|
+
continue;
|
|
356
|
+
} else {
|
|
357
|
+
throw new Error("ECError.IPFS_DOWNLOAD_ERROR");
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const downloadFolderFromIPFS = async (cid, outputPath) => {
|
|
364
|
+
try {
|
|
365
|
+
// const ipfs = create({ url: 'http://localhost:5001' }); // Adjust the IPFS API URL if necessary
|
|
366
|
+
|
|
367
|
+
console.log(`Downloading folder from IPFS: ${cid}`);
|
|
368
|
+
|
|
369
|
+
const multiBar = new MultiBar({
|
|
370
|
+
clearOnComplete: false,
|
|
371
|
+
hideCursor: true,
|
|
372
|
+
format: 'Progress [{bar}] {percentage}% | {value}/{total} MB'
|
|
373
|
+
}, Presets.shades_classic);
|
|
374
|
+
|
|
375
|
+
const files = [];
|
|
376
|
+
for await (const file of ipfs.get(cid)) {
|
|
377
|
+
console.log(`file: ${JSON.stringify(file, null, 2)}`);
|
|
378
|
+
if (!file.content) continue;
|
|
379
|
+
|
|
380
|
+
const filePath = path.join(outputPath, file.path);
|
|
381
|
+
const dir = path.dirname(filePath);
|
|
382
|
+
|
|
383
|
+
if (!fs.existsSync(dir)) {
|
|
384
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const writeStream = fs.createWriteStream(filePath);
|
|
388
|
+
const progressBar = multiBar.create(file.size / 1024 / 1024, 0);
|
|
389
|
+
|
|
390
|
+
for await (const chunk of file.content) {
|
|
391
|
+
writeStream.write(chunk);
|
|
392
|
+
progressBar.increment(chunk.length / 1024 / 1024);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
writeStream.end();
|
|
396
|
+
progressBar.update(file.size / 1024 / 1024);
|
|
397
|
+
files.push(filePath);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
multiBar.stop();
|
|
401
|
+
console.log(`Downloaded ${files.length} files to ${outputPath}`);
|
|
402
|
+
} catch (e) {
|
|
403
|
+
console.error(e);
|
|
404
|
+
return "err";
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
// const downloadFolderFromIPFS = async (cid, folderPath) => {
|
|
409
|
+
// try {
|
|
410
|
+
// console.log(`Downloading folder from IPFS: ${cid}`);
|
|
411
|
+
|
|
412
|
+
// // let res = await ipfs.get(cid);
|
|
413
|
+
|
|
414
|
+
// // const buffer = res[0];
|
|
415
|
+
|
|
416
|
+
// const utf8Decode = new TextDecoder('utf-8');
|
|
417
|
+
// // const string = utf8Decode.decode(buffer);
|
|
418
|
+
|
|
419
|
+
// // const object = JSON.parse(string);
|
|
420
|
+
// // console.log(`object: ${JSON.stringify(string, null, 2)}`);
|
|
421
|
+
// for await (const file of ipfs.get(cid)) {
|
|
422
|
+
|
|
423
|
+
// // console.log(`file: ${JSON.stringify(file, null, 2)}`);
|
|
424
|
+
// console.log(`file decoded: ${JSON.stringify(utf8Decode.decode(file), null, 2)}`);
|
|
425
|
+
// // const buffer = file[0];
|
|
426
|
+
// // console.log(`file: ${JSON.stringify(utf8Decode.decode(buffer), null, 2)}`);
|
|
427
|
+
// process.exit(0);
|
|
428
|
+
// // console.log(`${JSON.stringify(new TextDecoder().decode(file), null, 2)}`)
|
|
429
|
+
// // console.log(`file: ${JSON.stringify(file, null, 2)}`);
|
|
430
|
+
// // console.log(`file: ${JSON.stringify(file, null, 2)}`);
|
|
431
|
+
// // for await (const ffile of ipfs.ls(file.path)) {
|
|
432
|
+
// // console.log(`ffile: ${JSON.stringify(ffile, null, 2)}`);
|
|
433
|
+
// // }
|
|
434
|
+
// // for await (const ffile of ipfs.get("QmbjQpKFbueKR6QDU2Cj4ChsyGBR2spMwKV2S3yqrjF6w7")) {
|
|
435
|
+
// // console.log(`ffile: ${JSON.stringify(ffile, null, 2)}`);
|
|
436
|
+
// // }
|
|
437
|
+
// // console.log(`file cid: ${JSON.stringify(await ipfs.get("QmbjQpKFbueKR6QDU2Cj4ChsyGBR2spMwKV2S3yqrjF6w7"), null, 2)}`);
|
|
438
|
+
|
|
439
|
+
// // if (!file.path) {
|
|
440
|
+
// // // console.warn(`Skipping file with undefined path: ${JSON.stringify(file)}`);
|
|
441
|
+
// // continue;
|
|
442
|
+
// // }
|
|
443
|
+
|
|
444
|
+
// // const filePath = path.join(folderPath, file.path);
|
|
445
|
+
// // console.log(`Downloading file: ${filePath}`);
|
|
446
|
+
// // if (file.type === 'dir') {
|
|
447
|
+
// // fs.mkdirSync(filePath, { recursive: true });
|
|
448
|
+
// // } else {
|
|
449
|
+
// // fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
450
|
+
// // const content = [];
|
|
451
|
+
// // for await (const chunk of file.content) {
|
|
452
|
+
// // content.push(chunk);
|
|
453
|
+
// // }
|
|
454
|
+
// // fs.writeFileSync(filePath, Buffer.concat(content));
|
|
455
|
+
// // }
|
|
456
|
+
// }
|
|
457
|
+
|
|
458
|
+
// console.log(`Download complete: ${folderPath}`);
|
|
459
|
+
// } catch (e) {
|
|
460
|
+
// console.error(e);
|
|
461
|
+
// return "err";
|
|
462
|
+
// }
|
|
463
|
+
// };
|
|
464
|
+
|
|
465
|
+
const getContentFromIPFS = async (hash, maxRetries = process.env.REACT_APP_IPFS_RETRIES || 5) => {
|
|
466
|
+
let res = '';
|
|
467
|
+
let retryCount = 0;
|
|
468
|
+
|
|
469
|
+
while (retryCount < maxRetries) {
|
|
470
|
+
try {
|
|
471
|
+
for await (const file of ipfs.cat(hash)) {
|
|
472
|
+
res += new TextDecoder().decode(file.buffer);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return res;
|
|
476
|
+
} catch (error) {
|
|
477
|
+
console.error(error.message);
|
|
478
|
+
retryCount += 1;
|
|
479
|
+
|
|
480
|
+
if (retryCount < maxRetries) {
|
|
481
|
+
await delay(getRetryDelay(retryCount));
|
|
482
|
+
continue;
|
|
483
|
+
} else {
|
|
484
|
+
throw new Error("ECIPFSDownloadError");
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
program
|
|
491
|
+
.option('--host <host>', 'IPFS host')
|
|
492
|
+
.option('--hhash <hhash>', 'IPFS hash')
|
|
493
|
+
.option('--filePath <path>', 'Path to the file')
|
|
494
|
+
.option('--folderPath <path>', 'Path to the folder')
|
|
495
|
+
.option('--action <action>', 'Action to perform (upload, download)')
|
|
496
|
+
.option('--output <path>', 'Output path for download');
|
|
497
|
+
|
|
498
|
+
program.parse(process.argv);
|
|
499
|
+
|
|
500
|
+
const options = program.opts();
|
|
501
|
+
|
|
502
|
+
const main = async () => {
|
|
503
|
+
const host = options.host || 'localhost';
|
|
504
|
+
initialize(host);
|
|
505
|
+
|
|
506
|
+
if (options.action === 'upload') {
|
|
507
|
+
if (options.filePath) {
|
|
508
|
+
const hhash = await uploadFileToIPFS(options.filePath);
|
|
509
|
+
console.log(`${hhash}`);
|
|
510
|
+
} else if (options.folderPath) {
|
|
511
|
+
// const hhash = await uploadFolderToIPFSBatch(options.folderPath);
|
|
512
|
+
let retryCount = 0;
|
|
513
|
+
let hhash = null;
|
|
514
|
+
try {
|
|
515
|
+
hhash = await uploadFolderToIPFS(options.folderPath);
|
|
516
|
+
console.log(`${hhash}`);
|
|
517
|
+
} catch (e) {
|
|
518
|
+
// console.log(e);
|
|
519
|
+
}
|
|
520
|
+
while ((!hhash || hhash === 'Upload failed.') && retryCount < 3) {
|
|
521
|
+
console.log(`Retrying... (${retryCount}/3)`);
|
|
522
|
+
hhash = await uploadFolderToIPFS(options.folderPath);
|
|
523
|
+
console.log(`${hhash}`);
|
|
524
|
+
retryCount += 1;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (!hhash || hhash === 'Upload failed.') {
|
|
528
|
+
console.log(`Failed to upload folder to IPFS, please try again.`);
|
|
529
|
+
}
|
|
530
|
+
process.exit(0);
|
|
531
|
+
} else {
|
|
532
|
+
console.error('Please provide a filePath or folderPath for upload.');
|
|
533
|
+
}
|
|
534
|
+
} else if (options.action === 'download') {
|
|
535
|
+
if (options.filePath) {
|
|
536
|
+
console.log(`Downloading file from IPFS: ${options.hhash}`);
|
|
537
|
+
const content = await getFromIPFS(options.hhash, options.filePath);
|
|
538
|
+
console.log(`File downloaded. ${options.hhash}`);
|
|
539
|
+
} else if (options.folderPath) {
|
|
540
|
+
console.log(`Downloading folder from IPFS: ${options.hhash}`);
|
|
541
|
+
const content = await downloadFolderFromIPFS(options.hhash, options.folderPath);
|
|
542
|
+
console.log(`Folder downloaded. ${options.hhash}`);
|
|
543
|
+
} else {
|
|
544
|
+
console.error('Please provide a filePath or folderPath for download.');
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
console.error('Please provide a valid action (upload, download).');
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
main();
|
|
Binary file
|