@ethernity-cloud/sdk-js 1.7.0 → 1.7.1
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 +46 -46
- package/cas/config.js +4 -4
- package/init.js +4 -2
- package/network.js +51 -0
- package/nodenithy/src/ec_helloworld_example.js +46 -42
- package/nodenithy/src/preStart.mjs +41 -51
- package/package.json +3 -2
- package/pynithy/src/ec_helloworld_example.js +46 -42
- package/pynithy/src/preStart.mjs +41 -51
- package/run.js +1 -39
- package/nodenithy/src/preStart.js +0 -45
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ The sdk has been tested on the following operating systems:
|
|
|
43
43
|
provisioned by the ethernity-cas validator set exactly as on mainnet.
|
|
44
44
|
`ecld-publish` registers the securelock session on-chain in the
|
|
45
45
|
SessionRegistry (`0xcb1F389b...`, see `cas/config.js`), resolves a CAS
|
|
46
|
-
from the ValidatorRegistry (`
|
|
46
|
+
from the ValidatorRegistry (`0x0014aB10...`, or `ECLD_CAS_ADDR=host:port`)
|
|
47
47
|
for the compose and the certificate harvest, takes the trustedzone
|
|
48
48
|
session name from the ImageRegistry (ECImageRegistryV2,
|
|
49
49
|
`0x99A84C62...`), and links the session to the published image. `ecld-build` signs the securelock `--production`.
|
|
@@ -53,7 +53,7 @@ The sdk has been tested on the following operating systems:
|
|
|
53
53
|
- LitVM:
|
|
54
54
|
- LiteForge - CAS-attested the same way, by LitVM's own ethernity-cas
|
|
55
55
|
validator set (SessionRegistry `0x8ad24b3F...`, ValidatorRegistry
|
|
56
|
-
`
|
|
56
|
+
`0xbE3759f3...`).
|
|
57
57
|
- LiteForge Unsafe - the unsafe network beside LiteForge (see below).
|
|
58
58
|
- Polyhon:
|
|
59
59
|
- Amoy Testnet - to be provided during the following updates
|
|
@@ -189,63 +189,63 @@ function hello(msg='World') {
|
|
|
189
189
|
|
|
190
190
|
module.exports = { hello };
|
|
191
191
|
```
|
|
192
|
-
From your frontend application, using the ethernity cloud runner library, you will be calling the function as seen in the below example, where we pass `hello("World");` to be executed on the backend which will run in the Blockchain
|
|
192
|
+
From your frontend application, using the ethernity cloud runner library (`@ethernity-cloud/runner`, installed by `ecld-init` at the version this SDK depends on), you will be calling the function as seen in the below example, where we pass `hello("World");` to be executed on the backend which will run in the Blockchain. `npm start` runs `src/preStart.mjs` first, which fills the constants at the top from the project's `.env`: the securelock name the dApp is published as, the trustedzone it was built against, the network's token address and chain id, the `-unsafe` network when the dApp runs without a CAS, and the IPFS endpoint.
|
|
193
193
|
```js
|
|
194
|
-
|
|
194
|
+
import './App.css';
|
|
195
195
|
import EthernityCloudRunner from "@ethernity-cloud/runner";
|
|
196
|
-
import {
|
|
197
|
-
import Web3 from 'web3';
|
|
196
|
+
import { ECStatus } from "@ethernity-cloud/runner/enums";
|
|
198
197
|
|
|
198
|
+
// Filled in from the project's .env by src/preStart.mjs on `npm start`.
|
|
199
199
|
const PROJECT_NAME = "";
|
|
200
|
+
const TRUSTED_ZONE_IMAGE = "";
|
|
201
|
+
const NETWORK_ADDRESS = "";
|
|
202
|
+
const CHAIN_ID = null;
|
|
203
|
+
const UNSAFE_NETWORK = null;
|
|
200
204
|
const IPFS_ENDPOINT = "";
|
|
201
205
|
|
|
206
|
+
// A call into src/serverless/backend.js; its return value is the task result.
|
|
202
207
|
const code = `hello("World");`;
|
|
203
208
|
|
|
204
209
|
function App() {
|
|
205
210
|
const executeTask = async () => {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
console.log(PROJECT_NAME)
|
|
211
|
-
const onTaskProgress = (e) => {
|
|
212
|
-
if (e.detail.status === ECStatus.ERROR) {
|
|
213
|
-
console.error(e.detail.message);
|
|
214
|
-
} else {
|
|
215
|
-
console.log(e.detail.message);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
const onTaskCompleted = (e) => {
|
|
220
|
-
console.log(`Task Result: ${e.detail.message.result}`);
|
|
221
|
-
// display the result in page below the buttons
|
|
222
|
-
const result = document.createElement("p");
|
|
223
|
-
result.innerHTML = `Task Result: ${e.detail.message.result}`;
|
|
224
|
-
document.body.appendChild(result);
|
|
211
|
+
// The browser wallet (MetaMask) signs and pays for the order.
|
|
212
|
+
const runner = new EthernityCloudRunner(NETWORK_ADDRESS, {}, CHAIN_ID || undefined);
|
|
213
|
+
if (UNSAFE_NETWORK) {
|
|
214
|
+
await runner.setNetwork(...UNSAFE_NETWORK);
|
|
225
215
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
216
|
+
runner.initializeStorage(IPFS_ENDPOINT);
|
|
217
|
+
|
|
218
|
+
// Events are named by task status; detail is { message, status, progress }.
|
|
219
|
+
runner.addEventListener(ECStatus.DEFAULT, (e) => {
|
|
220
|
+
console.log(`[${e.detail.progress}] ${e.detail.message}`);
|
|
221
|
+
});
|
|
222
|
+
runner.addEventListener(ECStatus.ERROR, (e) => {
|
|
223
|
+
console.error(e.detail.message);
|
|
224
|
+
});
|
|
225
|
+
runner.addEventListener(ECStatus.SUCCESS, async () => {
|
|
226
|
+
const result = await runner.getResult();
|
|
227
|
+
console.log(`Task Result: ${result}`);
|
|
228
|
+
const line = document.createElement("p");
|
|
229
|
+
line.textContent = `Task Result: ${result}`;
|
|
230
|
+
document.body.appendChild(line);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
const resources = { taskPrice: 10, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1 };
|
|
234
|
+
await runner.run(resources, PROJECT_NAME, code, '', TRUSTED_ZONE_IMAGE);
|
|
234
235
|
};
|
|
236
|
+
|
|
235
237
|
const connectWallet = async () => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
};
|
|
238
|
+
if (!window.ethereum) {
|
|
239
|
+
console.log('Please install MetaMask!');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
await window.ethereum.request({ method: 'eth_requestAccounts' });
|
|
244
|
+
console.log("Wallet connected");
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.error("User denied account access");
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
249
|
|
|
250
250
|
return (
|
|
251
251
|
<div className="container">
|
package/cas/config.js
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
// Kept in sync with etny-{pynithy,nodenithy}/v3/networks.yaml
|
|
15
15
|
// (cas_session_registry_address, validator_registry_address).
|
|
16
16
|
const VALIDATOR_REGISTRY = {
|
|
17
|
-
'etny-pynithy-testnet': '
|
|
18
|
-
'etny-nodenithy-testnet': '
|
|
19
|
-
'ecld-pynithy-litvm-testnet': '
|
|
20
|
-
'ecld-nodenithy-litvm-testnet': '
|
|
17
|
+
'etny-pynithy-testnet': '0x0014aB102FEa6b02e3D793FF4b9a0Af309fB4E14',
|
|
18
|
+
'etny-nodenithy-testnet': '0x0014aB102FEa6b02e3D793FF4b9a0Af309fB4E14',
|
|
19
|
+
'ecld-pynithy-litvm-testnet': '0xbE3759f327e8643fC5A1717fb2072A0dAcBAD29E',
|
|
20
|
+
'ecld-nodenithy-litvm-testnet': '0xbE3759f327e8643fC5A1717fb2072A0dAcBAD29E',
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const SESSION_REGISTRY = {
|
package/init.js
CHANGED
|
@@ -310,9 +310,11 @@ const main = async () => {
|
|
|
310
310
|
);
|
|
311
311
|
}
|
|
312
312
|
console.log("Installing required packages...");
|
|
313
|
-
//
|
|
313
|
+
// The app runs on the runner at the range this SDK depends on; the spec is
|
|
314
|
+
// quoted because cmd.exe treats a bare ^ as its escape character.
|
|
315
|
+
const runnerSpec = `@ethernity-cloud/runner@${require("./package.json").dependencies["@ethernity-cloud/runner"]}`;
|
|
314
316
|
execSync(
|
|
315
|
-
|
|
317
|
+
`npm install "${runnerSpec}" @testing-library/jest-dom@5.17.0 @testing-library/react@13.4.0 @testing-library/user-event@13.5.0 react@18.3.1 react-dom@18.3.1 react-scripts@5.0.1 web-vitals@2.1.4 dotenv@16.4.5`,
|
|
316
318
|
{ stdio: "inherit" },
|
|
317
319
|
);
|
|
318
320
|
} else {
|
package/network.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/* The runner's view of a project's network.
|
|
2
|
+
*
|
|
3
|
+
* BLOCKCHAIN_NETWORK, as ecld-init writes it (spaces -> underscores), names a
|
|
4
|
+
* network; the runner is constructed with that network's token ADDRESS, the
|
|
5
|
+
* chain id of a testnet whose token address other testnets share, and for an
|
|
6
|
+
* -unsafe network is set to the (network, type) that runs only -unsafe
|
|
7
|
+
* trustedzones. The table is built from the runner's own enums so the two
|
|
8
|
+
* cannot drift; the enums are an argument because the runner is ESM and this
|
|
9
|
+
* module is loaded from CJS (ecld-run) and ESM (a dApp's preStart) alike.
|
|
10
|
+
* Shared by ecld-run and the Hello World template's src/preStart.mjs. */
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const casConfig = require('./cas/config.js');
|
|
15
|
+
|
|
16
|
+
/* Accepts a few spellings per network. Returns the normalised key, the
|
|
17
|
+
* network ({ address, chainId?, unsafe? }) or null, and the known keys. */
|
|
18
|
+
function networkFor({ ECAddress, ECNetworkByChainId }, raw) {
|
|
19
|
+
const key = String(raw || '').trim().toUpperCase().replace(/\s+/g, '_');
|
|
20
|
+
const bloxbergTestnet = { address: ECAddress.BLOXBERG.TESTNET_ADDRESS };
|
|
21
|
+
const amoy = { address: ECAddress.POLYGON.TESTNET_ADDRESS };
|
|
22
|
+
const sepolia = { address: ECAddress.SEPOLIA.TESTNET_ADDRESS, chainId: ECNetworkByChainId.SEPOLIA.TESTNET };
|
|
23
|
+
const litvm = { address: ECAddress.LITVM.TESTNET_ADDRESS, chainId: ECNetworkByChainId.LITVM.TESTNET };
|
|
24
|
+
const table = {
|
|
25
|
+
BLOXBERG_TESTNET: bloxbergTestnet,
|
|
26
|
+
BLOXBERG_TESTNET_UNSAFE: { ...bloxbergTestnet, unsafe: ['BLOXBERG', 'TESTNET_UNSAFE'] },
|
|
27
|
+
BLOXBERG_MAINNET: { address: ECAddress.BLOXBERG.MAINNET_ADDRESS },
|
|
28
|
+
POLYGON_MAINNET: { address: ECAddress.POLYGON.MAINNET_ADDRESS },
|
|
29
|
+
POLYGON_AMOY: amoy,
|
|
30
|
+
POLYGON_AMOY_TESTNET: amoy,
|
|
31
|
+
IOTEX_TESTNET: { address: ECAddress.IOTEX.TESTNET_ADDRESS, chainId: ECNetworkByChainId.IOTEX.TESTNET },
|
|
32
|
+
ETHEREUM_SEPOLIA: sepolia,
|
|
33
|
+
SEPOLIA: sepolia,
|
|
34
|
+
LITVM_LITEFORGE: litvm,
|
|
35
|
+
LITVM: litvm,
|
|
36
|
+
LITVM_LITEFORGE_UNSAFE: { ...litvm, unsafe: ['LITVM', 'TESTNET_UNSAFE'] },
|
|
37
|
+
};
|
|
38
|
+
return { key, network: table[key] || null, known: Object.keys(table) };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* The -unsafe network a network token names, or whose sibling it names; null
|
|
42
|
+
* when the network has no -unsafe variant. */
|
|
43
|
+
function unsafeVariant(raw) {
|
|
44
|
+
const key = String(raw || '').trim().replace(/\s+/g, '_');
|
|
45
|
+
if (casConfig.isUnsafeNetwork(key)) return key;
|
|
46
|
+
const variant = Object.keys(casConfig.UNSAFE_NETWORKS)
|
|
47
|
+
.find((name) => casConfig.UNSAFE_NETWORKS[name].toUpperCase() === key.toUpperCase());
|
|
48
|
+
return variant || null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { networkFor, unsafeVariant };
|
|
@@ -1,58 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
import './App.css';
|
|
2
2
|
import EthernityCloudRunner from "@ethernity-cloud/runner";
|
|
3
|
-
import {
|
|
4
|
-
import Web3 from 'web3';
|
|
3
|
+
import { ECStatus } from "@ethernity-cloud/runner/enums";
|
|
5
4
|
|
|
5
|
+
// Filled in from the project's .env by src/preStart.mjs on `npm start`: the
|
|
6
|
+
// securelock this dApp is published as, the trustedzone it was built against,
|
|
7
|
+
// the network's token address and chain id, the -unsafe network when the dApp
|
|
8
|
+
// runs without a CAS (null otherwise), and the IPFS endpoint.
|
|
6
9
|
const PROJECT_NAME = "";
|
|
10
|
+
const TRUSTED_ZONE_IMAGE = "";
|
|
11
|
+
const NETWORK_ADDRESS = "";
|
|
12
|
+
const CHAIN_ID = null;
|
|
13
|
+
const UNSAFE_NETWORK = null;
|
|
7
14
|
const IPFS_ENDPOINT = "";
|
|
8
15
|
|
|
16
|
+
// A call into src/serverless/backend.js; its return value is the task result.
|
|
9
17
|
const code = `hello("World");`;
|
|
10
18
|
|
|
11
19
|
function App() {
|
|
12
20
|
const executeTask = async () => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
console.log(PROJECT_NAME)
|
|
18
|
-
const onTaskProgress = (e) => {
|
|
19
|
-
if (e.detail.status === ECStatus.ERROR) {
|
|
20
|
-
console.error(e.detail.message);
|
|
21
|
-
} else {
|
|
22
|
-
console.log(e.detail.message);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const onTaskCompleted = (e) => {
|
|
27
|
-
console.log(`Task Result: ${e.detail.message.result}`);
|
|
28
|
-
// display the result in page below the buttons
|
|
29
|
-
const result = document.createElement("p");
|
|
30
|
-
result.innerHTML = `Task Result: ${e.detail.message.result}`;
|
|
31
|
-
document.body.appendChild(result);
|
|
21
|
+
// The browser wallet (MetaMask) signs and pays for the order.
|
|
22
|
+
const runner = new EthernityCloudRunner(NETWORK_ADDRESS, {}, CHAIN_ID || undefined);
|
|
23
|
+
if (UNSAFE_NETWORK) {
|
|
24
|
+
await runner.setNetwork(...UNSAFE_NETWORK);
|
|
32
25
|
}
|
|
26
|
+
runner.initializeStorage(IPFS_ENDPOINT);
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
runner.addEventListener(
|
|
28
|
+
// Events are named by task status; detail is { message, status, progress }.
|
|
29
|
+
runner.addEventListener(ECStatus.DEFAULT, (e) => {
|
|
30
|
+
console.log(`[${e.detail.progress}] ${e.detail.message}`);
|
|
31
|
+
});
|
|
32
|
+
runner.addEventListener(ECStatus.ERROR, (e) => {
|
|
33
|
+
console.error(e.detail.message);
|
|
34
|
+
});
|
|
35
|
+
runner.addEventListener(ECStatus.SUCCESS, async () => {
|
|
36
|
+
const result = await runner.getResult();
|
|
37
|
+
console.log(`Task Result: ${result}`);
|
|
38
|
+
// display the result in page below the buttons
|
|
39
|
+
const line = document.createElement("p");
|
|
40
|
+
line.textContent = `Task Result: ${result}`;
|
|
41
|
+
document.body.appendChild(line);
|
|
42
|
+
});
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
'',
|
|
40
|
-
{ taskPrice: 10, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1 });
|
|
44
|
+
const resources = { taskPrice: 10, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1 };
|
|
45
|
+
await runner.run(resources, PROJECT_NAME, code, '', TRUSTED_ZONE_IMAGE);
|
|
41
46
|
};
|
|
47
|
+
|
|
42
48
|
const connectWallet = async () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
};
|
|
49
|
+
if (!window.ethereum) {
|
|
50
|
+
console.log('Please install MetaMask!');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await window.ethereum.request({ method: 'eth_requestAccounts' });
|
|
55
|
+
console.log("Wallet connected");
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error("User denied account access");
|
|
58
|
+
}
|
|
59
|
+
};
|
|
56
60
|
|
|
57
61
|
return (
|
|
58
62
|
<div className="container">
|
|
@@ -61,4 +65,4 @@ function App() {
|
|
|
61
65
|
</div>
|
|
62
66
|
);
|
|
63
67
|
}
|
|
64
|
-
export default App;
|
|
68
|
+
export default App;
|
|
@@ -1,57 +1,47 @@
|
|
|
1
|
+
// Runs before `react-scripts start` (the project's `npm start`): fills the
|
|
2
|
+
// constants at the top of src/ec_helloworld_example.js from the project's
|
|
3
|
+
// .env, the way ecld-run reads the same values. PROJECT_NAME and
|
|
4
|
+
// TRUSTED_ZONE_IMAGE take their -unsafe form on an -unsafe network; the
|
|
5
|
+
// network's token address, chain id and -unsafe (network, type) come from the
|
|
6
|
+
// runner's own enums through the SDK's network table.
|
|
1
7
|
import fs from 'fs';
|
|
8
|
+
import { createRequire } from 'module';
|
|
2
9
|
import dotenv from 'dotenv';
|
|
3
|
-
|
|
10
|
+
import * as enums from '@ethernity-cloud/runner/enums.js';
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'ecld-
|
|
12
|
+
dotenv.config();
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const casConfig = require('@ethernity-cloud/sdk-js/cas/config.js');
|
|
15
|
+
const { networkFor } = require('@ethernity-cloud/sdk-js/network.js');
|
|
16
|
+
|
|
17
|
+
const { PROJECT_NAME, TRUSTED_ZONE_IMAGE, BLOCKCHAIN_NETWORK, IPFS_ENDPOINT } = process.env;
|
|
18
|
+
if (!PROJECT_NAME || !BLOCKCHAIN_NETWORK) {
|
|
19
|
+
console.error('preStart: PROJECT_NAME and BLOCKCHAIN_NETWORK are not set in .env; run `npm run ecld-init` first.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const { network, known } = networkFor(enums, BLOCKCHAIN_NETWORK);
|
|
23
|
+
if (!network) {
|
|
24
|
+
console.error(`preStart: unknown BLOCKCHAIN_NETWORK '${BLOCKCHAIN_NETWORK}' in .env. Known: ${known.join(', ')}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const constants = {
|
|
29
|
+
PROJECT_NAME: casConfig.nameOnNetwork(PROJECT_NAME, BLOCKCHAIN_NETWORK),
|
|
30
|
+
TRUSTED_ZONE_IMAGE: casConfig.nameOnNetwork(TRUSTED_ZONE_IMAGE, BLOCKCHAIN_NETWORK) || '',
|
|
31
|
+
NETWORK_ADDRESS: network.address,
|
|
32
|
+
CHAIN_ID: network.chainId || null,
|
|
33
|
+
UNSAFE_NETWORK: network.unsafe || null,
|
|
34
|
+
IPFS_ENDPOINT: IPFS_ENDPOINT || 'https://ipfs.ethernity.cloud',
|
|
13
35
|
};
|
|
14
36
|
|
|
15
37
|
const filePath = 'src/ec_helloworld_example.js';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const imageRegistryPath = 'node_modules/@ethernity-cloud/runner/contract/operation/imageRegistryContract.js';
|
|
28
|
-
const imageRegistryContent = fs.readFileSync(imageRegistryPath, 'utf8');
|
|
29
|
-
|
|
30
|
-
// Log the original content for debugging
|
|
31
|
-
// console.log('Original imageRegistryContent:', imageRegistryContent);
|
|
32
|
-
|
|
33
|
-
// Replace the content in imageRegistryContract.js
|
|
34
|
-
// const updatedImageRegistryContent = imageRegistryContent.replace(/getLatestTrustedZoneImageCertPublicKey\([^)]*\);/, "getLatestTrustedZoneImageCertPublicKey('" + process.env.ENCLAVE_NAME_TRUSTEDZONE + "', 'v3')").replace(/getLatestImageVersionPublicKey\([^)]*\)/, "getLatestImageVersionPublicKey(imageName, '" + process.env.VERSION + "')");
|
|
35
|
-
const updatedImageRegistryContent = imageRegistryContent.replace(
|
|
36
|
-
/async getEnclaveDetailsV3\(.*?\{[\s\S]*?\}\s*\}/,
|
|
37
|
-
`async getEnclaveDetailsV3(imageName, version) {
|
|
38
|
-
try {
|
|
39
|
-
const trustedZonePublicKey = (await this.contract.getLatestTrustedZoneImageCertPublicKey('${process.env.ENCLAVE_NAME_TRUSTEDZONE}', 'v3'));
|
|
40
|
-
const imageDetails = await this.contract.getLatestImageVersionPublicKey(imageName, '${process.env.VERSION}');
|
|
41
|
-
return [imageDetails[0], trustedZonePublicKey[1], imageDetails[2]];
|
|
42
|
-
} catch (e) {
|
|
43
|
-
console.log(e);
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}`
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
fs.writeFileSync(imageRegistryPath, updatedImageRegistryContent, 'utf8');
|
|
51
|
-
|
|
52
|
-
const runnerPath = 'node_modules/@ethernity-cloud/runner/runner.js';
|
|
53
|
-
const runnerContent = fs.readFileSync(runnerPath, 'utf8');
|
|
54
|
-
|
|
55
|
-
const updatedRunnerContent = runnerContent.replace(/this.#enclaveImageIPFSHash}:.*?:/, "this.#enclaveImageIPFSHash}:"+process.env.ENCLAVE_NAME_TRUSTEDZONE+":").replace(/new ImageRegistryContract\([^)]*\);/, "new ImageRegistryContract(this.#networkAddress, '"+process.env.ENCLAVE_NAME_TRUSTEDZONE+"');");
|
|
56
|
-
|
|
57
|
-
fs.writeFileSync(runnerPath, updatedRunnerContent, 'utf8');
|
|
38
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
39
|
+
for (const [name, value] of Object.entries(constants)) {
|
|
40
|
+
const line = new RegExp(`^const ${name} = .*;$`, 'm');
|
|
41
|
+
if (!line.test(content)) {
|
|
42
|
+
console.error(`preStart: ${filePath} has no 'const ${name} = ...;' line to fill.`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
content = content.replace(line, `const ${name} = ${JSON.stringify(value)};`);
|
|
46
|
+
}
|
|
47
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethernity-cloud/sdk-js",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "A package to run ethernity cloud build scripts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"ecld-build": "cross-env node ./node_modules/@ethernity-cloud/sdk-js/build.js",
|
|
@@ -31,11 +31,12 @@
|
|
|
31
31
|
"test.js",
|
|
32
32
|
"info.js",
|
|
33
33
|
"run.js",
|
|
34
|
+
"network.js",
|
|
34
35
|
"!**/__pycache__/**",
|
|
35
36
|
"!**/*.pyc"
|
|
36
37
|
],
|
|
37
38
|
"dependencies": {
|
|
38
|
-
"@ethernity-cloud/runner": "^0.6.
|
|
39
|
+
"@ethernity-cloud/runner": "^0.6.1",
|
|
39
40
|
"acorn": "^8.11.0",
|
|
40
41
|
"adm-zip": "^0.5.14",
|
|
41
42
|
"axios": "^1.7.2",
|
|
@@ -1,58 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
import './App.css';
|
|
2
2
|
import EthernityCloudRunner from "@ethernity-cloud/runner";
|
|
3
|
-
import {
|
|
4
|
-
import Web3 from 'web3';
|
|
3
|
+
import { ECStatus } from "@ethernity-cloud/runner/enums";
|
|
5
4
|
|
|
5
|
+
// Filled in from the project's .env by src/preStart.mjs on `npm start`: the
|
|
6
|
+
// securelock this dApp is published as, the trustedzone it was built against,
|
|
7
|
+
// the network's token address and chain id, the -unsafe network when the dApp
|
|
8
|
+
// runs without a CAS (null otherwise), and the IPFS endpoint.
|
|
6
9
|
const PROJECT_NAME = "";
|
|
10
|
+
const TRUSTED_ZONE_IMAGE = "";
|
|
11
|
+
const NETWORK_ADDRESS = "";
|
|
12
|
+
const CHAIN_ID = null;
|
|
13
|
+
const UNSAFE_NETWORK = null;
|
|
7
14
|
const IPFS_ENDPOINT = "";
|
|
8
15
|
|
|
16
|
+
// A call into src/serverless/backend.py; its return value is the task result.
|
|
9
17
|
const code = `hello("World")`;
|
|
10
18
|
|
|
11
19
|
function App() {
|
|
12
20
|
const executeTask = async () => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
console.log(PROJECT_NAME)
|
|
18
|
-
const onTaskProgress = (e) => {
|
|
19
|
-
if (e.detail.status === ECStatus.ERROR) {
|
|
20
|
-
console.error(e.detail.message);
|
|
21
|
-
} else {
|
|
22
|
-
console.log(e.detail.message);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const onTaskCompleted = (e) => {
|
|
27
|
-
console.log(`Task Result: ${e.detail.message.result}`);
|
|
28
|
-
// display the result in page below the buttons
|
|
29
|
-
const result = document.createElement("p");
|
|
30
|
-
result.innerHTML = `Task Result: ${e.detail.message.result}`;
|
|
31
|
-
document.body.appendChild(result);
|
|
21
|
+
// The browser wallet (MetaMask) signs and pays for the order.
|
|
22
|
+
const runner = new EthernityCloudRunner(NETWORK_ADDRESS, {}, CHAIN_ID || undefined);
|
|
23
|
+
if (UNSAFE_NETWORK) {
|
|
24
|
+
await runner.setNetwork(...UNSAFE_NETWORK);
|
|
32
25
|
}
|
|
26
|
+
runner.initializeStorage(IPFS_ENDPOINT);
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
runner.addEventListener(
|
|
28
|
+
// Events are named by task status; detail is { message, status, progress }.
|
|
29
|
+
runner.addEventListener(ECStatus.DEFAULT, (e) => {
|
|
30
|
+
console.log(`[${e.detail.progress}] ${e.detail.message}`);
|
|
31
|
+
});
|
|
32
|
+
runner.addEventListener(ECStatus.ERROR, (e) => {
|
|
33
|
+
console.error(e.detail.message);
|
|
34
|
+
});
|
|
35
|
+
runner.addEventListener(ECStatus.SUCCESS, async () => {
|
|
36
|
+
const result = await runner.getResult();
|
|
37
|
+
console.log(`Task Result: ${result}`);
|
|
38
|
+
// display the result in page below the buttons
|
|
39
|
+
const line = document.createElement("p");
|
|
40
|
+
line.textContent = `Task Result: ${result}`;
|
|
41
|
+
document.body.appendChild(line);
|
|
42
|
+
});
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
'0xd58f5C1834279ABD601df85b3E4b2323aDD4E75e',
|
|
40
|
-
{ taskPrice: 6, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1 });
|
|
44
|
+
const resources = { taskPrice: 10, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1 };
|
|
45
|
+
await runner.run(resources, PROJECT_NAME, code, '', TRUSTED_ZONE_IMAGE);
|
|
41
46
|
};
|
|
47
|
+
|
|
42
48
|
const connectWallet = async () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
};
|
|
49
|
+
if (!window.ethereum) {
|
|
50
|
+
console.log('Please install MetaMask!');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await window.ethereum.request({ method: 'eth_requestAccounts' });
|
|
55
|
+
console.log("Wallet connected");
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error("User denied account access");
|
|
58
|
+
}
|
|
59
|
+
};
|
|
56
60
|
|
|
57
61
|
return (
|
|
58
62
|
<div className="container">
|
|
@@ -61,4 +65,4 @@ function App() {
|
|
|
61
65
|
</div>
|
|
62
66
|
);
|
|
63
67
|
}
|
|
64
|
-
export default App;
|
|
68
|
+
export default App;
|
package/pynithy/src/preStart.mjs
CHANGED
|
@@ -1,57 +1,47 @@
|
|
|
1
|
+
// Runs before `react-scripts start` (the project's `npm start`): fills the
|
|
2
|
+
// constants at the top of src/ec_helloworld_example.js from the project's
|
|
3
|
+
// .env, the way ecld-run reads the same values. PROJECT_NAME and
|
|
4
|
+
// TRUSTED_ZONE_IMAGE take their -unsafe form on an -unsafe network; the
|
|
5
|
+
// network's token address, chain id and -unsafe (network, type) come from the
|
|
6
|
+
// runner's own enums through the SDK's network table.
|
|
1
7
|
import fs from 'fs';
|
|
8
|
+
import { createRequire } from 'module';
|
|
2
9
|
import dotenv from 'dotenv';
|
|
3
|
-
|
|
10
|
+
import * as enums from '@ethernity-cloud/runner/enums.js';
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'ecld-
|
|
12
|
+
dotenv.config();
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const casConfig = require('@ethernity-cloud/sdk-js/cas/config.js');
|
|
15
|
+
const { networkFor } = require('@ethernity-cloud/sdk-js/network.js');
|
|
16
|
+
|
|
17
|
+
const { PROJECT_NAME, TRUSTED_ZONE_IMAGE, BLOCKCHAIN_NETWORK, IPFS_ENDPOINT } = process.env;
|
|
18
|
+
if (!PROJECT_NAME || !BLOCKCHAIN_NETWORK) {
|
|
19
|
+
console.error('preStart: PROJECT_NAME and BLOCKCHAIN_NETWORK are not set in .env; run `npm run ecld-init` first.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const { network, known } = networkFor(enums, BLOCKCHAIN_NETWORK);
|
|
23
|
+
if (!network) {
|
|
24
|
+
console.error(`preStart: unknown BLOCKCHAIN_NETWORK '${BLOCKCHAIN_NETWORK}' in .env. Known: ${known.join(', ')}`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const constants = {
|
|
29
|
+
PROJECT_NAME: casConfig.nameOnNetwork(PROJECT_NAME, BLOCKCHAIN_NETWORK),
|
|
30
|
+
TRUSTED_ZONE_IMAGE: casConfig.nameOnNetwork(TRUSTED_ZONE_IMAGE, BLOCKCHAIN_NETWORK) || '',
|
|
31
|
+
NETWORK_ADDRESS: network.address,
|
|
32
|
+
CHAIN_ID: network.chainId || null,
|
|
33
|
+
UNSAFE_NETWORK: network.unsafe || null,
|
|
34
|
+
IPFS_ENDPOINT: IPFS_ENDPOINT || 'https://ipfs.ethernity.cloud',
|
|
13
35
|
};
|
|
14
36
|
|
|
15
37
|
const filePath = 'src/ec_helloworld_example.js';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const imageRegistryPath = 'node_modules/@ethernity-cloud/runner/contract/operation/imageRegistryContract.js';
|
|
28
|
-
const imageRegistryContent = fs.readFileSync(imageRegistryPath, 'utf8');
|
|
29
|
-
|
|
30
|
-
// Log the original content for debugging
|
|
31
|
-
// console.log('Original imageRegistryContent:', imageRegistryContent);
|
|
32
|
-
|
|
33
|
-
// Replace the content in imageRegistryContract.js
|
|
34
|
-
// const updatedImageRegistryContent = imageRegistryContent.replace(/getLatestTrustedZoneImageCertPublicKey\([^)]*\);/, "getLatestTrustedZoneImageCertPublicKey('" + process.env.ENCLAVE_NAME_TRUSTEDZONE + "', 'v3')").replace(/getLatestImageVersionPublicKey\([^)]*\)/, "getLatestImageVersionPublicKey(imageName, '" + process.env.VERSION + "')");
|
|
35
|
-
const updatedImageRegistryContent = imageRegistryContent.replace(
|
|
36
|
-
/async getEnclaveDetailsV3\(.*?\{[\s\S]*?\}\s*\}/,
|
|
37
|
-
`async getEnclaveDetailsV3(imageName, version) {
|
|
38
|
-
try {
|
|
39
|
-
const trustedZonePublicKey = (await this.contract.getLatestTrustedZoneImageCertPublicKey('${process.env.ENCLAVE_NAME_TRUSTEDZONE}', 'v3'));
|
|
40
|
-
const imageDetails = await this.contract.getLatestImageVersionPublicKey(imageName, '${process.env.VERSION}');
|
|
41
|
-
return [imageDetails[0], trustedZonePublicKey[1], imageDetails[2]];
|
|
42
|
-
} catch (e) {
|
|
43
|
-
console.log(e);
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
}`
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
fs.writeFileSync(imageRegistryPath, updatedImageRegistryContent, 'utf8');
|
|
51
|
-
|
|
52
|
-
const runnerPath = 'node_modules/@ethernity-cloud/runner/runner.js';
|
|
53
|
-
const runnerContent = fs.readFileSync(runnerPath, 'utf8');
|
|
54
|
-
|
|
55
|
-
const updatedRunnerContent = runnerContent.replace(/this.#enclaveImageIPFSHash}:.*?:/, "this.#enclaveImageIPFSHash}:"+process.env.ENCLAVE_NAME_TRUSTEDZONE+":").replace(/new ImageRegistryContract\([^)]*\);/, "new ImageRegistryContract(this.#networkAddress, '"+process.env.ENCLAVE_NAME_TRUSTEDZONE+"');");
|
|
56
|
-
|
|
57
|
-
fs.writeFileSync(runnerPath, updatedRunnerContent, 'utf8');
|
|
38
|
+
let content = fs.readFileSync(filePath, 'utf8');
|
|
39
|
+
for (const [name, value] of Object.entries(constants)) {
|
|
40
|
+
const line = new RegExp(`^const ${name} = .*;$`, 'm');
|
|
41
|
+
if (!line.test(content)) {
|
|
42
|
+
console.error(`preStart: ${filePath} has no 'const ${name} = ...;' line to fill.`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
content = content.replace(line, `const ${name} = ${JSON.stringify(value)};`);
|
|
46
|
+
}
|
|
47
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
package/run.js
CHANGED
|
@@ -40,48 +40,10 @@
|
|
|
40
40
|
const fs = require('fs');
|
|
41
41
|
try { require('dotenv').config(); } catch (e) { /* dotenv optional */ }
|
|
42
42
|
const casConfig = require('./cas/config.js');
|
|
43
|
+
const { networkFor, unsafeVariant } = require('./network.js');
|
|
43
44
|
|
|
44
45
|
const DEFAULT_IPFS = 'https://ipfs.ethernity.cloud/api/v0';
|
|
45
46
|
|
|
46
|
-
/* Map a BLOCKCHAIN_NETWORK token (as ecld-init writes it, spaces -> underscores)
|
|
47
|
-
* to the runner's network: its token ADDRESS, the chain id of a testnet whose
|
|
48
|
-
* token address other testnets share, and for an -unsafe network the
|
|
49
|
-
* (network, type) the runner is set to, which runs only -unsafe trustedzones.
|
|
50
|
-
* Built from the runner's own enums so it can't drift. Accepts a few spellings
|
|
51
|
-
* per network. */
|
|
52
|
-
function networkFor({ ECAddress, ECNetworkByChainId }, raw) {
|
|
53
|
-
const key = String(raw || '').trim().toUpperCase().replace(/\s+/g, '_');
|
|
54
|
-
const bloxbergTestnet = { address: ECAddress.BLOXBERG.TESTNET_ADDRESS };
|
|
55
|
-
const amoy = { address: ECAddress.POLYGON.TESTNET_ADDRESS };
|
|
56
|
-
const sepolia = { address: ECAddress.SEPOLIA.TESTNET_ADDRESS, chainId: ECNetworkByChainId.SEPOLIA.TESTNET };
|
|
57
|
-
const litvm = { address: ECAddress.LITVM.TESTNET_ADDRESS, chainId: ECNetworkByChainId.LITVM.TESTNET };
|
|
58
|
-
const table = {
|
|
59
|
-
BLOXBERG_TESTNET: bloxbergTestnet,
|
|
60
|
-
BLOXBERG_TESTNET_UNSAFE: { ...bloxbergTestnet, unsafe: ['BLOXBERG', 'TESTNET_UNSAFE'] },
|
|
61
|
-
BLOXBERG_MAINNET: { address: ECAddress.BLOXBERG.MAINNET_ADDRESS },
|
|
62
|
-
POLYGON_MAINNET: { address: ECAddress.POLYGON.MAINNET_ADDRESS },
|
|
63
|
-
POLYGON_AMOY: amoy,
|
|
64
|
-
POLYGON_AMOY_TESTNET: amoy,
|
|
65
|
-
IOTEX_TESTNET: { address: ECAddress.IOTEX.TESTNET_ADDRESS, chainId: ECNetworkByChainId.IOTEX.TESTNET },
|
|
66
|
-
ETHEREUM_SEPOLIA: sepolia,
|
|
67
|
-
SEPOLIA: sepolia,
|
|
68
|
-
LITVM_LITEFORGE: litvm,
|
|
69
|
-
LITVM: litvm,
|
|
70
|
-
LITVM_LITEFORGE_UNSAFE: { ...litvm, unsafe: ['LITVM', 'TESTNET_UNSAFE'] },
|
|
71
|
-
};
|
|
72
|
-
return { key, network: table[key] || null, known: Object.keys(table) };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* The -unsafe network a network token names, or whose sibling it names; null
|
|
76
|
-
* when the network has no -unsafe variant. */
|
|
77
|
-
function unsafeVariant(raw) {
|
|
78
|
-
const key = String(raw || '').trim().replace(/\s+/g, '_');
|
|
79
|
-
if (casConfig.isUnsafeNetwork(key)) return key;
|
|
80
|
-
const variant = Object.keys(casConfig.UNSAFE_NETWORKS)
|
|
81
|
-
.find((name) => casConfig.UNSAFE_NETWORKS[name].toUpperCase() === key.toUpperCase());
|
|
82
|
-
return variant || null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
47
|
function parseArgs(argv) {
|
|
86
48
|
const opts = { ipfs: DEFAULT_IPFS, timeout: 600, taskPrice: 3, cpu: 1, memory: 1, storage: 10, bandwidth: 1, duration: 1, validators: 1, node: '' };
|
|
87
49
|
const positional = [];
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
require('dotenv').config();
|
|
3
|
-
|
|
4
|
-
const filePath = 'src/ec_helloworld_example.js';
|
|
5
|
-
const fileContent = fs.readFileSync(filePath, 'utf8');
|
|
6
|
-
|
|
7
|
-
const updatedContent = fileContent
|
|
8
|
-
.replace(/const PROJECT_NAME = ".*?";/, `const PROJECT_NAME = "${process.env.PROJECT_NAME}";`)
|
|
9
|
-
.replace(/const IPFS_ENDPOINT = ".*?";/, `const IPFS_ENDPOINT = "${process.env.IPFS_ENDPOINT}";`)
|
|
10
|
-
|
|
11
|
-
fs.writeFileSync(filePath, updatedContent, 'utf8');
|
|
12
|
-
|
|
13
|
-
// const code = updatedContent.match(/const code = `hello\("(.*?)"\);/)[1];
|
|
14
|
-
|
|
15
|
-
const imageRegistryPath = 'node_modules/@ethernity-cloud/runner/contract/operation/imageRegistryContract.js';
|
|
16
|
-
const imageRegistryContent = fs.readFileSync(imageRegistryPath, 'utf8');
|
|
17
|
-
|
|
18
|
-
// Log the original content for debugging
|
|
19
|
-
// console.log('Original imageRegistryContent:', imageRegistryContent);
|
|
20
|
-
|
|
21
|
-
// Replace the content in imageRegistryContract.js
|
|
22
|
-
// const updatedImageRegistryContent = imageRegistryContent.replace(/getLatestTrustedZoneImageCertPublicKey\([^)]*\);/, "getLatestTrustedZoneImageCertPublicKey('" + process.env.ENCLAVE_NAME_TRUSTEDZONE + "', 'v3')").replace(/getLatestImageVersionPublicKey\([^)]*\)/, "getLatestImageVersionPublicKey(imageName, '" + process.env.VERSION + "')");
|
|
23
|
-
const updatedImageRegistryContent = imageRegistryContent.replace(
|
|
24
|
-
/async getEnclaveDetailsV3\(.*?\{[\s\S]*?\}\s*\}/,
|
|
25
|
-
`async getEnclaveDetailsV3(imageName, version) {
|
|
26
|
-
try {
|
|
27
|
-
const trustedZonePublicKey = (await this.contract.getLatestTrustedZoneImageCertPublicKey('${process.env.ENCLAVE_NAME_TRUSTEDZONE}', 'v3'));
|
|
28
|
-
const imageDetails = await this.contract.getLatestImageVersionPublicKey(imageName, '${process.env.VERSION}');
|
|
29
|
-
return [imageDetails[0], trustedZonePublicKey[1], imageDetails[2]];
|
|
30
|
-
} catch (e) {
|
|
31
|
-
console.log(e);
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
}`
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
fs.writeFileSync(imageRegistryPath, updatedImageRegistryContent, 'utf8');
|
|
39
|
-
|
|
40
|
-
const runnerPath = 'node_modules/@ethernity-cloud/runner/runner.js';
|
|
41
|
-
const runnerContent = fs.readFileSync(runnerPath, 'utf8');
|
|
42
|
-
|
|
43
|
-
const updatedRunnerContent = runnerContent.replace(/this.#enclaveImageIPFSHash}:.*?:/, "this.#enclaveImageIPFSHash}:"+process.env.ENCLAVE_NAME_TRUSTEDZONE+":").replace(/new ImageRegistryContract\([^)]*\);/, "new ImageRegistryContract(this.#networkAddress, '"+process.env.ENCLAVE_NAME_TRUSTEDZONE+"');");
|
|
44
|
-
|
|
45
|
-
fs.writeFileSync(runnerPath, updatedRunnerContent, 'utf8');
|