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
@@ -4,32 +4,19 @@
4
4
  */
5
5
 
6
6
  // @ts-check
7
- import { CommanderError, InvalidArgumentError } from 'commander';
8
- // TODO: should get M from endo https://github.com/Agoric/agoric-sdk/issues/7090
7
+ import { fetchEnvNetworkConfig, makeWalletUtils } from '@agoric/client-utils';
9
8
  import { makeOfferSpecShape } from '@agoric/inter-protocol/src/auction/auctionBook.js';
10
9
  import { Offers } from '@agoric/inter-protocol/src/clientSupport.js';
11
10
  import { objectMap } from '@agoric/internal';
12
- import { M, matches } from '@agoric/store';
13
-
14
- // XXX scare away ambient type zombies to fix ScheduleNotification.activeStartTime etc.
15
- // https://github.com/Agoric/agoric-sdk/issues/6512
16
- // https://github.com/Agoric/agoric-sdk/issues/6343
17
- import '@agoric/inter-protocol/src/vaultFactory/types.js';
18
-
11
+ import { M, matches } from '@endo/patterns';
12
+ import { CommanderError, InvalidArgumentError } from 'commander';
19
13
  import { normalizeAddressWithOptions, pollBlocks } from '../lib/chain.js';
20
14
  import {
21
15
  asBoardRemote,
22
16
  bigintReplacer,
23
17
  makeAmountFormatter,
24
18
  } from '../lib/format.js';
25
- import { getNetworkConfig } from '../lib/rpc.js';
26
- import {
27
- getCurrent,
28
- makeParseAmount,
29
- makeWalletUtils,
30
- outputActionAndHint,
31
- sendAction,
32
- } from '../lib/wallet.js';
19
+ import { getCurrent, outputActionAndHint, sendAction } from '../lib/wallet.js';
33
20
 
34
21
  const { values } = Object;
35
22
 
@@ -39,16 +26,16 @@ const bidInvitationShape = harden({
39
26
  callPipe: [['makeBidInvitation', M.any()]],
40
27
  });
41
28
 
42
- /** @typedef {import('@agoric/vats/tools/board-utils.js').VBankAssetDetail } AssetDescriptor */
43
- /** @typedef {import('@agoric/smart-wallet/src/smartWallet').TryExitOfferAction } TryExitOfferAction */
44
- /** @typedef {import('@agoric/inter-protocol/src/auction/auctionBook.js').OfferSpec} BidSpec */
45
- /** @typedef {import('@agoric/inter-protocol/src/auction/scheduler.js').ScheduleNotification} ScheduleNotification */
46
- /** @typedef {import('@agoric/inter-protocol/src/auction/auctionBook.js').BookDataNotification} BookDataNotification */
29
+ /** @import {VBankAssetDetail} from '@agoric/vats/tools/board-utils.js'; */
30
+ /** @import {TryExitOfferAction} from '@agoric/smart-wallet/src/smartWallet.js'; */
31
+ /** @import {OfferSpec as BidSpec} from '@agoric/inter-protocol/src/auction/auctionBook.js' */
32
+ /** @import {ScheduleNotification} from '@agoric/inter-protocol/src/auction/scheduler.js' */
33
+ /** @import {BookDataNotification} from '@agoric/inter-protocol/src/auction/auctionBook.js' */
47
34
 
48
35
  /**
49
36
  * Format amounts, prices etc. based on brand board Ids, displayInfo
50
37
  *
51
- * @param {AssetDescriptor[]} assets
38
+ * @param {VBankAssetDetail[]} assets
52
39
  */
53
40
  const makeFormatters = assets => {
54
41
  const r4 = x => Math.round(x * 10_000) / 10_000;
@@ -71,12 +58,12 @@ const makeFormatters = assets => {
71
58
  r4(100 - (Number(r.numerator.value) / Number(r.denominator.value)) * 100);
72
59
 
73
60
  // XXX real TimeMath.absValue requires real Remotable timerBrand
74
- /** @param {import('@agoric/time/src/types.js').Timestamp} ts */
61
+ /** @param {import('@agoric/time').Timestamp} ts */
75
62
  const absValue = ts => (typeof ts === 'bigint' ? ts : ts.absValue);
76
63
 
77
- /** @param {import('@agoric/time/src/types.js').Timestamp} tr */
64
+ /** @param {import('@agoric/time').Timestamp} tr */
78
65
  const absTime = tr => new Date(Number(absValue(tr)) * 1000).toISOString();
79
- /** @param {import('@agoric/time/src/types.js').RelativeTimeRecord} tr */
66
+ /** @param {import('@agoric/time').RelativeTimeRecord} tr */
80
67
  const relTime = tr =>
81
68
  new Date(Number(tr.relValue) * 1000).toISOString().slice(11, 19);
82
69
 
@@ -88,7 +75,7 @@ const makeFormatters = assets => {
88
75
  * @param {(_: T) => string} f
89
76
  * @returns { (x: T | null | undefined ) => string | undefined }
90
77
  */
91
- const maybe = f => x => x ? f(x) : undefined;
78
+ const maybe = f => x => (x ? f(x) : undefined);
92
79
 
93
80
  return {
94
81
  amount,
@@ -108,7 +95,7 @@ const makeFormatters = assets => {
108
95
  * Dynamic check that an OfferStatus is also a BidSpec.
109
96
  *
110
97
  * @param {import('@agoric/smart-wallet/src/offers.js').OfferStatus} offerStatus
111
- * @param {Awaited<ReturnType<import('../lib/rpc').makeAgoricNames>>} agoricNames
98
+ * @param {import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes} agoricNames
112
99
  * @param {typeof console.warn} warn
113
100
  * returns null if offerStatus is not a BidSpec
114
101
  */
@@ -144,7 +131,7 @@ const coerceBid = (offerStatus, agoricNames, warn) => {
144
131
  *
145
132
  * @param {import('@agoric/smart-wallet/src/offers.js').OfferStatus &
146
133
  * { offerArgs: BidSpec}} bid
147
- * @param {import('agoric/src/lib/format.js').AssetDescriptor[]} assets
134
+ * @param {VBankAssetDetail[]} assets
148
135
  */
149
136
  export const fmtBid = (bid, assets) => {
150
137
  const fmt = makeFormatters(assets);
@@ -206,6 +193,10 @@ export const makeInterCommand = (
206
193
  const interCmd = createCommand('inter')
207
194
  .description('Inter Protocol commands for liquidation bidding etc.')
208
195
  .option('--home <dir>', 'agd CosmosSDK application home directory')
196
+ .option(
197
+ '--fees <amount>',
198
+ 'set fees for transaction broadcast (e.g. 5000ubld)',
199
+ )
209
200
  .option(
210
201
  '--keyring-backend <os|file|test>',
211
202
  `keyring's backend (os|file|test) (default "${
@@ -220,6 +211,8 @@ export const makeInterCommand = (
220
211
  try {
221
212
  return rawExec(file, args, ...opts);
222
213
  } catch (err) {
214
+ // InvalidArgumentError is a class constructor, and so
215
+ // must be invoked with `new`.
223
216
  throw new InvalidArgumentError(
224
217
  `${err.message}: is ${file} in your $PATH?`,
225
218
  );
@@ -238,10 +231,11 @@ export const makeInterCommand = (
238
231
  try {
239
232
  // XXX pass fetch to getNetworkConfig() explicitly
240
233
  // await null above makes this await safe
241
- // eslint-disable-next-line @jessie.js/no-nested-await
242
- const networkConfig = await getNetworkConfig(env);
243
- return makeWalletUtils({ fetch, execFileSync, delay }, networkConfig);
234
+ const networkConfig = await fetchEnvNetworkConfig({ env, fetch });
235
+ return makeWalletUtils({ fetch, delay }, networkConfig);
244
236
  } catch (err) {
237
+ // CommanderError is a class constructor, and so
238
+ // must be invoked with `new`.
245
239
  throw new CommanderError(1, 'RPC_FAIL', err.message);
246
240
  }
247
241
  };
@@ -286,14 +280,12 @@ inter auction status
286
280
  * }}
287
281
  */ opts,
288
282
  ) => {
289
- const { agoricNames, readLatestHead } = await tryMakeUtils();
283
+ const { agoricNames, readPublished } = await tryMakeUtils();
290
284
 
291
- /** @type { [ScheduleNotification, BookDataNotification, *] } */
292
- // @ts-expect-error dynamic cast
293
285
  const [schedule, book, { current: params }] = await Promise.all([
294
- readLatestHead(`published.auction.schedule`),
295
- readLatestHead(`published.auction.book${opts.book}`),
296
- readLatestHead(`published.auction.governance`),
286
+ readPublished('auction.schedule'),
287
+ readPublished(`auction.book${opts.book}`),
288
+ readPublished('auction.governance'),
297
289
  ]);
298
290
 
299
291
  const fmt = makeFormatters(Object.values(agoricNames.vbankAsset));
@@ -333,16 +325,16 @@ inter auction status
333
325
  * @param {string} from
334
326
  * @param {import('@agoric/smart-wallet/src/offers.js').OfferSpec} offer
335
327
  * @param {Awaited<ReturnType<tryMakeUtils>>} tools
336
- * @param {boolean?} dryRun
328
+ * @param {boolean | undefined} dryRun
337
329
  */
338
330
  const placeBid = async (from, offer, tools, dryRun = false) => {
339
331
  const { networkConfig, agoricNames, pollOffer } = tools;
340
332
  const io = { ...networkConfig, execFileSync, delay, stdout };
341
333
 
342
- const { home, keyringBackend: backend } = interCmd.opts();
334
+ const { home, keyringBackend: backend, fees } = interCmd.opts();
343
335
  const result = await sendAction(
344
336
  { method: 'executeOffer', offer },
345
- { keyring: { home, backend }, from, verbose: false, dryRun, ...io },
337
+ { keyring: { home, backend }, from, fees, verbose: false, dryRun, ...io },
346
338
  );
347
339
  if (dryRun) {
348
340
  return;
@@ -416,14 +408,7 @@ inter auction status
416
408
  async ({ generateOnly, dryRun, ...opts }) => {
417
409
  const tools = await tryMakeUtils();
418
410
 
419
- const parseAmount = makeParseAmount(
420
- tools.agoricNames,
421
- msg => new InvalidArgumentError(msg),
422
- );
423
- const offer = Offers.auction.Bid(tools.agoricNames.brand, {
424
- ...opts,
425
- parseAmount,
426
- });
411
+ const offer = Offers.auction.Bid(tools.agoricNames, opts);
427
412
 
428
413
  if (generateOnly) {
429
414
  outputActionAndHint(
@@ -441,6 +426,8 @@ inter auction status
441
426
  const parsePercent = v => {
442
427
  const p = Number(v);
443
428
  if (!(p >= -100 && p <= 100)) {
429
+ // InvalidArgumentError is a class constructor, and so
430
+ // must be invoked with `new`.
444
431
  throw new InvalidArgumentError('must be between -100 and 100');
445
432
  }
446
433
  return p / 100;
@@ -464,14 +451,7 @@ inter auction status
464
451
  async ({ generateOnly, ...opts }) => {
465
452
  const tools = await tryMakeUtils();
466
453
 
467
- const parseAmount = makeParseAmount(
468
- tools.agoricNames,
469
- msg => new InvalidArgumentError(msg),
470
- );
471
- const offer = Offers.auction.Bid(tools.agoricNames.brand, {
472
- ...opts,
473
- parseAmount,
474
- });
454
+ const offer = Offers.auction.Bid(tools.agoricNames, opts);
475
455
  if (generateOnly) {
476
456
  outputActionAndHint(
477
457
  { method: 'executeOffer', offer },
@@ -510,11 +490,13 @@ inter auction status
510
490
  return;
511
491
  }
512
492
 
513
- const { networkConfig, readLatestHead } = await tryMakeUtils();
493
+ const { networkConfig, readPublished } = await tryMakeUtils();
514
494
 
515
- const current = await getCurrent(from, { readLatestHead });
495
+ const current = await getCurrent(from, { readPublished });
516
496
  const liveIds = current.liveOffers.map(([i, _s]) => i);
517
497
  if (!liveIds.includes(id)) {
498
+ // InvalidArgumentError is a class constructor, and so
499
+ // must be invoked with `new`.
518
500
  throw new InvalidArgumentError(
519
501
  `${id} not in live offer ids: ${liveIds}`,
520
502
  );
@@ -535,7 +517,7 @@ inter auction status
535
517
  show({ timestamp, height, offerId: id, txhash });
536
518
 
537
519
  const checkGone = async blockInfo => {
538
- const pollResult = await getCurrent(from, { readLatestHead });
520
+ const pollResult = await getCurrent(from, { readPublished });
539
521
  const found = pollResult.liveOffers.find(([i, _]) => i === id);
540
522
  if (found) throw Error('retry');
541
523
  return blockInfo;
@@ -577,11 +559,11 @@ $ inter bid list --from my-acct
577
559
  * }} opts
578
560
  */
579
561
  async opts => {
580
- const { agoricNames, readLatestHead, storedWalletState } =
562
+ const { agoricNames, readPublished, storedWalletState } =
581
563
  await tryMakeUtils();
582
564
 
583
565
  const [current, state] = await Promise.all([
584
- getCurrent(opts.from, { readLatestHead }),
566
+ getCurrent(opts.from, { readPublished }),
585
567
  storedWalletState(opts.from),
586
568
  ]);
587
569
  const entries = opts.all
@@ -1,44 +1,59 @@
1
- /* eslint-disable no-await-in-loop */
2
- /* eslint-disable @jessie.js/no-nested-await */
3
1
  // @ts-check
4
2
  /* eslint-disable func-names */
5
- /* global fetch, setTimeout, process */
6
- import { Fail } from '@agoric/assert';
3
+ /* eslint-env node */
4
+ import {
5
+ fetchEnvNetworkConfig,
6
+ makeAgoricNames,
7
+ makeVstorageKit,
8
+ makeWalletUtils,
9
+ storageHelper,
10
+ } from '@agoric/client-utils';
7
11
  import { Offers } from '@agoric/inter-protocol/src/clientSupport.js';
12
+ import { oracleBrandFeedName } from '@agoric/inter-protocol/src/proposals/utils.js';
13
+ import { Fail } from '@endo/errors';
8
14
  import { Nat } from '@endo/nat';
9
15
  import { Command } from 'commander';
10
- import * as cp from 'child_process';
11
16
  import { inspect } from 'util';
12
17
  import { normalizeAddressWithOptions } from '../lib/chain.js';
13
- import { getNetworkConfig, makeRpcUtils, storageHelper } from '../lib/rpc.js';
18
+ import { bigintReplacer } from '../lib/format.js';
14
19
  import {
15
20
  getCurrent,
16
- makeWalletUtils,
17
21
  outputAction,
18
22
  sendAction,
23
+ sendHint,
19
24
  } from '../lib/wallet.js';
20
- import { bigintReplacer } from '../lib/format.js';
25
+
26
+ /** @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; */
21
27
 
22
28
  // XXX support other decimal places
23
29
  const COSMOS_UNIT = 1_000_000n;
24
- const scaleDecimals = num => BigInt(num * Number(COSMOS_UNIT));
30
+ /** @param {number} num */
31
+ const scaleDecimals = num => BigInt(Math.round(num * Number(COSMOS_UNIT)));
25
32
 
26
33
  /**
27
- * @param {import('anylogger').Logger} logger
34
+ * Prints JSON output to stdout and diagnostic info (like logs) to stderr
35
+ *
28
36
  * @param {{
29
- * delay?: (ms: number) => Promise<void>,
30
- * execFileSync?: typeof import('child_process').execFileSync,
31
- * env?: Record<string, string | undefined>,
32
- * stdout?: Pick<import('stream').Writable,'write'>,
33
- * }} [io]
37
+ * createCommand: typeof import('commander').createCommand,
38
+ * env: Partial<Record<string, string>>,
39
+ * execFileSync: typeof import('child_process').execFileSync,
40
+ * now: () => number,
41
+ * setTimeout: typeof setTimeout,
42
+ * stderr: Pick<import('stream').Writable,'write'>,
43
+ * stdout: Pick<import('stream').Writable,'write'>,
44
+ * }} process
45
+ * @param {import('anylogger').Logger} [logger]
34
46
  */
35
- export const makeOracleCommand = (logger, io = {}) => {
36
- const {
37
- delay = ms => new Promise(resolve => setTimeout(resolve, ms)),
38
- execFileSync = cp.execFileSync,
39
- env = process.env,
40
- stdout = process.stdout,
41
- } = io;
47
+ export const makeOracleCommand = (
48
+ { env, execFileSync, setTimeout, stderr, stdout },
49
+ logger,
50
+ ) => {
51
+ /**
52
+ * @param {number} ms
53
+ * @returns {Promise<void>}
54
+ */
55
+ const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
56
+
42
57
  const oracle = new Command('oracle')
43
58
  .description('Oracle commands')
44
59
  .usage(
@@ -71,22 +86,31 @@ export const makeOracleCommand = (logger, io = {}) => {
71
86
  env.AGORIC_KEYRING_BACKEND,
72
87
  );
73
88
 
89
+ const normalizeAddress = literalOrName =>
90
+ normalizeAddressWithOptions(literalOrName, oracle.opts(), {
91
+ execFileSync,
92
+ });
93
+
74
94
  const rpcTools = async () => {
75
95
  // XXX pass fetch to getNetworkConfig() explicitly
76
- const networkConfig = await getNetworkConfig(env);
77
- const utils = await makeRpcUtils({ fetch });
96
+ const networkConfig = await fetchEnvNetworkConfig({
97
+ env: process.env,
98
+ fetch,
99
+ });
100
+ const vsk = makeVstorageKit({ fetch }, networkConfig);
101
+ const agoricNames = await makeAgoricNames(vsk.fromBoard, vsk.vstorage);
78
102
 
79
103
  const lookupPriceAggregatorInstance = ([brandIn, brandOut]) => {
80
- const name = `${brandIn}-${brandOut} price feed`;
81
- const instance = utils.agoricNames.instance[name];
104
+ const name = oracleBrandFeedName(brandIn, brandOut);
105
+ const instance = agoricNames.instance[name];
82
106
  if (!instance) {
83
- logger.debug('known instances:', utils.agoricNames.instance);
107
+ logger && logger.debug('known instances:', agoricNames.instance);
84
108
  throw Error(`Unknown instance ${name}`);
85
109
  }
86
110
  return instance;
87
111
  };
88
112
 
89
- return { ...utils, networkConfig, lookupPriceAggregatorInstance };
113
+ return { ...vsk, networkConfig, lookupPriceAggregatorInstance };
90
114
  };
91
115
 
92
116
  oracle
@@ -119,12 +143,15 @@ export const makeOracleCommand = (logger, io = {}) => {
119
143
  proposal: {},
120
144
  };
121
145
 
122
- outputAction({
123
- method: 'executeOffer',
124
- offer,
125
- });
146
+ outputAction(
147
+ {
148
+ method: 'executeOffer',
149
+ offer,
150
+ },
151
+ stdout,
152
+ );
126
153
 
127
- console.warn('Now execute the prepared offer');
154
+ stderr.write(sendHint);
128
155
  });
129
156
 
130
157
  oracle
@@ -154,24 +181,27 @@ export const makeOracleCommand = (logger, io = {}) => {
154
181
  opts.oracleAdminAcceptOfferId,
155
182
  );
156
183
 
157
- outputAction({
158
- method: 'executeOffer',
159
- offer,
160
- });
184
+ outputAction(
185
+ {
186
+ method: 'executeOffer',
187
+ offer,
188
+ },
189
+ stdout,
190
+ );
161
191
 
162
- console.warn('Now execute the prepared offer');
192
+ stderr.write(sendHint);
163
193
  });
164
194
 
165
- const findOracleCap = async (from, readLatestHead) => {
166
- const current = await getCurrent(from, { readLatestHead });
195
+ const findOracleCap = async (instance, from, readPublished) => {
196
+ const current = await getCurrent(from, { readPublished });
167
197
 
168
198
  const { offerToUsedInvitation: entries } = /** @type {any} */ (current);
169
199
  Array.isArray(entries) || Fail`entries must be an array: ${entries}`;
170
200
 
171
201
  for (const [offerId, { value }] of entries) {
172
202
  /** @type {{ description: string, instance: unknown }[]} */
173
- const [{ description }] = value;
174
- if (description === 'oracle invitation') {
203
+ const [{ description, instance: candidate }] = value;
204
+ if (description === 'oracle invitation' && candidate === instance) {
175
205
  return offerId;
176
206
  }
177
207
  }
@@ -180,11 +210,21 @@ export const makeOracleCommand = (logger, io = {}) => {
180
210
  oracle
181
211
  .command('find-continuing-id')
182
212
  .description('print id of specified oracle continuing invitation')
183
- .requiredOption('--from <address>', 'from address', String)
213
+ .requiredOption(
214
+ '--from <address>',
215
+ 'wallet address literal or name',
216
+ normalizeAddress,
217
+ )
218
+ .requiredOption(
219
+ '--pair [brandIn.brandOut]',
220
+ 'token pair (brandIn.brandOut)',
221
+ s => s.split('.'),
222
+ )
184
223
  .action(async opts => {
185
- const { readLatestHead } = await makeRpcUtils({ fetch });
224
+ const { readPublished, lookupPriceAggregatorInstance } = await rpcTools();
225
+ const instance = lookupPriceAggregatorInstance(opts.pair);
186
226
 
187
- const offerId = await findOracleCap(opts.from, readLatestHead);
227
+ const offerId = await findOracleCap(instance, opts.from, readPublished);
188
228
  if (!offerId) {
189
229
  console.error('No continuing ids found');
190
230
  }
@@ -212,11 +252,6 @@ export const makeOracleCommand = (logger, io = {}) => {
212
252
  console.log(inspect(capDatas[0], { depth: 10, colors: true }));
213
253
  });
214
254
 
215
- /** @param {string} literalOrName */
216
- const normalizeAddress = literalOrName =>
217
- normalizeAddressWithOptions(literalOrName, oracle.opts(), {
218
- execFileSync,
219
- });
220
255
  const show = (info, indent = false) =>
221
256
  stdout.write(
222
257
  `${JSON.stringify(info, bigintReplacer, indent ? 2 : undefined)}\n`,
@@ -250,21 +285,22 @@ export const makeOracleCommand = (logger, io = {}) => {
250
285
  * }}
251
286
  */ { pair, keys, price },
252
287
  ) => {
253
- const { readLatestHead, networkConfig } = await rpcTools();
254
- const wutil = await makeWalletUtils(
255
- { fetch, execFileSync, delay },
288
+ const {
289
+ readLatestHead,
290
+ readPublished,
256
291
  networkConfig,
257
- );
292
+ lookupPriceAggregatorInstance,
293
+ } = await rpcTools();
294
+ const wutil = await makeWalletUtils({ fetch, delay }, networkConfig);
258
295
  const unitPrice = scaleDecimals(price);
259
296
 
260
- console.error(`${pair[0]}-${pair[1]}_price_feed: before setPrice`);
297
+ const feedPath = `published.priceFeed.${pair[0]}-${pair[1]}_price_feed`;
261
298
 
262
299
  const readPrice = () =>
263
300
  /** @type {Promise<PriceDescription>} */ (
264
- readLatestHead(
265
- `published.priceFeed.${pair[0]}-${pair[1]}_price_feed`,
266
- ).catch(err => {
267
- console.warn(`cannot get ${pair[0]}-${pair[1]}_price_feed`, err);
301
+ readLatestHead(feedPath).catch(() => {
302
+ const viewer = `https://vstorage.agoric.net/#${networkConfig.rpcAddrs[0]}|published,published.priceFeed|${feedPath}`;
303
+ stderr.write(`no existing price data; see ${viewer}`);
268
304
  return undefined;
269
305
  })
270
306
  );
@@ -283,40 +319,61 @@ export const makeOracleCommand = (logger, io = {}) => {
283
319
  show(fmtFeed(before));
284
320
  }
285
321
 
286
- console.error(
287
- 'Choose lead oracle operator order based on latestRound...',
288
- );
289
322
  const keyOrder = keys.map(normalizeAddress);
290
- const latestRoundP = readLatestHead(
291
- `published.priceFeed.${pair[0]}-${pair[1]}_price_feed.latestRound`,
292
- );
293
- await Promise.race([
294
- delay(5000),
295
- latestRoundP.then(round => {
296
- // @ts-expect-error XXX get type from contract
297
- const { roundId, startedAt, startedBy } = round;
298
- show({
299
- startedAt: fmtSecs(startedAt.absValue),
300
- roundId,
301
- startedBy,
302
- });
303
- if (startedBy === keyOrder[0]) {
304
- keyOrder.reverse();
305
- }
306
- }),
307
- ]).catch(err => {
308
- console.warn(err);
309
- });
323
+ if (before) {
324
+ console.error(
325
+ 'Choose lead oracle operator order based on latestRound...',
326
+ );
310
327
 
311
- console.error('pushPrice from each:', keyOrder);
328
+ const latestRoundP =
329
+ /** @type {Promise<{roundId: number, startedAt: import('@agoric/time').TimestampRecord, startedBy: string}>} */ (
330
+ readLatestHead(
331
+ `published.priceFeed.${pair[0]}-${pair[1]}_price_feed.latestRound`,
332
+ )
333
+ );
334
+ await Promise.race([
335
+ delay(5000),
336
+ latestRoundP.then(round => {
337
+ const { roundId, startedAt, startedBy } = round;
338
+ show({
339
+ startedAt: fmtSecs(startedAt.absValue),
340
+ roundId,
341
+ startedBy,
342
+ });
343
+ if (startedBy === keyOrder[0]) {
344
+ keyOrder.reverse();
345
+ }
346
+ }),
347
+ ]).catch(err => {
348
+ stderr.write(err);
349
+ });
350
+ }
351
+
352
+ const instance = lookupPriceAggregatorInstance(pair);
353
+ const adminOfferIds = {};
312
354
  for await (const from of keyOrder) {
313
- const oracleAdminAcceptOfferId = await findOracleCap(
355
+ adminOfferIds[from] = await findOracleCap(
356
+ instance,
314
357
  from,
315
- readLatestHead,
358
+ readPublished,
316
359
  );
317
- if (!oracleAdminAcceptOfferId) {
318
- throw Error(`no oracle invitation found: ${from}`);
360
+ if (!adminOfferIds[from]) {
361
+ console.error(
362
+ `Failed to find an offer accepting oracle invitation for ${from}. Accept and try again:`,
363
+ );
364
+ console.error(
365
+ ` agops oracle accept > accept.json; agoric wallet send --from ${from} --offer accept.json`,
366
+ );
319
367
  }
368
+ }
369
+ assert(
370
+ Object.values(adminOfferIds).every(x => x),
371
+ 'Missing oracle admin offer ids',
372
+ );
373
+
374
+ console.error('pushPrice from each:', keyOrder);
375
+ for await (const from of keyOrder) {
376
+ const oracleAdminAcceptOfferId = adminOfferIds[from];
320
377
  show({ from, oracleAdminAcceptOfferId });
321
378
  const offerId = `pushPrice-${Date.now()}`;
322
379
  const offer = Offers.fluxAggregator.PushPrice(
@@ -1,29 +1,29 @@
1
- /* eslint-disable no-await-in-loop */
2
- /* eslint-disable @jessie.js/no-nested-await */
3
1
  // @ts-check
4
2
  /* eslint-disable func-names */
5
- /* global process */
3
+ /* eslint-env node */
6
4
  import {
7
5
  iterateEach,
8
6
  makeCastingSpec,
9
7
  makeFollower,
10
8
  makeLeaderFromRpcAddresses,
11
9
  } from '@agoric/casting';
10
+ import { fetchEnvNetworkConfig } from '@agoric/client-utils';
11
+ import { slotToRemotable } from '@agoric/internal/src/storage-test-utils.js';
12
+ import { boardSlottingMarshaller } from '@agoric/vats/tools/board-utils.js';
12
13
  import { Command } from 'commander';
13
14
  import fs from 'fs';
14
15
  import { exit } from 'process';
15
- import { slotToRemotable } from '@agoric/internal/src/storage-test-utils.js';
16
- import { boardSlottingMarshaller } from '@agoric/vats/tools/board-utils.js';
17
16
  import { makeLeaderOptions } from '../lib/casting.js';
18
17
  import {
19
18
  execSwingsetTransaction,
20
19
  normalizeAddressWithOptions,
21
20
  } from '../lib/chain.js';
22
- import { networkConfig } from '../lib/rpc.js';
23
21
 
24
22
  // tight for perf testing but less than this tends to hang.
25
23
  const SLEEP_SECONDS = 0.1;
26
24
 
25
+ const networkConfig = await fetchEnvNetworkConfig({ env: process.env, fetch });
26
+
27
27
  /**
28
28
  * @param {import('anylogger').Logger} logger
29
29
  */
@@ -51,6 +51,7 @@ export const makePerfCommand = logger => {
51
51
  'address literal or name',
52
52
  normalizeAddress,
53
53
  )
54
+ .option('--verbose')
54
55
  .action(async function (opts) {
55
56
  const sharedOpts = perf.opts();
56
57
  logger.warn({ sharedOpts, opts });
@@ -63,15 +64,13 @@ export const makePerfCommand = logger => {
63
64
 
64
65
  const spec = `:published.wallet.${opts.from}`;
65
66
 
66
- const leaderOptions = makeLeaderOptions({
67
- sleep: SLEEP_SECONDS,
68
- jitter: 0,
69
- log: () => undefined,
70
- });
71
-
72
67
  const leader = makeLeaderFromRpcAddresses(
73
68
  networkConfig.rpcAddrs,
74
- leaderOptions,
69
+ makeLeaderOptions({
70
+ sleep: SLEEP_SECONDS,
71
+ jitter: 0,
72
+ log: console.warn,
73
+ }),
75
74
  );
76
75
 
77
76
  logger.warn('Following', spec);
@@ -86,9 +85,10 @@ export const makePerfCommand = logger => {
86
85
  if (status.error) {
87
86
  console.error(status.error);
88
87
  exit(1);
89
- } else if (status.numWantsSatisfied)
88
+ } else if (status.numWantsSatisfied) {
90
89
  process.stdout.write(`satisfied: ${status.numWantsSatisfied}\n`);
91
- exit(0);
90
+ exit(0);
91
+ }
92
92
  }
93
93
  }
94
94
  };
@@ -102,7 +102,11 @@ export const makePerfCommand = logger => {
102
102
  if (sharedOpts.home) {
103
103
  cmd.push(`--home=${sharedOpts.home}`);
104
104
  }
105
- execSwingsetTransaction(cmd, { from: opts.from, ...networkConfig });
105
+ execSwingsetTransaction(cmd, {
106
+ from: opts.from,
107
+ verbose: opts.verbose,
108
+ ...networkConfig,
109
+ });
106
110
  });
107
111
 
108
112
  return perf;