agoric 0.21.2-mainnet1B-dev-26244e8.0 → 0.21.2-orchestration-dev-096c4e8.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/package.json +48 -35
- package/src/anylogger-agoric.js +28 -14
- package/src/bin-agops.js +9 -8
- package/src/chain-config.js +11 -11
- package/src/commands/auction.js +6 -3
- package/src/commands/{ec.js → gov.js} +177 -38
- package/src/commands/inter.js +14 -31
- package/src/commands/oracle.js +32 -17
- package/src/commands/perf.js +0 -2
- package/src/commands/psm.js +11 -15
- package/src/commands/reserve.js +1 -2
- package/src/commands/test-upgrade.js +7 -2
- package/src/commands/vaults.js +6 -8
- package/src/commands/wallet.js +12 -8
- package/src/cosmos.js +2 -2
- package/src/follow.js +6 -3
- package/src/helpers.js +1 -0
- package/src/init.js +5 -8
- package/src/install.js +8 -6
- package/src/lib/chain.js +30 -20
- package/src/lib/format.js +9 -14
- package/src/lib/rpc.js +17 -5
- package/src/lib/wallet.js +26 -55
- package/src/main-publish.js +1 -2
- package/src/main.js +43 -45
- package/src/open.js +6 -6
- package/src/publish.js +4 -13
- package/src/sdk-package-names.js +9 -5
- package/src/set-defaults.js +1 -0
- package/src/start.js +53 -59
- package/tools/getting-started.js +273 -0
- package/tools/resm-plugin/deploy.js +18 -0
- package/tools/resm-plugin/package.json +12 -0
- package/tools/resm-plugin/src/output.js +1 -0
- package/tools/resm-plugin/src/plugin.js +17 -0
- package/CHANGELOG.md +0 -1086
package/src/start.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-floating-promises: "warn" */
|
|
1
2
|
/* global process setTimeout */
|
|
2
3
|
import chalk from 'chalk';
|
|
3
4
|
import { createHash } from 'crypto';
|
|
@@ -40,6 +41,7 @@ const DELEGATE0_COINS = `50000000${STAKING_DENOM}`;
|
|
|
40
41
|
const SOLO_COINS = `13000000${STAKING_DENOM},500000000${CENTRAL_DENOM}`;
|
|
41
42
|
const CHAIN_ID = 'agoriclocal';
|
|
42
43
|
|
|
44
|
+
const SERVERS_ROOT_DIR = '_agstate/agoric-servers';
|
|
43
45
|
const FAKE_CHAIN_DELAY =
|
|
44
46
|
process.env.FAKE_CHAIN_DELAY === undefined
|
|
45
47
|
? 0
|
|
@@ -69,10 +71,10 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
69
71
|
const pspawnEnv = { ...process.env };
|
|
70
72
|
if (opts.verbose > 1) {
|
|
71
73
|
// Loudly verbose logs (nondeterministic).
|
|
72
|
-
pspawnEnv.DEBUG = 'agoric,SwingSet:vat,SwingSet:ls';
|
|
74
|
+
pspawnEnv.DEBUG = 'agoric:debug,SwingSet:vat,SwingSet:ls';
|
|
73
75
|
} else if (opts.verbose) {
|
|
74
76
|
// Verbose vat logs (nondeterministic).
|
|
75
|
-
pspawnEnv.DEBUG = 'SwingSet:vat,SwingSet:ls';
|
|
77
|
+
pspawnEnv.DEBUG = 'agoric:info,SwingSet:vat,SwingSet:ls';
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
const pspawn = makePspawn({ env: pspawnEnv, spawn, log, chalk });
|
|
@@ -151,6 +153,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
151
153
|
]);
|
|
152
154
|
|
|
153
155
|
const exists = async file => {
|
|
156
|
+
await null;
|
|
154
157
|
try {
|
|
155
158
|
await fs.stat(file);
|
|
156
159
|
return true;
|
|
@@ -159,6 +162,12 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
159
162
|
}
|
|
160
163
|
};
|
|
161
164
|
|
|
165
|
+
const rmVerbose = async filePath => {
|
|
166
|
+
log(chalk.green(`removing ${filePath}`));
|
|
167
|
+
// rm is available on all the unix-likes, so use it for speed.
|
|
168
|
+
await pspawn('rm', ['-rf', filePath]);
|
|
169
|
+
};
|
|
170
|
+
|
|
162
171
|
let agSolo;
|
|
163
172
|
let agSoloBuild;
|
|
164
173
|
if (opts.dockerTag) {
|
|
@@ -171,12 +180,11 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
171
180
|
const fakeDelay =
|
|
172
181
|
popts.delay === undefined ? FAKE_CHAIN_DELAY : Number(popts.delay);
|
|
173
182
|
|
|
174
|
-
const
|
|
183
|
+
const serverDir = `${SERVERS_ROOT_DIR}/${profileName}`;
|
|
175
184
|
|
|
185
|
+
await null;
|
|
176
186
|
if (popts.reset) {
|
|
177
|
-
|
|
178
|
-
// rm is available on all the unix-likes, so use it for speed.
|
|
179
|
-
await pspawn('rm', ['-rf', agServer]);
|
|
187
|
+
await rmVerbose(serverDir);
|
|
180
188
|
}
|
|
181
189
|
|
|
182
190
|
if (!opts.dockerTag) {
|
|
@@ -197,14 +205,14 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
const fakeGCI = 'sim-chain';
|
|
200
|
-
const serverExists = await exists(
|
|
208
|
+
const serverExists = await exists(serverDir);
|
|
201
209
|
if (!serverExists) {
|
|
202
210
|
log(chalk.yellow(`initializing ${profileName}`));
|
|
203
211
|
await pspawn(
|
|
204
212
|
agSolo,
|
|
205
213
|
['init', profileName, '--egresses=fake', `--webport=${HOST_PORT}`],
|
|
206
214
|
{
|
|
207
|
-
cwd:
|
|
215
|
+
cwd: SERVERS_ROOT_DIR,
|
|
208
216
|
},
|
|
209
217
|
);
|
|
210
218
|
}
|
|
@@ -215,7 +223,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
215
223
|
agSolo,
|
|
216
224
|
['set-fake-chain', `--delay=${fakeDelay}`, fakeGCI],
|
|
217
225
|
{
|
|
218
|
-
cwd:
|
|
226
|
+
cwd: serverDir,
|
|
219
227
|
},
|
|
220
228
|
);
|
|
221
229
|
}
|
|
@@ -226,7 +234,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
const ps = pspawn(agSolo, [...debugOpts, 'start'], {
|
|
229
|
-
cwd:
|
|
237
|
+
cwd: serverDir,
|
|
230
238
|
env: nodeDebugEnv,
|
|
231
239
|
});
|
|
232
240
|
process.on('SIGINT', () => ps.childProcess.kill('SIGINT'));
|
|
@@ -246,6 +254,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
246
254
|
}
|
|
247
255
|
|
|
248
256
|
const { cosmosChain, cosmosChainBuild } = getSDKBinaries(sdkPrefixes);
|
|
257
|
+
await null;
|
|
249
258
|
if (popts.pull || popts.rebuild) {
|
|
250
259
|
if (popts.dockerTag) {
|
|
251
260
|
const exitStatus = await pspawn('docker', ['pull', SDK_IMAGE]);
|
|
@@ -263,17 +272,15 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
263
272
|
}
|
|
264
273
|
}
|
|
265
274
|
|
|
266
|
-
const
|
|
275
|
+
const serverDir = `${SERVERS_ROOT_DIR}/${profileName}-${portNum}`;
|
|
267
276
|
if (popts.reset) {
|
|
268
|
-
|
|
269
|
-
// rm is available on all the unix-likes, so use it for speed.
|
|
270
|
-
await pspawn('rm', ['-rf', agServer]);
|
|
277
|
+
await rmVerbose(serverDir);
|
|
271
278
|
}
|
|
272
279
|
|
|
273
280
|
let chainSpawn;
|
|
274
281
|
if (!popts.dockerTag) {
|
|
275
282
|
chainSpawn = (args, spawnOpts = undefined) => {
|
|
276
|
-
return pspawn(cosmosChain, [...args, `--home=${
|
|
283
|
+
return pspawn(cosmosChain, [...args, `--home=${serverDir}`], spawnOpts);
|
|
277
284
|
};
|
|
278
285
|
} else {
|
|
279
286
|
chainSpawn = (args, spawnOpts = undefined, dockerArgs = []) =>
|
|
@@ -287,13 +294,13 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
287
294
|
...terminalOnlyFlags(`-it`),
|
|
288
295
|
SDK_IMAGE,
|
|
289
296
|
...args,
|
|
290
|
-
`--home=/usr/src/dapp/${
|
|
297
|
+
`--home=/usr/src/dapp/${serverDir}`,
|
|
291
298
|
],
|
|
292
299
|
spawnOpts,
|
|
293
300
|
);
|
|
294
301
|
}
|
|
295
302
|
|
|
296
|
-
const serverExists = await exists(
|
|
303
|
+
const serverExists = await exists(serverDir);
|
|
297
304
|
if (!serverExists) {
|
|
298
305
|
const exitStatus = await chainSpawn([
|
|
299
306
|
'init',
|
|
@@ -308,7 +315,6 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
308
315
|
// Get or create the essential addresses.
|
|
309
316
|
const addrs = {};
|
|
310
317
|
for (const keyName of ['provision', 'delegate0']) {
|
|
311
|
-
/* eslint-disable no-await-in-loop */
|
|
312
318
|
let statusOut = showKey(keyName);
|
|
313
319
|
const exitStatusOut = await statusOut[0];
|
|
314
320
|
if (exitStatusOut) {
|
|
@@ -331,7 +337,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
331
337
|
/* eslint-enable no-await-in-loop */
|
|
332
338
|
}
|
|
333
339
|
|
|
334
|
-
const genesisFile = `${
|
|
340
|
+
const genesisFile = `${serverDir}/config/genesis.json`;
|
|
335
341
|
const stampExists = await exists(`${genesisFile}.stamp`);
|
|
336
342
|
if (!stampExists) {
|
|
337
343
|
let exitStatus;
|
|
@@ -361,7 +367,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
361
367
|
`--keyring-dir=${keysHome}`,
|
|
362
368
|
'--keyring-backend=test',
|
|
363
369
|
`--chain-id=${CHAIN_ID}`,
|
|
364
|
-
|
|
370
|
+
DELEGATE0_COINS,
|
|
365
371
|
]);
|
|
366
372
|
if (exitStatus) {
|
|
367
373
|
return exitStatus;
|
|
@@ -382,8 +388,8 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
382
388
|
|
|
383
389
|
// Complete the genesis file and launch the chain.
|
|
384
390
|
log('read ag-chain-cosmos config');
|
|
385
|
-
const configFile = `${
|
|
386
|
-
const appFile = `${
|
|
391
|
+
const configFile = `${serverDir}/config/config.toml`;
|
|
392
|
+
const appFile = `${serverDir}/config/app.toml`;
|
|
387
393
|
const [genesisJson, configToml, appToml] = await Promise.all([
|
|
388
394
|
fs.readFile(genesisFile, 'utf-8'),
|
|
389
395
|
fs.readFile(configFile, 'utf-8'),
|
|
@@ -446,9 +452,10 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
446
452
|
return 1;
|
|
447
453
|
}
|
|
448
454
|
|
|
449
|
-
const
|
|
455
|
+
const serverDir = `${SERVERS_ROOT_DIR}/${profileName}-${portNum}`;
|
|
450
456
|
|
|
451
457
|
const { cosmosClientBuild } = getSDKBinaries(sdkPrefixes);
|
|
458
|
+
await null;
|
|
452
459
|
if (popts.pull || popts.rebuild) {
|
|
453
460
|
if (popts.dockerTag) {
|
|
454
461
|
const exitStatus = await pspawn('docker', ['pull', SDK_IMAGE]);
|
|
@@ -474,9 +481,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
474
481
|
}
|
|
475
482
|
|
|
476
483
|
if (popts.reset) {
|
|
477
|
-
|
|
478
|
-
// rm is available on all the unix-likes, so use it for speed.
|
|
479
|
-
await pspawn('rm', ['-rf', agServer]);
|
|
484
|
+
await rmVerbose(serverDir);
|
|
480
485
|
}
|
|
481
486
|
|
|
482
487
|
let soloSpawn;
|
|
@@ -491,7 +496,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
491
496
|
'run',
|
|
492
497
|
`--volume=${process.cwd()}:/usr/src/dapp`,
|
|
493
498
|
`--volume=${process.env.HOME}/.agoric:/root/.agoric`,
|
|
494
|
-
`-eAG_SOLO_BASEDIR=/usr/src/dapp/${
|
|
499
|
+
`-eAG_SOLO_BASEDIR=/usr/src/dapp/${serverDir}`,
|
|
495
500
|
`--rm`,
|
|
496
501
|
...terminalOnlyFlags(`-it`),
|
|
497
502
|
`--entrypoint=ag-solo`,
|
|
@@ -503,7 +508,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
503
508
|
);
|
|
504
509
|
}
|
|
505
510
|
|
|
506
|
-
const serverExists = await exists(
|
|
511
|
+
const serverExists = await exists(serverDir);
|
|
507
512
|
// Initialise the solo directory and key.
|
|
508
513
|
if (!serverExists) {
|
|
509
514
|
const initArgs = [`--webport=${portNum}`];
|
|
@@ -511,7 +516,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
511
516
|
initArgs.push(`--webhost=0.0.0.0`);
|
|
512
517
|
}
|
|
513
518
|
const exitStatus = await soloSpawn(
|
|
514
|
-
['init',
|
|
519
|
+
['init', serverDir, ...initArgs],
|
|
515
520
|
undefined,
|
|
516
521
|
[`--workdir=/usr/src/dapp`],
|
|
517
522
|
);
|
|
@@ -522,15 +527,15 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
522
527
|
|
|
523
528
|
// Create the full economy chain config.
|
|
524
529
|
const agServerResolve = spec =>
|
|
525
|
-
require.resolve(spec, { paths: [
|
|
530
|
+
require.resolve(spec, { paths: [serverDir] });
|
|
526
531
|
const coreConfigPath = agServerResolve(
|
|
527
|
-
'@agoric/
|
|
532
|
+
'@agoric/vm-config/decentral-core-config.json',
|
|
528
533
|
);
|
|
529
534
|
const economyTemplPath = agServerResolve(
|
|
530
535
|
'@agoric/cosmic-swingset/economy-template.json',
|
|
531
536
|
);
|
|
532
537
|
const [rawSoloAddr, coreConfigJson, economyTemplJson] = await Promise.all([
|
|
533
|
-
fs.readFile(`${
|
|
538
|
+
fs.readFile(`${serverDir}/ag-cosmos-helper-address`, 'utf-8'),
|
|
534
539
|
fs.readFile(coreConfigPath, 'utf-8'),
|
|
535
540
|
fs.readFile(economyTemplPath, 'utf-8'),
|
|
536
541
|
]);
|
|
@@ -541,7 +546,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
541
546
|
const economyConfig = JSON.parse(coreConfigJson);
|
|
542
547
|
economyConfig.coreProposals = economyProposals;
|
|
543
548
|
await fs.writeFile(
|
|
544
|
-
`${
|
|
549
|
+
`${serverDir}/decentral-economy-config.json`,
|
|
545
550
|
JSON.stringify(economyConfig, null, 2),
|
|
546
551
|
);
|
|
547
552
|
|
|
@@ -549,13 +554,12 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
549
554
|
return 0;
|
|
550
555
|
}
|
|
551
556
|
|
|
552
|
-
const gciFile =
|
|
557
|
+
const gciFile = `${SERVERS_ROOT_DIR}/local-chain-${CHAIN_PORT}/config/genesis.json.sha256`;
|
|
553
558
|
process.stdout.write(`Waiting for local-chain-${CHAIN_PORT} to start...`);
|
|
554
559
|
let hasGci = false;
|
|
555
560
|
for await (const _ of untilTrue(() => hasGci)) {
|
|
556
561
|
process.stdout.write('.');
|
|
557
562
|
|
|
558
|
-
// eslint-disable-next-line no-await-in-loop
|
|
559
563
|
await new Promise((resolve, reject) => {
|
|
560
564
|
fs.stat(gciFile).then(
|
|
561
565
|
_2 => {
|
|
@@ -576,7 +580,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
576
580
|
|
|
577
581
|
const spawnOpts = {};
|
|
578
582
|
if (!popts.dockerTag) {
|
|
579
|
-
spawnOpts.cwd =
|
|
583
|
+
spawnOpts.cwd = serverDir;
|
|
580
584
|
}
|
|
581
585
|
|
|
582
586
|
const rpcAddrs = [`localhost:${CHAIN_PORT}`];
|
|
@@ -590,7 +594,6 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
590
594
|
let bestRpcAddr;
|
|
591
595
|
for await (const _ of untilTrue(() => bestRpcAddr)) {
|
|
592
596
|
for await (const rpcAddr of rpcAddrs) {
|
|
593
|
-
// eslint-disable-next-line no-await-in-loop
|
|
594
597
|
exitStatus = await keysSpawn([
|
|
595
598
|
'query',
|
|
596
599
|
'swingset',
|
|
@@ -639,7 +642,6 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
639
642
|
];
|
|
640
643
|
for (/* await */ const cmd of provCmds) {
|
|
641
644
|
const statusOut = capture(keysSpawn, cmd, true);
|
|
642
|
-
// eslint-disable-next-line no-await-in-loop
|
|
643
645
|
exitStatus = await statusOut[0];
|
|
644
646
|
if (!exitStatus) {
|
|
645
647
|
const json = statusOut[1].replace(/^gas estimate: \d+$/m, '');
|
|
@@ -664,7 +666,6 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
664
666
|
}
|
|
665
667
|
}
|
|
666
668
|
if (!bestRpcAddr) {
|
|
667
|
-
// eslint-disable-next-line no-await-in-loop
|
|
668
669
|
await delay(2000);
|
|
669
670
|
}
|
|
670
671
|
}
|
|
@@ -690,6 +691,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
690
691
|
}
|
|
691
692
|
|
|
692
693
|
async function startTestnetDocker(profileName, startArgs, popts) {
|
|
694
|
+
await null;
|
|
693
695
|
if (popts.dockerTag && popts.pull) {
|
|
694
696
|
const exitStatus = await pspawn('docker', ['pull', SOLO_IMAGE]);
|
|
695
697
|
if (exitStatus) {
|
|
@@ -699,12 +701,10 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
699
701
|
|
|
700
702
|
const port = startArgs[0] || PORT;
|
|
701
703
|
const netconfig = startArgs[1] || DEFAULT_NETCONFIG;
|
|
702
|
-
const
|
|
704
|
+
const serverDir = `${SERVERS_ROOT_DIR}/${profileName}-${port}`;
|
|
703
705
|
|
|
704
706
|
if (popts.reset) {
|
|
705
|
-
|
|
706
|
-
// rm is available on all the unix-likes, so use it for speed.
|
|
707
|
-
await pspawn('rm', ['-rf', agServer]);
|
|
707
|
+
await rmVerbose(serverDir);
|
|
708
708
|
}
|
|
709
709
|
|
|
710
710
|
const setupRun = (...bonusArgs) =>
|
|
@@ -712,7 +712,7 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
712
712
|
'run',
|
|
713
713
|
`-p127.0.0.1:${HOST_PORT}:${port}`,
|
|
714
714
|
`--volume=${process.cwd()}:/usr/src/dapp`,
|
|
715
|
-
`-eAG_SOLO_BASEDIR=/usr/src/dapp/${
|
|
715
|
+
`-eAG_SOLO_BASEDIR=/usr/src/dapp/${serverDir}`,
|
|
716
716
|
`--rm`,
|
|
717
717
|
...terminalOnlyFlags(`-it`),
|
|
718
718
|
SOLO_IMAGE,
|
|
@@ -727,44 +727,38 @@ export default async function startMain(progname, rawArgs, powers, opts) {
|
|
|
727
727
|
async function startTestnetSdk(profileName, startArgs, popts) {
|
|
728
728
|
const port = startArgs[0] || PORT;
|
|
729
729
|
const netconfig = startArgs[1] || DEFAULT_NETCONFIG;
|
|
730
|
-
const
|
|
730
|
+
const serverDir = `${SERVERS_ROOT_DIR}/${profileName}-${port}`;
|
|
731
731
|
|
|
732
|
+
await null;
|
|
732
733
|
if (popts.reset) {
|
|
733
|
-
|
|
734
|
-
// rm is available on all the unix-likes, so use it for speed.
|
|
735
|
-
await pspawn('rm', ['-rf', agServer]);
|
|
734
|
+
await rmVerbose(serverDir);
|
|
736
735
|
}
|
|
737
736
|
|
|
738
737
|
const setupRun = (...bonusArgs) =>
|
|
739
738
|
pspawn(agSolo, [`--webport=${port}`, ...bonusArgs], {
|
|
740
|
-
env: { ...pspawnEnv, AG_SOLO_BASEDIR:
|
|
739
|
+
env: { ...pspawnEnv, AG_SOLO_BASEDIR: serverDir },
|
|
741
740
|
});
|
|
742
741
|
|
|
743
742
|
return setupRun('setup', `--netconfig=${netconfig}`);
|
|
744
743
|
}
|
|
745
744
|
|
|
746
745
|
const profiles = {
|
|
746
|
+
__proto__: null,
|
|
747
747
|
dev: startFakeChain,
|
|
748
748
|
'local-chain': startLocalChain,
|
|
749
749
|
'local-solo': startLocalSolo,
|
|
750
750
|
testnet: opts.dockerTag ? startTestnetDocker : startTestnetSdk,
|
|
751
751
|
};
|
|
752
752
|
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
const args = rawArgs.slice(1);
|
|
756
|
-
const profileName = args[0] || 'dev';
|
|
753
|
+
const [_command = 'start', profileName = 'dev', ...args] = rawArgs;
|
|
757
754
|
const startFn = profiles[profileName];
|
|
758
755
|
if (!startFn) {
|
|
756
|
+
const profileNames = Object.keys(profiles).join(', ');
|
|
759
757
|
log.error(
|
|
760
|
-
`unrecognized profile name ${profileName}; use one of: ${
|
|
761
|
-
profiles,
|
|
762
|
-
)
|
|
763
|
-
.sort()
|
|
764
|
-
.join(', ')}`,
|
|
758
|
+
`unrecognized profile name ${profileName}; use one of: ${profileNames}`,
|
|
765
759
|
);
|
|
766
760
|
return 1;
|
|
767
761
|
}
|
|
768
762
|
|
|
769
|
-
return startFn(profileName, args
|
|
763
|
+
return startFn(profileName, args, opts);
|
|
770
764
|
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/* global process setTimeout clearTimeout setInterval clearInterval */
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import tmp from 'tmp';
|
|
6
|
+
import { makePromiseKit } from '@endo/promise-kit';
|
|
7
|
+
import { request } from 'http';
|
|
8
|
+
|
|
9
|
+
import { spawn } from 'child_process';
|
|
10
|
+
|
|
11
|
+
import { makePspawn } from '../src/helpers.js';
|
|
12
|
+
|
|
13
|
+
const TIMEOUT_SECONDS = 20 * 60;
|
|
14
|
+
|
|
15
|
+
const dirname = new URL('./', import.meta.url).pathname;
|
|
16
|
+
|
|
17
|
+
// To keep in sync with https://agoric.com/documentation/getting-started/
|
|
18
|
+
|
|
19
|
+
// Note that we currently only test:
|
|
20
|
+
// agoric init dapp-foo
|
|
21
|
+
// agoric install
|
|
22
|
+
// agoric start --reset
|
|
23
|
+
// agoric deploy ./contract/deploy.js ./api/deploy.js
|
|
24
|
+
// (For simple-exchange and autoswap, the above also makes and accepts offers)
|
|
25
|
+
// cd ui && yarn install
|
|
26
|
+
// cd ui && yarn start
|
|
27
|
+
|
|
28
|
+
export const gettingStartedWorkflowTest = async (t, options = {}) => {
|
|
29
|
+
const {
|
|
30
|
+
init: initOptions = [],
|
|
31
|
+
install: installOptions = [],
|
|
32
|
+
start: startOptions = [],
|
|
33
|
+
testUnsafePlugins = false,
|
|
34
|
+
} = options;
|
|
35
|
+
// FIXME: Do a search for an unused port or allow specification.
|
|
36
|
+
const PORT = '7999';
|
|
37
|
+
process.env.PORT = PORT;
|
|
38
|
+
|
|
39
|
+
const pspawn = makePspawn({ spawn });
|
|
40
|
+
|
|
41
|
+
// Kill an entire process group.
|
|
42
|
+
const pkill = (cp, signal = 'SIGINT') => process.kill(-cp.pid, signal);
|
|
43
|
+
|
|
44
|
+
function pspawnStdout(...args) {
|
|
45
|
+
const ps = pspawn(...args);
|
|
46
|
+
ps.childProcess.stdout.on('data', chunk => {
|
|
47
|
+
process.stdout.write(chunk);
|
|
48
|
+
});
|
|
49
|
+
// ps.childProcess.unref();
|
|
50
|
+
return ps;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const defaultAgoricCmd = () => {
|
|
54
|
+
// Run all main programs with the '--sdk' flag if we are in agoric-sdk.
|
|
55
|
+
const extraArgs = fs.existsSync(`${dirname}/../../cosmic-swingset`)
|
|
56
|
+
? ['--sdk']
|
|
57
|
+
: [];
|
|
58
|
+
const localCli = path.join(dirname, '..', 'bin', 'agoric');
|
|
59
|
+
return [localCli, ...extraArgs];
|
|
60
|
+
};
|
|
61
|
+
const { AGORIC_CMD = JSON.stringify(defaultAgoricCmd()) } = process.env;
|
|
62
|
+
const agoricCmd = JSON.parse(AGORIC_CMD);
|
|
63
|
+
function myMain(args, opts = {}) {
|
|
64
|
+
// console.error('running agoric-cli', ...extraArgs, ...args);
|
|
65
|
+
return pspawnStdout(agoricCmd[0], [...agoricCmd.slice(1), ...args], {
|
|
66
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
67
|
+
env: { ...process.env, DEBUG: 'agoric:debug' },
|
|
68
|
+
detached: true,
|
|
69
|
+
...opts,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const olddir = process.cwd();
|
|
74
|
+
const { name } = tmp.dirSync({
|
|
75
|
+
unsafeCleanup: true,
|
|
76
|
+
prefix: 'agoric-cli-test-',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const finalizers = [];
|
|
80
|
+
const runFinalizers = sig => {
|
|
81
|
+
while (finalizers.length) {
|
|
82
|
+
const f = finalizers.shift();
|
|
83
|
+
try {
|
|
84
|
+
f();
|
|
85
|
+
} catch (e) {
|
|
86
|
+
// console.log(e);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (sig) {
|
|
90
|
+
// We're dying due to signal.
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
await null;
|
|
96
|
+
try {
|
|
97
|
+
process.on('SIGINT', runFinalizers);
|
|
98
|
+
process.on('exit', runFinalizers);
|
|
99
|
+
process.chdir(name);
|
|
100
|
+
|
|
101
|
+
// ==============
|
|
102
|
+
// agoric init dapp-foo
|
|
103
|
+
if (process.env.AGORIC_INIT_OPTIONS) {
|
|
104
|
+
const opts = JSON.parse(process.env.AGORIC_INIT_OPTIONS);
|
|
105
|
+
initOptions.push(...opts);
|
|
106
|
+
}
|
|
107
|
+
t.is(
|
|
108
|
+
await myMain([
|
|
109
|
+
'init',
|
|
110
|
+
'--dapp-template',
|
|
111
|
+
'dapp-fungible-faucet',
|
|
112
|
+
...initOptions,
|
|
113
|
+
'dapp-foo',
|
|
114
|
+
]),
|
|
115
|
+
0,
|
|
116
|
+
'init dapp-foo works',
|
|
117
|
+
);
|
|
118
|
+
process.chdir('dapp-foo');
|
|
119
|
+
|
|
120
|
+
// ==============
|
|
121
|
+
// agoric install
|
|
122
|
+
if (process.env.AGORIC_INSTALL_OPTIONS) {
|
|
123
|
+
const opts = JSON.parse(process.env.AGORIC_INSTALL_OPTIONS);
|
|
124
|
+
installOptions.push(...opts);
|
|
125
|
+
}
|
|
126
|
+
t.is(await myMain(['install', ...installOptions]), 0, 'install works');
|
|
127
|
+
|
|
128
|
+
// ==============
|
|
129
|
+
// agoric start --reset
|
|
130
|
+
const startResult = makePromiseKit();
|
|
131
|
+
|
|
132
|
+
if (process.env.AGORIC_START_OPTIONS) {
|
|
133
|
+
const opts = JSON.parse(process.env.AGORIC_START_OPTIONS);
|
|
134
|
+
startOptions.push(...opts);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// TODO: Allow this to work even if the port is already used.
|
|
138
|
+
const startP = myMain(['start', '--reset', ...startOptions]);
|
|
139
|
+
finalizers.push(() => pkill(startP.childProcess, 'SIGINT'));
|
|
140
|
+
|
|
141
|
+
let stdoutStr = '';
|
|
142
|
+
if (startP.childProcess.stdout) {
|
|
143
|
+
startP.childProcess.stdout.on('data', chunk => {
|
|
144
|
+
// console.log('stdout:', chunk.toString());
|
|
145
|
+
stdoutStr += chunk.toString();
|
|
146
|
+
if (stdoutStr.match(/(^|:\s+)swingset running$/m)) {
|
|
147
|
+
startResult.resolve(true);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
startP.childProcess.on('close', code =>
|
|
152
|
+
startResult.reject(Error(`early termination: ${code}`)),
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const timeout = setTimeout(
|
|
156
|
+
startResult.reject,
|
|
157
|
+
TIMEOUT_SECONDS * 1000,
|
|
158
|
+
'timeout',
|
|
159
|
+
);
|
|
160
|
+
t.is(await startResult.promise, true, `swingset running before timeout`);
|
|
161
|
+
clearTimeout(timeout);
|
|
162
|
+
|
|
163
|
+
const openP = myMain(['open', '--no-browser'], {
|
|
164
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
165
|
+
});
|
|
166
|
+
t.is(await openP, 0, `open --no-browser exits successfully`);
|
|
167
|
+
|
|
168
|
+
const testDeploy = async (deployCmd, opts = {}) => {
|
|
169
|
+
const deployResult = makePromiseKit();
|
|
170
|
+
const deployP = myMain(
|
|
171
|
+
['deploy', `--hostport=127.0.0.1:${PORT}`, ...deployCmd],
|
|
172
|
+
{
|
|
173
|
+
stdio: [opts.stdin ? 'pipe' : 'ignore', 'pipe', 'inherit'],
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
if (opts.stdin) {
|
|
178
|
+
// Write the input to stdin.
|
|
179
|
+
deployP.childProcess.stdin.write(opts.stdin);
|
|
180
|
+
deployP.childProcess.stdin.end();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
finalizers.push(() => pkill(deployP.childProcess, 'SIGINT'));
|
|
184
|
+
const to = setTimeout(
|
|
185
|
+
deployResult.resolve,
|
|
186
|
+
TIMEOUT_SECONDS * 1000,
|
|
187
|
+
'timeout',
|
|
188
|
+
);
|
|
189
|
+
const done = await Promise.race([deployResult.promise, deployP]);
|
|
190
|
+
t.is(done, 0, `deploy ${deployCmd.join(' ')} successful before timeout`);
|
|
191
|
+
clearTimeout(to);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// ==============
|
|
195
|
+
// agoric deploy ./contract/deploy.js ./api/deploy.js
|
|
196
|
+
await testDeploy(['./contract/deploy.js', './api/deploy.js']);
|
|
197
|
+
|
|
198
|
+
for (const [suffix, code] of [
|
|
199
|
+
['/notthere', 404],
|
|
200
|
+
['', 200],
|
|
201
|
+
]) {
|
|
202
|
+
let urlResolve;
|
|
203
|
+
const url = `http://127.0.0.1:${PORT}${suffix}`;
|
|
204
|
+
const urlP = new Promise(resolve => (urlResolve = resolve));
|
|
205
|
+
const urlReq = request(url, res => urlResolve(res.statusCode));
|
|
206
|
+
urlReq.setTimeout(2000);
|
|
207
|
+
urlReq.on('error', err => urlResolve(`Cannot connect to ${url}: ${err}`));
|
|
208
|
+
urlReq.end();
|
|
209
|
+
const urlTimeout = setTimeout(urlResolve, 3000, 'timeout');
|
|
210
|
+
const urlDone = await urlP;
|
|
211
|
+
clearTimeout(urlTimeout);
|
|
212
|
+
t.is(urlDone, code, `${url} gave status ${code}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ==============
|
|
216
|
+
// cd ui && yarn start
|
|
217
|
+
const uiStartP = pspawn(`yarn`, ['start'], {
|
|
218
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
219
|
+
cwd: 'ui',
|
|
220
|
+
env: { ...process.env, PORT: '3000' },
|
|
221
|
+
detached: true,
|
|
222
|
+
});
|
|
223
|
+
finalizers.push(() => pkill(uiStartP.childProcess, 'SIGINT'));
|
|
224
|
+
const uiListening = makePromiseKit();
|
|
225
|
+
let retries = 0;
|
|
226
|
+
const ival = setInterval(() => {
|
|
227
|
+
try {
|
|
228
|
+
const resolve = status => {
|
|
229
|
+
clearInterval(ival);
|
|
230
|
+
uiListening.resolve(status);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
retries += 1;
|
|
234
|
+
if (retries > 8) {
|
|
235
|
+
resolve('too many retries');
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const req = request('http://localhost:3000/', _res => {
|
|
240
|
+
resolve('listening');
|
|
241
|
+
});
|
|
242
|
+
req.setTimeout(2000);
|
|
243
|
+
req.on('error', err => {
|
|
244
|
+
if (err.code !== 'ECONNREFUSED') {
|
|
245
|
+
resolve(`Cannot connect to UI server: ${err}`);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
req.end();
|
|
249
|
+
} catch (e) {
|
|
250
|
+
console.error('cannot make request', e);
|
|
251
|
+
}
|
|
252
|
+
}, 3000);
|
|
253
|
+
t.is(
|
|
254
|
+
await Promise.race([uiStartP, uiListening.promise]),
|
|
255
|
+
'listening',
|
|
256
|
+
`cd ui && yarn start succeeded`,
|
|
257
|
+
);
|
|
258
|
+
clearInterval(ival);
|
|
259
|
+
|
|
260
|
+
// Test that the Node.js `-r esm`-dependent plugin works.
|
|
261
|
+
await (testUnsafePlugins &&
|
|
262
|
+
testDeploy(
|
|
263
|
+
['--allow-unsafe-plugins', `${dirname}/resm-plugin/deploy.js`],
|
|
264
|
+
{ stdin: 'yes\n' },
|
|
265
|
+
));
|
|
266
|
+
|
|
267
|
+
// TODO: When it exists, Test that the Node.js native ESM plugin works.
|
|
268
|
+
} finally {
|
|
269
|
+
runFinalizers();
|
|
270
|
+
process.off('SIGINT', runFinalizers);
|
|
271
|
+
process.chdir(olddir);
|
|
272
|
+
}
|
|
273
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* globals setTimeout */
|
|
2
|
+
import { E } from '@endo/eventual-send';
|
|
3
|
+
|
|
4
|
+
const PONG_TIMEOUT = 10_000;
|
|
5
|
+
|
|
6
|
+
export default async function deployPlugin(
|
|
7
|
+
homePromise,
|
|
8
|
+
{ installUnsafePlugin },
|
|
9
|
+
) {
|
|
10
|
+
const plugin = await installUnsafePlugin('./src/plugin.js', {});
|
|
11
|
+
const result = await Promise.race([
|
|
12
|
+
E(plugin).ping(),
|
|
13
|
+
new Promise(resolve => setTimeout(resolve, PONG_TIMEOUT, 'timeout')),
|
|
14
|
+
]);
|
|
15
|
+
if (result !== 'pong') {
|
|
16
|
+
throw Error(`ping failed ${result}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const start = 'Started plugin';
|