agoric 0.21.2-other-dev-8f8782b.0 → 0.21.2-other-dev-fbe72e7.0.fbe72e7

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.
Files changed (44) hide show
  1. package/README.md +0 -73
  2. package/package.json +60 -43
  3. package/src/anylogger-agoric.js +31 -16
  4. package/src/bin-agops.js +8 -12
  5. package/src/chain-config.js +42 -16
  6. package/src/commands/auction.js +22 -19
  7. package/src/commands/gov.js +475 -0
  8. package/src/commands/inter.js +44 -62
  9. package/src/commands/oracle.js +144 -87
  10. package/src/commands/perf.js +20 -16
  11. package/src/commands/psm.js +29 -26
  12. package/src/commands/reserve.js +13 -6
  13. package/src/commands/test-upgrade.js +15 -8
  14. package/src/commands/vaults.js +31 -18
  15. package/src/commands/wallet.js +121 -48
  16. package/src/cosmos.js +3 -3
  17. package/src/deploy.js +10 -5
  18. package/src/entrypoint.js +2 -5
  19. package/src/follow.js +14 -10
  20. package/src/helpers.js +10 -5
  21. package/src/init.js +2 -9
  22. package/src/install.js +18 -25
  23. package/src/lib/bundles.js +102 -0
  24. package/src/lib/chain.js +71 -35
  25. package/src/lib/format.js +28 -34
  26. package/src/lib/index.js +7 -0
  27. package/src/lib/packageManager.js +24 -0
  28. package/src/lib/wallet.js +44 -144
  29. package/src/main-publish.js +2 -3
  30. package/src/main.js +95 -125
  31. package/src/open.js +8 -10
  32. package/src/publish.js +4 -9
  33. package/src/scripts.js +14 -32
  34. package/src/sdk-package-names.js +22 -9
  35. package/src/set-defaults.js +2 -1
  36. package/src/start.js +59 -68
  37. package/tools/getting-started.js +272 -0
  38. package/tools/resm-plugin/deploy.js +18 -0
  39. package/tools/resm-plugin/package.json +12 -0
  40. package/tools/resm-plugin/src/output.js +1 -0
  41. package/tools/resm-plugin/src/plugin.js +17 -0
  42. package/CHANGELOG.md +0 -1069
  43. package/src/commands/ec.js +0 -314
  44. package/src/lib/rpc.js +0 -272
@@ -0,0 +1,475 @@
1
+ // @ts-check
2
+ /* eslint-disable func-names */
3
+ /* eslint-env node */
4
+ import {
5
+ fetchEnvNetworkConfig,
6
+ makeAgoricNames,
7
+ makeVstorageKit,
8
+ } from '@agoric/client-utils';
9
+ import { execFileSync as execFileSyncAmbient } from 'child_process';
10
+ import { Command, CommanderError } from 'commander';
11
+ import { normalizeAddressWithOptions, pollBlocks } from '../lib/chain.js';
12
+ import {
13
+ findContinuingIds,
14
+ getCurrent,
15
+ getLastUpdate,
16
+ outputActionAndHint,
17
+ sendAction,
18
+ } from '../lib/wallet.js';
19
+
20
+ /**
21
+ * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
22
+ * @import {AgoricNamesRemotes} from '@agoric/vats/tools/board-utils.js';
23
+ * @import {CurrentWalletRecord} from '@agoric/smart-wallet/src/smartWallet.js';
24
+ * @import {VstorageKit} from '@agoric/client-utils';
25
+ */
26
+
27
+ const collectValues = (val, memo) => {
28
+ memo.push(val);
29
+ return memo;
30
+ };
31
+
32
+ const defaultKeyring = process.env.AGORIC_KEYRING_BACKEND || 'test';
33
+
34
+ const networkConfig = await fetchEnvNetworkConfig({ env: process.env, fetch });
35
+
36
+ /**
37
+ * @param {import('anylogger').Logger} _logger
38
+ * @param {{
39
+ * env?: Record<string, string|undefined>,
40
+ * fetch?: typeof window.fetch,
41
+ * stdout?: Pick<import('stream').Writable, 'write'>,
42
+ * stderr?: Pick<import('stream').Writable, 'write'>,
43
+ * execFileSync?: typeof execFileSyncAmbient,
44
+ * delay?: (ms: number) => Promise<void>,
45
+ * }} [io]
46
+ */
47
+ export const makeGovCommand = (_logger, io = {}) => {
48
+ const {
49
+ // Allow caller to provide access explicitly, but
50
+ // default to conventional ambient IO facilities.
51
+ stdout = process.stdout,
52
+ stderr = process.stderr,
53
+ fetch = global.fetch,
54
+ execFileSync = execFileSyncAmbient,
55
+ delay = ms => new Promise(resolve => setTimeout(resolve, ms)),
56
+ } = io;
57
+
58
+ const cmd = new Command('gov').description('Electoral governance commands');
59
+ // backwards compatibility with less general "ec" command. To make this work
60
+ // the new CLI options default to the values used for Economic Committee
61
+ cmd.alias('ec');
62
+ cmd.option(
63
+ '--keyring-backend <os|file|test>',
64
+ `keyring's backend (os|file|test) (default "${defaultKeyring}")`,
65
+ defaultKeyring,
66
+ );
67
+
68
+ /** @param {string} literalOrName */
69
+ const normalizeAddress = literalOrName =>
70
+ normalizeAddressWithOptions(literalOrName, {
71
+ // FIXME does not observe keyring-backend option, which isn't available during arg parsing
72
+ keyringBackend: defaultKeyring,
73
+ });
74
+
75
+ /** @type {(info: unknown, indent?: unknown) => boolean } */
76
+ const show = (info, indent) =>
77
+ stdout.write(`${JSON.stringify(info, null, indent ? 2 : undefined)}\n`);
78
+
79
+ const abortIfSeen = (instanceName, found) => {
80
+ const done = found.filter(it => it.instanceName === instanceName);
81
+ if (done.length > 0) {
82
+ console.warn(`invitation to ${instanceName} already accepted`, done);
83
+ // CommanderError is a class constructor, and so
84
+ // must be invoked with `new`.
85
+ throw new CommanderError(1, 'EALREADY', `already accepted`);
86
+ }
87
+ };
88
+
89
+ /**
90
+ * Make an offer from agoricNames, wallet status; sign and broadcast it,
91
+ * given a sendFrom address; else print it.
92
+ *
93
+ * @param {{
94
+ * toOffer: (agoricNames: AgoricNamesRemotes, current: CurrentWalletRecord | undefined) => OfferSpec,
95
+ * sendFrom?: string | undefined,
96
+ * keyringBackend: string,
97
+ * instanceName?: string,
98
+ * }} detail
99
+ * @param {VstorageKit} [vsk]
100
+ */
101
+ const processOffer = async function (
102
+ { toOffer, sendFrom, keyringBackend },
103
+ vsk,
104
+ ) {
105
+ await null;
106
+ vsk ||= makeVstorageKit({ fetch }, networkConfig);
107
+ const { readPublished } = vsk;
108
+ const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
109
+
110
+ assert(keyringBackend, 'missing keyring-backend option');
111
+
112
+ let current;
113
+ if (sendFrom) {
114
+ current = await getCurrent(sendFrom, { readPublished });
115
+ }
116
+
117
+ const offer = toOffer(agoricNames, current);
118
+ if (!sendFrom) {
119
+ outputActionAndHint(
120
+ { method: 'executeOffer', offer },
121
+ { stdout, stderr },
122
+ );
123
+ return;
124
+ }
125
+
126
+ const result = await sendAction(
127
+ { method: 'executeOffer', offer },
128
+ {
129
+ keyring: { backend: keyringBackend },
130
+ from: sendFrom,
131
+ verbose: false,
132
+ ...networkConfig,
133
+ execFileSync,
134
+ stdout,
135
+ delay,
136
+ },
137
+ );
138
+ assert(result); // not dry-run
139
+ const { timestamp, txhash, height } = result;
140
+ console.error('wallet action is broadcast:');
141
+ show({ timestamp, height, offerId: offer.id, txhash });
142
+ const checkInWallet = async blockInfo => {
143
+ const [state, update] = await Promise.all([
144
+ getCurrent(sendFrom, { readPublished }),
145
+ getLastUpdate(sendFrom, { readPublished }),
146
+ readPublished(`wallet.${sendFrom}`),
147
+ ]);
148
+ if (update.updated === 'offerStatus' && update.status.id === offer.id) {
149
+ return blockInfo;
150
+ }
151
+ const info = await findContinuingIds(state, agoricNames);
152
+ const done = info.filter(it => it.offerId === offer.id);
153
+ if (!(done.length > 0)) throw Error('retry');
154
+ return blockInfo;
155
+ };
156
+ const blockInfo = await pollBlocks({
157
+ retryMessage: 'offer not yet in block',
158
+ ...networkConfig,
159
+ execFileSync,
160
+ delay,
161
+ })(checkInWallet);
162
+ console.error('offer accepted in block');
163
+ show(blockInfo);
164
+ };
165
+
166
+ cmd
167
+ .command('committee')
168
+ .description('accept invitation to join a committee')
169
+ .requiredOption(
170
+ '--name <string>',
171
+ 'Committee instance name',
172
+ String,
173
+ 'economicCommittee',
174
+ )
175
+ .option('--voter <number>', 'Voter number', Number, 0)
176
+ .option(
177
+ '--offerId <string>',
178
+ 'Offer id',
179
+ String,
180
+ `gov-committee-${Date.now()}`,
181
+ )
182
+ .option(
183
+ '--send-from <name-or-address>',
184
+ 'Send from address',
185
+ normalizeAddress,
186
+ )
187
+ .action(async function (opts, options) {
188
+ const { name: instanceName } = opts;
189
+
190
+ /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
191
+ const toOffer = (agoricNames, current) => {
192
+ const instance = agoricNames.instance[instanceName];
193
+ assert(instance, `missing ${instanceName}`);
194
+
195
+ if (current) {
196
+ const found = findContinuingIds(current, agoricNames);
197
+ abortIfSeen(instanceName, found);
198
+ }
199
+
200
+ return {
201
+ id: opts.offerId,
202
+ invitationSpec: {
203
+ source: 'purse',
204
+ instance,
205
+ description: `Voter${opts.voter}`,
206
+ },
207
+ proposal: {},
208
+ };
209
+ };
210
+
211
+ await processOffer({
212
+ toOffer,
213
+ instanceName,
214
+ sendFrom: opts.sendFrom,
215
+ keyringBackend: options.optsWithGlobals().keyringBackend,
216
+ });
217
+ });
218
+
219
+ cmd
220
+ .command('charter')
221
+ .description('accept the charter invitation')
222
+ .requiredOption(
223
+ '--name <string>',
224
+ 'Charter instance name',
225
+ 'economicCommitteeCharter',
226
+ )
227
+ .option('--offerId <string>', 'Offer id', String, `charter-${Date.now()}`)
228
+ .option(
229
+ '--send-from <name-or-address>',
230
+ 'Send from address',
231
+ normalizeAddress,
232
+ )
233
+ .action(async function (opts, options) {
234
+ const { name: instanceName } = opts;
235
+
236
+ /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
237
+ const toOffer = (agoricNames, current) => {
238
+ const instance = agoricNames.instance[instanceName];
239
+ assert(instance, `missing ${instanceName}`);
240
+
241
+ if (current) {
242
+ const found = findContinuingIds(current, agoricNames);
243
+ abortIfSeen(instanceName, found);
244
+ }
245
+
246
+ return {
247
+ id: opts.offerId,
248
+ invitationSpec: {
249
+ source: 'purse',
250
+ instance,
251
+ description: 'charter member invitation',
252
+ },
253
+ proposal: {},
254
+ };
255
+ };
256
+
257
+ await processOffer({
258
+ toOffer,
259
+ instanceName,
260
+ sendFrom: opts.sendFrom,
261
+ keyringBackend: options.optsWithGlobals().keyringBackend,
262
+ });
263
+ });
264
+
265
+ cmd
266
+ .command('find-continuing-id')
267
+ .description('print id of specified voting continuing invitation')
268
+ .requiredOption(
269
+ '--from <name-or-address>',
270
+ 'from address',
271
+ normalizeAddress,
272
+ )
273
+ .requiredOption('--for <string>', 'description of the invitation')
274
+ .action(async opts => {
275
+ const { readPublished, ...vsk } = makeVstorageKit(
276
+ { fetch },
277
+ networkConfig,
278
+ );
279
+ const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
280
+ const current = await getCurrent(opts.from, { readPublished });
281
+
282
+ const known = findContinuingIds(current, agoricNames);
283
+ if (!known) {
284
+ console.error('No continuing ids found');
285
+ return;
286
+ }
287
+ const match = known.find(r => r.description === opts.for);
288
+ if (!match) {
289
+ console.error(`No match found for '${opts.for}'`);
290
+ return;
291
+ }
292
+
293
+ console.log(match.offerId);
294
+ });
295
+
296
+ cmd
297
+ .command('find-continuing-ids')
298
+ .description('print records of voting continuing invitations')
299
+ .requiredOption(
300
+ '--from <name-or-address>',
301
+ 'from address',
302
+ normalizeAddress,
303
+ )
304
+ .action(async opts => {
305
+ const { readPublished, ...vsk } = makeVstorageKit(
306
+ { fetch },
307
+ networkConfig,
308
+ );
309
+ const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
310
+ const current = await getCurrent(opts.from, { readPublished });
311
+
312
+ const found = findContinuingIds(current, agoricNames);
313
+ for (const it of found) {
314
+ show({ ...it, address: opts.from });
315
+ }
316
+ });
317
+
318
+ cmd
319
+ .command('vote')
320
+ .description('vote on latest question')
321
+ .requiredOption(
322
+ '--instance <string>',
323
+ 'Committee name under agoricNames.instances',
324
+ String,
325
+ 'economicCommittee',
326
+ )
327
+ .requiredOption(
328
+ '--pathname <string>',
329
+ 'Committee name under published.committees',
330
+ String,
331
+ 'Economic_Committee',
332
+ )
333
+ .option('--offerId <number>', 'Offer id', String, `gov-vote-${Date.now()}`)
334
+ .requiredOption(
335
+ '--forPosition <number>',
336
+ 'index of one position to vote for (within the question description.positions); ',
337
+ Number,
338
+ )
339
+ .requiredOption(
340
+ '--send-from <name-or-address>',
341
+ 'Send from address',
342
+ normalizeAddress,
343
+ )
344
+ .action(async function (opts, options) {
345
+ const vsk = makeVstorageKit({ fetch }, networkConfig);
346
+ const { readPublished } = vsk;
347
+
348
+ const questionDesc = await readPublished(
349
+ `committees.${opts.pathname}.latestQuestion`,
350
+ ).catch(err => {
351
+ // CommanderError is a class constructor, and so
352
+ // must be invoked with `new`.
353
+ throw new CommanderError(1, 'VSTORAGE_FAILURE', err.message);
354
+ });
355
+
356
+ // TODO support multiple position arguments
357
+ const chosenPositions = [questionDesc.positions[opts.forPosition]];
358
+ assert(chosenPositions, `undefined position index ${opts.forPosition}`);
359
+
360
+ /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
361
+ const toOffer = (agoricNames, current) => {
362
+ const cont = current ? findContinuingIds(current, agoricNames) : [];
363
+ const votingRight = cont.find(it => it.instanceName === opts.instance);
364
+ if (!votingRight) {
365
+ console.debug('continuing ids', cont, 'for', current);
366
+ // CommanderError is a class constructor, and so
367
+ // must be invoked with `new`.
368
+ throw new CommanderError(
369
+ 1,
370
+ 'NO_INVITATION',
371
+ 'first, try: agops ec committee ...',
372
+ );
373
+ }
374
+ return {
375
+ id: opts.offerId,
376
+ invitationSpec: {
377
+ source: 'continuing',
378
+ previousOffer: votingRight.offerId,
379
+ invitationMakerName: 'makeVoteInvitation',
380
+ // (positionList, questionHandle)
381
+ invitationArgs: harden([
382
+ chosenPositions,
383
+ questionDesc.questionHandle,
384
+ ]),
385
+ },
386
+ proposal: {},
387
+ };
388
+ };
389
+
390
+ await processOffer(
391
+ {
392
+ toOffer,
393
+ sendFrom: opts.sendFrom,
394
+ keyringBackend: options.optsWithGlobals().keyringBackend,
395
+ },
396
+ vsk,
397
+ );
398
+ });
399
+
400
+ cmd
401
+ .command('proposePauseOffers')
402
+ .description('propose a vote to pause offers')
403
+ .option(
404
+ '--send-from <name-or-address>',
405
+ 'Send from address',
406
+ normalizeAddress,
407
+ )
408
+ .option(
409
+ '--offerId <string>',
410
+ 'Offer id',
411
+ String,
412
+ `proposePauseOffers-${Date.now()}`,
413
+ )
414
+ .requiredOption(
415
+ '--instance <string>',
416
+ 'name of governed instance in agoricNames',
417
+ )
418
+ .requiredOption(
419
+ '--substring <string>',
420
+ 'an offer string to pause (can be repeated)',
421
+ collectValues,
422
+ [],
423
+ )
424
+ .option(
425
+ '--deadline <minutes>',
426
+ 'minutes from now to close the vote',
427
+ Number,
428
+ 1,
429
+ )
430
+ .action(async function (opts, options) {
431
+ const { instance: instanceName } = opts;
432
+
433
+ /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
434
+ const toOffer = (agoricNames, current) => {
435
+ const instance = agoricNames.instance[instanceName];
436
+ assert(instance, `missing ${instanceName}`);
437
+ assert(current, 'missing current wallet');
438
+
439
+ const known = findContinuingIds(current, agoricNames);
440
+
441
+ assert(known, 'could not find committee acceptance offer id');
442
+
443
+ // TODO magic string
444
+ const match = known.find(
445
+ r => r.description === 'charter member invitation',
446
+ );
447
+ assert(match, 'no offer found for charter member invitation');
448
+
449
+ return {
450
+ id: opts.offerId,
451
+ invitationSpec: {
452
+ source: 'continuing',
453
+ previousOffer: match.offerId,
454
+ invitationMakerName: 'VoteOnPauseOffers',
455
+ // ( instance, strings list, timer deadline seconds )
456
+ invitationArgs: harden([
457
+ instance,
458
+ opts.substring,
459
+ BigInt(opts.deadline * 60 + Math.round(Date.now() / 1000)),
460
+ ]),
461
+ },
462
+ proposal: {},
463
+ };
464
+ };
465
+
466
+ await processOffer({
467
+ toOffer,
468
+ instanceName,
469
+ sendFrom: opts.sendFrom,
470
+ keyringBackend: options.optsWithGlobals().keyringBackend,
471
+ });
472
+ });
473
+
474
+ return cmd;
475
+ };