agoric 0.21.2-other-dev-8f8782b.0 → 0.21.2-other-dev-3eb1a1d.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/src/lib/wallet.js CHANGED
@@ -1,16 +1,18 @@
1
1
  // @ts-check
2
- /* global process */
2
+ /* eslint-env node */
3
3
 
4
4
  import { iterateReverse } from '@agoric/casting';
5
+ import { boardSlottingMarshaller } from '@agoric/client-utils';
5
6
  import { makeWalletStateCoalescer } from '@agoric/smart-wallet/src/utils.js';
6
- import { execSwingsetTransaction, pollBlocks, pollTx } from './chain.js';
7
- import { boardSlottingMarshaller, makeRpcUtils } from './rpc.js';
7
+ import { Fail } from '@endo/errors';
8
+ import { execSwingsetTransaction, pollTx } from './chain.js';
8
9
 
9
- /** @typedef {import('@agoric/smart-wallet/src/smartWallet.js').CurrentWalletRecord} CurrentWalletRecord */
10
- /** @typedef {import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes} AgoricNamesRemotes */
10
+ /**
11
+ * @import {CurrentWalletRecord} from '@agoric/smart-wallet/src/smartWallet.js';
12
+ * @import {AgoricNamesRemotes} from '@agoric/vats/tools/board-utils.js';
13
+ * @import {MinimalNetworkConfig, VstorageKit} from '@agoric/client-utils';
14
+ */
11
15
 
12
- const { values } = Object;
13
- const { Fail } = assert;
14
16
  const marshaller = boardSlottingMarshaller();
15
17
 
16
18
  /** @type {CurrentWalletRecord} */
@@ -23,18 +25,18 @@ const emptyCurrentRecord = {
23
25
 
24
26
  /**
25
27
  * @param {string} addr
26
- * @param {Pick<import('./rpc.js').RpcUtils, 'readLatestHead'>} io
27
- * @returns {Promise<import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord>}
28
+ * @param {Pick<VstorageKit, 'readPublished'>} io
29
+ * @returns {Promise<import('@agoric/smart-wallet/src/smartWallet.js').CurrentWalletRecord>}
28
30
  */
29
- export const getCurrent = async (addr, { readLatestHead }) => {
31
+ export const getCurrent = async (addr, { readPublished }) => {
30
32
  // Partial because older writes may not have had all properties
31
33
  // NB: assumes changes are only additions
32
34
  let current =
33
- /** @type {Partial<import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord> | undefined} */ (
34
- await readLatestHead(`published.wallet.${addr}.current`)
35
+ /** @type {Partial<import('@agoric/smart-wallet/src/smartWallet.js').CurrentWalletRecord> | undefined} */ (
36
+ await readPublished(`wallet.${addr}.current`)
35
37
  );
36
38
  if (current === undefined) {
37
- throw new Error(`undefined current node for ${addr}`);
39
+ throw Error(`undefined current node for ${addr}`);
38
40
  }
39
41
 
40
42
  // Repair a type misunderstanding seen in the wild.
@@ -58,16 +60,15 @@ export const getCurrent = async (addr, { readLatestHead }) => {
58
60
 
59
61
  /**
60
62
  * @param {string} addr
61
- * @param {Pick<import('./rpc.js').RpcUtils, 'readLatestHead'>} io
62
- * @returns {Promise<import('@agoric/smart-wallet/src/smartWallet').UpdateRecord>}
63
+ * @param {Pick<VstorageKit, 'readPublished'>} io
64
+ * @returns {Promise<import('@agoric/smart-wallet/src/smartWallet.js').UpdateRecord>}
63
65
  */
64
- export const getLastUpdate = (addr, { readLatestHead }) => {
65
- // @ts-expect-error cast
66
- return readLatestHead(`published.wallet.${addr}`);
66
+ export const getLastUpdate = (addr, { readPublished }) => {
67
+ return readPublished(`wallet.${addr}`);
67
68
  };
68
69
 
69
70
  /**
70
- * @param {import('@agoric/smart-wallet/src/smartWallet').BridgeAction} bridgeAction
71
+ * @param {import('@agoric/smart-wallet/src/smartWallet.js').BridgeAction} bridgeAction
71
72
  * @param {Pick<import('stream').Writable,'write'>} [stdout]
72
73
  */
73
74
  export const outputAction = (bridgeAction, stdout = process.stdout) => {
@@ -76,11 +77,11 @@ export const outputAction = (bridgeAction, stdout = process.stdout) => {
76
77
  stdout.write('\n');
77
78
  };
78
79
 
79
- const sendHint =
80
+ export const sendHint =
80
81
  'Now use `agoric wallet send ...` to sign and broadcast the offer.\n';
81
82
 
82
83
  /**
83
- * @param {import('@agoric/smart-wallet/src/smartWallet').BridgeAction} bridgeAction
84
+ * @param {import('@agoric/smart-wallet/src/smartWallet.js').BridgeAction} bridgeAction
84
85
  * @param {{
85
86
  * stdout: Pick<import('stream').Writable,'write'>,
86
87
  * stderr: Pick<import('stream').Writable,'write'>,
@@ -94,25 +95,38 @@ export const outputActionAndHint = (bridgeAction, { stdout, stderr }) => {
94
95
  /**
95
96
  * @param {import('@agoric/smart-wallet/src/offers.js').OfferSpec} offer
96
97
  * @param {Pick<import('stream').Writable,'write'>} [stdout]
98
+ * @param {Pick<import('stream').Writable,'write'>} [stderr]
97
99
  */
98
- export const outputExecuteOfferAction = (offer, stdout = process.stdout) => {
99
- /** @type {import('@agoric/smart-wallet/src/smartWallet').BridgeAction} */
100
+ export const outputExecuteOfferAction = (
101
+ offer,
102
+ stdout = process.stdout,
103
+ stderr = process.stderr,
104
+ ) => {
105
+ /** @type {import('@agoric/smart-wallet/src/smartWallet.js').BridgeAction} */
100
106
  const spendAction = {
101
107
  method: 'executeOffer',
102
108
  offer,
103
109
  };
104
110
  outputAction(spendAction, stdout);
111
+ stderr.write(sendHint);
105
112
  };
106
113
 
107
114
  /**
108
115
  * @deprecated use `.current` node for current state
109
- * @param {import('@agoric/casting').Follower<import('@agoric/casting').ValueFollowerElement<import('@agoric/smart-wallet/src/smartWallet').UpdateRecord>>} follower
116
+ * @param {import('@agoric/casting').Follower<import('@agoric/casting').ValueFollowerElement<import('@agoric/smart-wallet/src/smartWallet.js').UpdateRecord>>} follower
110
117
  * @param {Brand<'set'>} [invitationBrand]
111
118
  */
112
119
  export const coalesceWalletState = async (follower, invitationBrand) => {
113
120
  // values with oldest last
114
121
  const history = [];
115
122
  for await (const followerElement of iterateReverse(follower)) {
123
+ if ('error' in followerElement) {
124
+ console.error(
125
+ 'Skipping wallet update due to error:',
126
+ followerElement.error,
127
+ );
128
+ continue;
129
+ }
116
130
  history.push(followerElement.value);
117
131
  }
118
132
 
@@ -129,9 +143,10 @@ export const coalesceWalletState = async (follower, invitationBrand) => {
129
143
  * Sign and broadcast a wallet-action.
130
144
  *
131
145
  * @throws { Error & { code: number } } if transaction fails
132
- * @param {import('@agoric/smart-wallet/src/smartWallet').BridgeAction} bridgeAction
133
- * @param {import('./rpc').MinimalNetworkConfig & {
146
+ * @param {import('@agoric/smart-wallet/src/smartWallet.js').BridgeAction} bridgeAction
147
+ * @param {MinimalNetworkConfig & {
134
148
  * from: string,
149
+ * fees?: string,
135
150
  * verbose?: boolean,
136
151
  * keyring?: {home?: string, backend: string},
137
152
  * stdout: Pick<import('stream').Writable, 'write'>,
@@ -159,7 +174,7 @@ export const sendAction = async (bridgeAction, opts) => {
159
174
  assert(out); // not dry run
160
175
  const tx = JSON.parse(out);
161
176
  if (tx.code !== 0) {
162
- const err = Error(`failed to send action. code: ${tx.code}`);
177
+ const err = Error(`failed to send tx: ${tx.raw_log} code: ${tx.code}`);
163
178
  // @ts-expect-error XXX how to add properties to an error?
164
179
  err.code = tx.code;
165
180
  throw err;
@@ -174,7 +189,7 @@ export const sendAction = async (bridgeAction, opts) => {
174
189
  */
175
190
  export const findContinuingIds = (current, agoricNames) => {
176
191
  // XXX should runtime type-check
177
- /** @type {{ offerToUsedInvitation: [string, Amount<'set'>][]}} */
192
+ /** @type {{ offerToUsedInvitation: [string, InvitationAmount][]}} */
178
193
  const { offerToUsedInvitation: entries } = /** @type {any} */ (current);
179
194
 
180
195
  Array.isArray(entries) || Fail`entries must be an array: ${entries}`;
@@ -198,118 +213,3 @@ export const findContinuingIds = (current, agoricNames) => {
198
213
  }
199
214
  return found;
200
215
  };
201
-
202
- export const makeWalletUtils = async (
203
- { fetch, execFileSync, delay },
204
- networkConfig,
205
- ) => {
206
- const { agoricNames, fromBoard, readLatestHead, vstorage } =
207
- await makeRpcUtils({ fetch }, networkConfig);
208
- /**
209
- * @param {string} from
210
- * @param {number|string} [minHeight]
211
- */
212
- const storedWalletState = async (from, minHeight = undefined) => {
213
- const m = boardSlottingMarshaller(fromBoard.convertSlotToVal);
214
-
215
- const history = await vstorage.readFully(
216
- `published.wallet.${from}`,
217
- minHeight,
218
- );
219
-
220
- /** @type {{ Invitation: Brand<'set'> }} */
221
- // @ts-expect-error XXX how to narrow AssetKind to set?
222
- const { Invitation } = agoricNames.brand;
223
- const coalescer = makeWalletStateCoalescer(Invitation);
224
- // update with oldest first
225
- for (const txt of history.reverse()) {
226
- const { body, slots } = JSON.parse(txt);
227
- const record = m.fromCapData({ body, slots });
228
- coalescer.update(record);
229
- }
230
- const coalesced = coalescer.state;
231
- harden(coalesced);
232
- return coalesced;
233
- };
234
-
235
- /**
236
- * Get OfferStatus by id, polling until available.
237
- *
238
- * @param {string} from
239
- * @param {string|number} id
240
- * @param {number|string} minHeight
241
- * @param {boolean} [untilNumWantsSatisfied]
242
- */
243
- const pollOffer = async (
244
- from,
245
- id,
246
- minHeight,
247
- untilNumWantsSatisfied = false,
248
- ) => {
249
- const lookup = async () => {
250
- // eslint-disable-next-line @jessie.js/no-nested-await, no-await-in-loop
251
- const { offerStatuses } = await storedWalletState(from, minHeight);
252
- const offerStatus = [...offerStatuses.values()].find(s => s.id === id);
253
- if (!offerStatus) throw Error('retry');
254
- harden(offerStatus);
255
- if (untilNumWantsSatisfied && !('numWantsSatisfied' in offerStatus)) {
256
- throw Error('retry (no numWantsSatisfied yet)');
257
- }
258
- return offerStatus;
259
- };
260
- const retryMessage = 'offer not in wallet at block';
261
- const opts = { ...networkConfig, execFileSync, delay, retryMessage };
262
- return pollBlocks(opts)(lookup);
263
- };
264
-
265
- return {
266
- networkConfig,
267
- agoricNames,
268
- fromBoard,
269
- vstorage,
270
- readLatestHead,
271
- storedWalletState,
272
- pollOffer,
273
- };
274
- };
275
-
276
- /**
277
- * @param {{
278
- * brand: Record<string, Brand>,
279
- * vbankAsset: Record<string, { brand: Brand, displayInfo: DisplayInfo }>,
280
- * }} agoricNames
281
- * @param {(msg: string) => Error} makeError error constructor
282
- * @returns {(a: string) => Amount<'nat'>}
283
- */
284
- export const makeParseAmount =
285
- (agoricNames, makeError = msg => RangeError(msg)) =>
286
- opt => {
287
- assert.typeof(opt, 'string', 'parseAmount expected string');
288
- const m = opt.match(/^(?<value>[\d_]+(\.[\d_]+)?)(?<brand>[A-Z]\w*?)$/);
289
- if (!m || !m.groups) {
290
- throw makeError(`invalid amount: ${opt}`);
291
- }
292
- const anyBrand = agoricNames.brand[m.groups.brand];
293
- if (!anyBrand) {
294
- throw makeError(`unknown brand: ${m.groups.brand}`);
295
- }
296
- const assetDesc = values(agoricNames.vbankAsset).find(
297
- d => d.brand === anyBrand,
298
- );
299
- if (!assetDesc) {
300
- throw makeError(`unknown brand: ${m.groups.brand}`);
301
- }
302
- const { displayInfo } = assetDesc;
303
- if (!displayInfo.decimalPlaces || displayInfo.assetKind !== 'nat') {
304
- throw makeError(`bad brand: ${displayInfo}`);
305
- }
306
- const value = BigInt(
307
- Number(m.groups.value.replace(/_/g, '')) *
308
- 10 ** displayInfo.decimalPlaces,
309
- );
310
- /** @type {Brand<'nat'>} */
311
- // @ts-expect-error dynamic cast
312
- const natBrand = anyBrand;
313
- const amt = { value, brand: natBrand };
314
- return amt;
315
- };
@@ -1,4 +1,4 @@
1
- /* global process */
1
+ /* eslint-env node */
2
2
  // @ts-check
3
3
 
4
4
  import path from 'path';
@@ -31,9 +31,9 @@ const publishMain = async (progname, rawArgs, powers, opts) => {
31
31
  chainID,
32
32
  };
33
33
 
34
+ await null;
34
35
  for (const bundlePath of rawArgs.slice(1)) {
35
36
  // AWAIT
36
- // eslint-disable-next-line no-await-in-loop,@jessie.js/no-nested-await
37
37
  const bundleText = await fs.readFile(bundlePath, 'utf-8');
38
38
  const bundle = parseLocatedJson(bundleText, bundlePath);
39
39
 
@@ -53,7 +53,6 @@ const publishMain = async (progname, rawArgs, powers, opts) => {
53
53
  });
54
54
 
55
55
  // AWAIT
56
- // eslint-disable-next-line no-await-in-loop,@jessie.js/no-nested-await
57
56
  const hashedBundle = await publishBundle(bundle, connectionSpec);
58
57
  process.stdout.write(`${JSON.stringify(hashedBundle)}\n`);
59
58
  }
package/src/main.js CHANGED
@@ -1,26 +1,26 @@
1
- /* eslint-disable @jessie.js/no-nested-await */
2
- /* global process */
1
+ /* eslint-env node */
3
2
  import { Command } from 'commander';
4
3
  import path from 'path';
5
4
  import url from 'url';
6
- import { assert, details as X } from '@agoric/assert';
5
+ import { assert, X } from '@endo/errors';
7
6
  import {
8
7
  DEFAULT_KEEP_POLLING_SECONDS,
9
8
  DEFAULT_JITTER_SECONDS,
10
9
  } from '@agoric/casting';
10
+ import { makeWalletCommand } from './commands/wallet.js';
11
11
  import cosmosMain from './cosmos.js';
12
12
  import deployMain from './deploy.js';
13
- import runMain from './run.js';
14
- import publishMain from './main-publish.js';
13
+ import followMain from './follow.js';
15
14
  import initMain from './init.js';
16
15
  import installMain from './install.js';
16
+ import { statPlans } from './lib/bundles.js';
17
+ import publishMain from './main-publish.js';
18
+ import walletMain from './open.js';
19
+ import runMain from './run.js';
17
20
  import setDefaultsMain from './set-defaults.js';
18
21
  import startMain from './start.js';
19
- import followMain from './follow.js';
20
- import walletMain from './open.js';
21
- import { makeWalletCommand } from './commands/wallet.js';
22
22
 
23
- const DEFAULT_DAPP_TEMPLATE = 'dapp-fungible-faucet';
23
+ const DEFAULT_DAPP_TEMPLATE = 'dapp-offer-up';
24
24
  const DEFAULT_DAPP_URL_BASE = 'https://github.com/Agoric/';
25
25
  const DEFAULT_DAPP_BRANCH = undefined;
26
26
 
@@ -36,6 +36,7 @@ const main = async (progname, rawArgs, powers) => {
36
36
  const program = new Command();
37
37
 
38
38
  async function isNotBasedir() {
39
+ await null;
39
40
  try {
40
41
  await fs.stat(STAMP);
41
42
  return false;
@@ -46,6 +47,7 @@ const main = async (progname, rawArgs, powers) => {
46
47
  return true;
47
48
  }
48
49
 
50
+ // XXX exits process when fn resolves
49
51
  function subMain(fn, args, options) {
50
52
  return fn(progname, args, powers, options).then(
51
53
  // This seems to be the only way to propagate the exit code.
@@ -57,23 +59,31 @@ const main = async (progname, rawArgs, powers) => {
57
59
  const pkg = JSON.parse(pj);
58
60
  program.name(pkg.name).version(pkg.version);
59
61
 
60
- program
61
- .option('--sdk', 'use the Agoric SDK containing this program')
62
- .option('--no-sdk', 'do not use the Agoric SDK containing this program')
63
- .option('--docker-tag <tag>', 'image tag to use for Docker containers')
64
- .option(
62
+ const cmdOpts = { verbose: 0 };
63
+ const addCmdOpts = baseCmd =>
64
+ baseCmd.option(
65
65
  '-v, --verbose',
66
66
  'verbosity that can be increased',
67
- (_value, previous) => previous + 1,
68
- 0,
67
+ (_value, _previous) => (cmdOpts.verbose += 1),
69
68
  );
69
+ /** @type {typeof program.command} */
70
+ const baseCmd = (nameAndParams, ...rest) =>
71
+ addCmdOpts(program.command(nameAndParams, ...rest));
72
+
73
+ addCmdOpts(
74
+ program
75
+ .enablePositionalOptions()
76
+ .option('--sdk', 'use the Agoric SDK containing this program')
77
+ .option('--no-sdk', 'do not use the Agoric SDK containing this program'),
78
+ );
70
79
 
71
80
  // Add each of the commands.
72
- program
73
- .command('cosmos <command...>')
81
+ baseCmd('cosmos <command...>')
82
+ .passThroughOptions(true)
83
+ .option('--docker-tag <tag>', 'image tag to use for Docker containers')
74
84
  .description('client for an Agoric Cosmos chain')
75
85
  .action(async (command, _options, cmd) => {
76
- const opts = { ...program.opts(), ...cmd.opts() };
86
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
77
87
  return subMain(cosmosMain, ['cosmos', ...command], opts);
78
88
  });
79
89
 
@@ -90,13 +100,12 @@ const main = async (progname, rawArgs, powers) => {
90
100
  { executableFile: ibcSetup },
91
101
  );
92
102
 
93
- program
94
- .command('open')
103
+ baseCmd('open')
95
104
  .description('launch the Agoric UI')
96
105
  .option(
97
106
  '--hostport <host:port>',
98
107
  'host and port to connect to VM',
99
- '127.0.0.1:8000',
108
+ 'localhost:8000',
100
109
  )
101
110
  .option('--no-browser', `just display the URL, don't open a browser`)
102
111
  .option(
@@ -112,12 +121,11 @@ const main = async (progname, rawArgs, powers) => {
112
121
  },
113
122
  )
114
123
  .action(async (_options, cmd) => {
115
- const opts = { ...program.opts(), ...cmd.opts() };
124
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
116
125
  return subMain(walletMain, ['wallet'], opts);
117
126
  });
118
127
 
119
- program
120
- .command('init <project>')
128
+ baseCmd('init <project>')
121
129
  .description('create a new Dapp directory named <project>')
122
130
  .option(
123
131
  '--dapp-template <name>',
@@ -134,13 +142,17 @@ const main = async (progname, rawArgs, powers) => {
134
142
  'use this branch instead of the repository HEAD',
135
143
  DEFAULT_DAPP_BRANCH,
136
144
  )
145
+ // Tolerate @agoric/create-dapp's `agoric init --version` invocation.
146
+ .option('-V, --version', 'output the version number', () => {
147
+ console.log(pkg.version);
148
+ process.exit(0);
149
+ })
137
150
  .action(async (project, _options, cmd) => {
138
- const opts = { ...program.opts(), ...cmd.opts() };
151
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
139
152
  return subMain(initMain, ['init', project], opts);
140
153
  });
141
154
 
142
- program
143
- .command('set-defaults <program> <config-dir>')
155
+ baseCmd('set-defaults <program> <config-dir>')
144
156
  .description('update the configuration files for <program> in <config-dir>')
145
157
  .option(
146
158
  '--enable-cors',
@@ -168,7 +180,7 @@ const main = async (progname, rawArgs, powers) => {
168
180
  '',
169
181
  )
170
182
  .action(async (prog, configDir, _options, cmd) => {
171
- const opts = { ...program.opts(), ...cmd.opts() };
183
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
172
184
  return subMain(setDefaultsMain, ['set-defaults', prog, configDir], opts);
173
185
  });
174
186
 
@@ -187,17 +199,15 @@ const main = async (progname, rawArgs, powers) => {
187
199
  },
188
200
  );
189
201
 
190
- program
191
- .command('install [force-sdk-version]')
202
+ baseCmd('install [force-sdk-version]')
192
203
  .description('install Dapp dependencies')
193
204
  .action(async (forceSdkVersion, _options, cmd) => {
194
205
  await isNotBasedir();
195
- const opts = { ...program.opts(), ...cmd.opts() };
206
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
196
207
  return subMain(installMain, ['install', forceSdkVersion], opts);
197
208
  });
198
209
 
199
- program
200
- .command('follow <path-spec...>')
210
+ baseCmd('follow <path-spec...>')
201
211
  .description('follow an Agoric Casting leader')
202
212
  .option(
203
213
  '--proof <strict | optimistic | none>',
@@ -270,61 +280,59 @@ const main = async (progname, rawArgs, powers) => {
270
280
  )
271
281
  .option('-B, --bootstrap <config>', 'network bootstrap configuration')
272
282
  .action(async (pathSpecs, _options, cmd) => {
273
- const opts = { ...program.opts(), ...cmd.opts() };
283
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
274
284
  return subMain(followMain, ['follow', ...pathSpecs], opts);
275
285
  });
276
286
 
277
- const addRunOptions = cmd =>
278
- cmd
279
- .option(
280
- '--allow-unsafe-plugins',
281
- `CAREFUL: installed Agoric VM plugins will also have all your user's privileges`,
282
- false,
283
- )
284
- .option(
285
- '--hostport <host:port>',
286
- 'host and port to connect to VM',
287
- '127.0.0.1:8000',
288
- )
289
- .option(
290
- '--need <subsystems>',
291
- 'comma-separated names of subsystems to wait for',
292
- 'local,agoric,wallet',
293
- )
294
- .option(
295
- '--provide <subsystems>',
296
- 'comma-separated names of subsystems this script initializes',
297
- '',
298
- );
299
-
300
- program
301
- .command('run <script> [script-args...]')
287
+ baseCmd('run <script> [script-args...]')
302
288
  .description(
303
289
  'run a script with all your user privileges and some Agoric endowments',
304
290
  )
291
+ .passThroughOptions(true)
305
292
  .action(async (script, scriptArgs, _options, cmd) => {
306
- const opts = { ...program.opts(), ...cmd.opts(), scriptArgs };
307
- return subMain(runMain, ['run', script], opts);
293
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts, scriptArgs };
294
+ await runMain(progname, ['run', script], powers, opts);
295
+
296
+ if (opts.verbose) {
297
+ await statPlans(process.cwd());
298
+ }
308
299
  });
309
300
 
310
- addRunOptions(
311
- program
312
- .command('deploy [script...]')
313
- .option(
314
- '--target <target>',
315
- 'One of agoric, local, cosmos, or sim',
316
- 'agoric',
317
- )
318
- .description(
319
- 'run multiple scripts with all your user privileges against the local Agoric VM',
320
- ),
321
- ).action(async (scripts, _options, cmd) => {
322
- const opts = { ...program.opts(), ...cmd.opts() };
323
- return subMain(deployMain, ['deploy', ...scripts], opts);
324
- });
301
+ baseCmd('deploy [script...]')
302
+ .option(
303
+ '--target <target>',
304
+ 'One of agoric, local, cosmos, or sim',
305
+ 'agoric',
306
+ )
307
+ .option(
308
+ '--allow-unsafe-plugins',
309
+ `CAREFUL: installed Agoric VM plugins will also have all your user's privileges`,
310
+ false,
311
+ )
312
+ .option(
313
+ '--hostport <host:port>',
314
+ 'host and port to connect to VM',
315
+ '127.0.0.1:8000',
316
+ )
317
+ .option(
318
+ '--need <subsystems>',
319
+ 'comma-separated names of subsystems to wait for',
320
+ 'local,agoric,wallet',
321
+ )
322
+ .option(
323
+ '--provide <subsystems>',
324
+ 'comma-separated names of subsystems this script initializes',
325
+ '',
326
+ )
327
+ .description(
328
+ 'run multiple scripts with all your user privileges against the local Agoric VM',
329
+ )
330
+ .action(async (scripts, _options, cmd) => {
331
+ const opts = { ...program.opts(), ...cmd.opts() };
332
+ return subMain(deployMain, ['deploy', ...scripts], opts);
333
+ });
325
334
 
326
- program
327
- .command('publish [bundle...]')
335
+ baseCmd('publish [bundle...]')
328
336
  .option(
329
337
  '-c, --chain-id <chainID>',
330
338
  'The ID of the destination chain',
@@ -345,10 +353,9 @@ const main = async (progname, rawArgs, powers) => {
345
353
  return subMain(publishMain, ['publish', ...bundles], opts);
346
354
  });
347
355
 
348
- program.addCommand(await makeWalletCommand());
356
+ await makeWalletCommand(baseCmd);
349
357
 
350
- program
351
- .command('start [profile] [args...]')
358
+ baseCmd('start [profile] [args...]')
352
359
  .description(
353
360
  `\
354
361
  start an Agoric VM
@@ -360,6 +367,7 @@ agoric start local-solo [portNum] [provisionPowers] - local solo VM
360
367
  `,
361
368
  )
362
369
  .option('-d, --debug', 'run in JS debugger mode')
370
+ .option('--docker-tag <tag>', 'image tag to use for Docker containers')
363
371
  .option('--reset', 'clear all VM state before starting')
364
372
  .option('--no-restart', 'do not actually start the VM')
365
373
  .option('--pull', 'for Docker-based VM, pull the image before running')
@@ -383,19 +391,13 @@ agoric start local-solo [portNum] [provisionPowers] - local solo VM
383
391
  )
384
392
  .action(async (profile, args, _options, cmd) => {
385
393
  await isNotBasedir();
386
- const opts = { ...program.opts(), ...cmd.opts() };
394
+ const opts = { ...program.opts(), ...cmd.opts(), ...cmdOpts };
387
395
  return subMain(startMain, ['start', profile, ...args], opts);
388
396
  });
389
397
 
390
398
  // Throw an error instead of exiting directly.
391
399
  program.exitOverride();
392
400
 
393
- // Hack: cosmos arguments are always unparsed.
394
- const cosmosIndex = rawArgs.indexOf('cosmos');
395
- if (cosmosIndex >= 0) {
396
- rawArgs.splice(cosmosIndex + 1, 0, '--');
397
- }
398
-
399
401
  try {
400
402
  await program.parseAsync(rawArgs, { from: 'user' });
401
403
  } catch (e) {
package/src/open.js CHANGED
@@ -1,12 +1,10 @@
1
- /* global process setInterval clearInterval */
1
+ /* eslint-env node */
2
2
  import opener from 'opener';
3
-
3
+ import { assert, X } from '@endo/errors';
4
4
  import { getAccessToken } from '@agoric/access-token';
5
5
 
6
- import { assert, details as X } from '@agoric/assert';
7
-
8
- export default async function walletMain(progname, rawArgs, powers, opts) {
9
- const { anylogger, fs } = powers;
6
+ export default async function walletMain(_progname, _rawArgs, powers, opts) {
7
+ const { anylogger } = powers;
10
8
  const console = anylogger('agoric:wallet');
11
9
 
12
10
  let suffix;
@@ -39,10 +37,10 @@ export default async function walletMain(progname, rawArgs, powers, opts) {
39
37
  1000,
40
38
  );
41
39
 
42
- const walletAccessToken = await getAccessToken(opts.hostport, {
43
- console,
44
- fs,
45
- }).catch(e => console.error(`Trying to fetch access token:`, e));
40
+ const walletAccessToken = await getAccessToken(opts.hostport).catch(e => {
41
+ console.error(`Trying to fetch access token:`, e);
42
+ throw e;
43
+ });
46
44
 
47
45
  clearInterval(progressTimer);
48
46
  process.stderr.write('\n');