agoric 0.21.2-u11wf.0 → 0.21.2-upgrade-16-dev-8879538.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.
@@ -1,4 +1,3 @@
1
- /* eslint-disable @jessie.js/no-nested-await */
2
1
  // @ts-check
3
2
  /* eslint-disable func-names */
4
3
  /* global globalThis, process, setTimeout */
@@ -14,7 +13,17 @@ import {
14
13
  sendAction,
15
14
  } from '../lib/wallet.js';
16
15
 
17
- /** @typedef {import('@agoric/smart-wallet/src/offers.js').OfferSpec} OfferSpec */
16
+ /**
17
+ * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js'
18
+ * @import {QuestionDetails} from '@agoric/governance/src/types.js'
19
+ */
20
+
21
+ const collectValues = (val, memo) => {
22
+ memo.push(val);
23
+ return memo;
24
+ };
25
+
26
+ const defaultKeyring = process.env.AGORIC_KEYRING_BACKEND || 'test';
18
27
 
19
28
  /**
20
29
  * @param {import('anylogger').Logger} _logger
@@ -27,7 +36,7 @@ import {
27
36
  * delay?: (ms: number) => Promise<void>,
28
37
  * }} [io]
29
38
  */
30
- export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
39
+ export const makeGovCommand = (_logger, io = {}) => {
31
40
  const {
32
41
  // Allow caller to provide access explicitly, but
33
42
  // default to conventional ambient IO facilities.
@@ -39,11 +48,22 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
39
48
  delay = ms => new Promise(resolve => setTimeout(resolve, ms)),
40
49
  } = io;
41
50
 
42
- const ec = new Command('ec').description('Economic Committee commands');
51
+ const cmd = new Command('gov').description('Electoral governance commands');
52
+ // backwards compatibility with less general "ec" command. To make this work
53
+ // the new CLI options default to the values used for Economic Committee
54
+ cmd.alias('ec');
55
+ cmd.option(
56
+ '--keyring-backend <os|file|test>',
57
+ `keyring's backend (os|file|test) (default "${defaultKeyring}")`,
58
+ defaultKeyring,
59
+ );
43
60
 
44
61
  /** @param {string} literalOrName */
45
62
  const normalizeAddress = literalOrName =>
46
- normalizeAddressWithOptions(literalOrName, { keyringBackend: 'test' });
63
+ normalizeAddressWithOptions(literalOrName, {
64
+ // FIXME does not observe keyring-backend option, which isn't available during arg parsing
65
+ keyringBackend: defaultKeyring,
66
+ });
47
67
 
48
68
  /** @type {(info: unknown, indent?: unknown) => boolean } */
49
69
  const show = (info, indent) =>
@@ -62,17 +82,23 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
62
82
  * given a sendFrom address; else print it.
63
83
  *
64
84
  * @param {{
65
- * toOffer: (agoricNames: *, current: import('@agoric/smart-wallet/src/smartWallet').CurrentWalletRecord | undefined) => OfferSpec,
85
+ * toOffer: (agoricNames: *, current: import('@agoric/smart-wallet/src/smartWallet.js').CurrentWalletRecord | undefined) => OfferSpec,
66
86
  * sendFrom?: string | undefined,
87
+ * keyringBackend: string,
67
88
  * instanceName?: string,
68
89
  * }} detail
69
90
  * @param {Awaited<ReturnType<makeRpcUtils>>} [optUtils]
70
91
  */
71
- const processOffer = async function ({ toOffer, sendFrom }, optUtils) {
92
+ const processOffer = async function (
93
+ { toOffer, sendFrom, keyringBackend },
94
+ optUtils,
95
+ ) {
72
96
  const networkConfig = await getNetworkConfig(env);
73
97
  const utils = await (optUtils || makeRpcUtils({ fetch }));
74
98
  const { agoricNames, readLatestHead } = utils;
75
99
 
100
+ assert(keyringBackend, 'missing keyring-backend option');
101
+
76
102
  let current;
77
103
  if (sendFrom) {
78
104
  current = await getCurrent(sendFrom, { readLatestHead });
@@ -90,7 +116,7 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
90
116
  const result = await sendAction(
91
117
  { method: 'executeOffer', offer },
92
118
  {
93
- keyring: { backend: 'test' }, // XXX
119
+ keyring: { backend: keyringBackend },
94
120
  from: sendFrom,
95
121
  verbose: false,
96
122
  ...networkConfig,
@@ -127,29 +153,38 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
127
153
  show(blockInfo);
128
154
  };
129
155
 
130
- ec.command('committee')
131
- .description('accept invitation to join the economic committee')
156
+ cmd
157
+ .command('committee')
158
+ .description('accept invitation to join a committee')
159
+ .requiredOption(
160
+ '--name <string>',
161
+ 'Committee instance name',
162
+ String,
163
+ 'economicCommittee',
164
+ )
132
165
  .option('--voter <number>', 'Voter number', Number, 0)
133
166
  .option(
134
167
  '--offerId <string>',
135
168
  'Offer id',
136
169
  String,
137
- `ecCommittee-${Date.now()}`,
170
+ `gov-committee-${Date.now()}`,
138
171
  )
139
172
  .option(
140
173
  '--send-from <name-or-address>',
141
174
  'Send from address',
142
175
  normalizeAddress,
143
176
  )
144
- .action(async function (opts) {
177
+ .action(async function (opts, options) {
178
+ const { name: instanceName } = opts;
179
+
145
180
  /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
146
181
  const toOffer = (agoricNames, current) => {
147
- const instance = agoricNames.instance.economicCommittee;
148
- assert(instance, `missing economicCommittee`);
182
+ const instance = agoricNames.instance[instanceName];
183
+ assert(instance, `missing ${instanceName}`);
149
184
 
150
185
  if (current) {
151
186
  const found = findContinuingIds(current, agoricNames);
152
- abortIfSeen('economicCommittee', found);
187
+ abortIfSeen(instanceName, found);
153
188
  }
154
189
 
155
190
  return {
@@ -165,28 +200,37 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
165
200
 
166
201
  await processOffer({
167
202
  toOffer,
168
- instanceName: 'economicCommittee',
169
- ...opts,
203
+ instanceName,
204
+ sendFrom: opts.sendFrom,
205
+ keyringBackend: options.optsWithGlobals().keyringBackend,
170
206
  });
171
207
  });
172
208
 
173
- ec.command('charter')
209
+ cmd
210
+ .command('charter')
174
211
  .description('accept the charter invitation')
175
- .option('--offerId <string>', 'Offer id', String, `ecCharter-${Date.now()}`)
212
+ .requiredOption(
213
+ '--name <string>',
214
+ 'Charter instance name',
215
+ 'economicCommitteeCharter',
216
+ )
217
+ .option('--offerId <string>', 'Offer id', String, `charter-${Date.now()}`)
176
218
  .option(
177
219
  '--send-from <name-or-address>',
178
220
  'Send from address',
179
221
  normalizeAddress,
180
222
  )
181
- .action(async function (opts) {
223
+ .action(async function (opts, options) {
224
+ const { name: instanceName } = opts;
225
+
182
226
  /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
183
227
  const toOffer = (agoricNames, current) => {
184
- const instance = agoricNames.instance.econCommitteeCharter;
185
- assert(instance, `missing econCommitteeCharter`);
228
+ const instance = agoricNames.instance[instanceName];
229
+ assert(instance, `missing ${instanceName}`);
186
230
 
187
231
  if (current) {
188
232
  const found = findContinuingIds(current, agoricNames);
189
- abortIfSeen('econCommitteeCharter', found);
233
+ abortIfSeen(instanceName, found);
190
234
  }
191
235
 
192
236
  return {
@@ -202,12 +246,14 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
202
246
 
203
247
  await processOffer({
204
248
  toOffer,
205
- instanceName: 'econCommitteeCharter',
206
- ...opts,
249
+ instanceName,
250
+ sendFrom: opts.sendFrom,
251
+ keyringBackend: options.optsWithGlobals().keyringBackend,
207
252
  });
208
253
  });
209
254
 
210
- ec.command('find-continuing-id')
255
+ cmd
256
+ .command('find-continuing-id')
211
257
  .description('print id of specified voting continuing invitation')
212
258
  .requiredOption(
213
259
  '--from <name-or-address>',
@@ -233,7 +279,8 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
233
279
  console.log(match.offerId);
234
280
  });
235
281
 
236
- ec.command('find-continuing-ids')
282
+ cmd
283
+ .command('find-continuing-ids')
237
284
  .description('print records of voting continuing invitations')
238
285
  .requiredOption(
239
286
  '--from <name-or-address>',
@@ -245,12 +292,27 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
245
292
  const current = await getCurrent(opts.from, { readLatestHead });
246
293
 
247
294
  const found = findContinuingIds(current, agoricNames);
248
- found.forEach(it => show({ ...it, address: opts.from }));
295
+ for (const it of found) {
296
+ show({ ...it, address: opts.from });
297
+ }
249
298
  });
250
299
 
251
- ec.command('vote')
252
- .description('vote on a question (hard-coded for now))')
253
- .option('--offerId <number>', 'Offer id', String, `ecVote-${Date.now()}`)
300
+ cmd
301
+ .command('vote')
302
+ .description('vote on latest question')
303
+ .requiredOption(
304
+ '--instance <string>',
305
+ 'Committee name under agoricNames.instances',
306
+ String,
307
+ 'economicCommittee',
308
+ )
309
+ .requiredOption(
310
+ '--pathname <string>',
311
+ 'Committee name under published.committees',
312
+ String,
313
+ 'Economic_Committee',
314
+ )
315
+ .option('--offerId <number>', 'Offer id', String, `gov-vote-${Date.now()}`)
254
316
  .requiredOption(
255
317
  '--forPosition <number>',
256
318
  'index of one position to vote for (within the question description.positions); ',
@@ -261,17 +323,18 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
261
323
  'Send from address',
262
324
  normalizeAddress,
263
325
  )
264
- .action(async function (opts) {
326
+ .action(async function (opts, options) {
265
327
  const utils = await makeRpcUtils({ fetch });
266
328
  const { readLatestHead } = utils;
267
329
 
268
330
  const info = await readLatestHead(
269
- 'published.committees.Economic_Committee.latestQuestion',
331
+ `published.committees.${opts.pathname}.latestQuestion`,
270
332
  ).catch(err => {
271
333
  throw new CommanderError(1, 'VSTORAGE_FAILURE', err.message);
272
334
  });
335
+
273
336
  // XXX runtime shape-check
274
- const questionDesc = /** @type {any} */ (info);
337
+ const questionDesc = /** @type {QuestionDetails} */ (info);
275
338
 
276
339
  // TODO support multiple position arguments
277
340
  const chosenPositions = [questionDesc.positions[opts.forPosition]];
@@ -280,9 +343,7 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
280
343
  /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
281
344
  const toOffer = (agoricNames, current) => {
282
345
  const cont = current ? findContinuingIds(current, agoricNames) : [];
283
- const votingRight = cont.find(
284
- it => it.instance === agoricNames.instance.economicCommittee,
285
- );
346
+ const votingRight = cont.find(it => it.instanceName === opts.instance);
286
347
  if (!votingRight) {
287
348
  console.debug('continuing ids', cont, 'for', current);
288
349
  throw new CommanderError(
@@ -307,8 +368,89 @@ export const makeEconomicCommiteeCommand = (_logger, io = {}) => {
307
368
  };
308
369
  };
309
370
 
310
- await processOffer({ toOffer, sendFrom: opts.sendFrom }, utils);
371
+ await processOffer(
372
+ {
373
+ toOffer,
374
+ sendFrom: opts.sendFrom,
375
+ keyringBackend: options.optsWithGlobals().keyringBackend,
376
+ },
377
+ utils,
378
+ );
379
+ });
380
+
381
+ cmd
382
+ .command('proposePauseOffers')
383
+ .description('propose a vote to pause offers')
384
+ .option(
385
+ '--send-from <name-or-address>',
386
+ 'Send from address',
387
+ normalizeAddress,
388
+ )
389
+ .option(
390
+ '--offerId <string>',
391
+ 'Offer id',
392
+ String,
393
+ `proposePauseOffers-${Date.now()}`,
394
+ )
395
+ .requiredOption(
396
+ '--instance <string>',
397
+ 'name of governed instance in agoricNames',
398
+ )
399
+ .requiredOption(
400
+ '--substring <string>',
401
+ 'an offer string to pause (can be repeated)',
402
+ collectValues,
403
+ [],
404
+ )
405
+ .option(
406
+ '--deadline <minutes>',
407
+ 'minutes from now to close the vote',
408
+ Number,
409
+ 1,
410
+ )
411
+ .action(async function (opts, options) {
412
+ const { instance: instanceName } = opts;
413
+
414
+ /** @type {Parameters<typeof processOffer>[0]['toOffer']} */
415
+ const toOffer = (agoricNames, current) => {
416
+ const instance = agoricNames.instance[instanceName];
417
+ assert(instance, `missing ${instanceName}`);
418
+ assert(current, 'missing current wallet');
419
+
420
+ const known = findContinuingIds(current, agoricNames);
421
+
422
+ assert(known, 'could not find committee acceptance offer id');
423
+
424
+ // TODO magic string
425
+ const match = known.find(
426
+ r => r.description === 'charter member invitation',
427
+ );
428
+ assert(match, 'no offer found for charter member invitation');
429
+
430
+ return {
431
+ id: opts.offerId,
432
+ invitationSpec: {
433
+ source: 'continuing',
434
+ previousOffer: match.offerId,
435
+ invitationMakerName: 'VoteOnPauseOffers',
436
+ // ( instance, strings list, timer deadline seconds )
437
+ invitationArgs: harden([
438
+ instance,
439
+ opts.substring,
440
+ BigInt(opts.deadline * 60 + Math.round(Date.now() / 1000)),
441
+ ]),
442
+ },
443
+ proposal: {},
444
+ };
445
+ };
446
+
447
+ await processOffer({
448
+ toOffer,
449
+ instanceName,
450
+ sendFrom: opts.sendFrom,
451
+ keyringBackend: options.optsWithGlobals().keyringBackend,
452
+ });
311
453
  });
312
454
 
313
- return ec;
455
+ return cmd;
314
456
  };
@@ -11,11 +11,6 @@ import { Offers } from '@agoric/inter-protocol/src/clientSupport.js';
11
11
  import { objectMap } from '@agoric/internal';
12
12
  import { M, matches } from '@agoric/store';
13
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
-
19
14
  import { normalizeAddressWithOptions, pollBlocks } from '../lib/chain.js';
20
15
  import {
21
16
  asBoardRemote,
@@ -25,7 +20,6 @@ import {
25
20
  import { getNetworkConfig } from '../lib/rpc.js';
26
21
  import {
27
22
  getCurrent,
28
- makeParseAmount,
29
23
  makeWalletUtils,
30
24
  outputActionAndHint,
31
25
  sendAction,
@@ -39,16 +33,16 @@ const bidInvitationShape = harden({
39
33
  callPipe: [['makeBidInvitation', M.any()]],
40
34
  });
41
35
 
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 */
36
+ /** @import {VBankAssetDetail} from '@agoric/vats/tools/board-utils.js'; */
37
+ /** @import {TryExitOfferAction} from '@agoric/smart-wallet/src/smartWallet.js'; */
38
+ /** @import {OfferSpec as BidSpec} from '@agoric/inter-protocol/src/auction/auctionBook.js' */
39
+ /** @import {ScheduleNotification} from '@agoric/inter-protocol/src/auction/scheduler.js' */
40
+ /** @import {BookDataNotification} from '@agoric/inter-protocol/src/auction/auctionBook.js' */
47
41
 
48
42
  /**
49
43
  * Format amounts, prices etc. based on brand board Ids, displayInfo
50
44
  *
51
- * @param {AssetDescriptor[]} assets
45
+ * @param {VBankAssetDetail[]} assets
52
46
  */
53
47
  const makeFormatters = assets => {
54
48
  const r4 = x => Math.round(x * 10_000) / 10_000;
@@ -71,12 +65,12 @@ const makeFormatters = assets => {
71
65
  r4(100 - (Number(r.numerator.value) / Number(r.denominator.value)) * 100);
72
66
 
73
67
  // XXX real TimeMath.absValue requires real Remotable timerBrand
74
- /** @param {import('@agoric/time/src/types.js').Timestamp} ts */
68
+ /** @param {import('@agoric/time').Timestamp} ts */
75
69
  const absValue = ts => (typeof ts === 'bigint' ? ts : ts.absValue);
76
70
 
77
- /** @param {import('@agoric/time/src/types.js').Timestamp} tr */
71
+ /** @param {import('@agoric/time').Timestamp} tr */
78
72
  const absTime = tr => new Date(Number(absValue(tr)) * 1000).toISOString();
79
- /** @param {import('@agoric/time/src/types.js').RelativeTimeRecord} tr */
73
+ /** @param {import('@agoric/time').RelativeTimeRecord} tr */
80
74
  const relTime = tr =>
81
75
  new Date(Number(tr.relValue) * 1000).toISOString().slice(11, 19);
82
76
 
@@ -88,7 +82,7 @@ const makeFormatters = assets => {
88
82
  * @param {(_: T) => string} f
89
83
  * @returns { (x: T | null | undefined ) => string | undefined }
90
84
  */
91
- const maybe = f => x => x ? f(x) : undefined;
85
+ const maybe = f => x => (x ? f(x) : undefined);
92
86
 
93
87
  return {
94
88
  amount,
@@ -108,7 +102,7 @@ const makeFormatters = assets => {
108
102
  * Dynamic check that an OfferStatus is also a BidSpec.
109
103
  *
110
104
  * @param {import('@agoric/smart-wallet/src/offers.js').OfferStatus} offerStatus
111
- * @param {Awaited<ReturnType<import('../lib/rpc').makeAgoricNames>>} agoricNames
105
+ * @param {import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes} agoricNames
112
106
  * @param {typeof console.warn} warn
113
107
  * returns null if offerStatus is not a BidSpec
114
108
  */
@@ -144,7 +138,7 @@ const coerceBid = (offerStatus, agoricNames, warn) => {
144
138
  *
145
139
  * @param {import('@agoric/smart-wallet/src/offers.js').OfferStatus &
146
140
  * { offerArgs: BidSpec}} bid
147
- * @param {import('agoric/src/lib/format.js').AssetDescriptor[]} assets
141
+ * @param {VBankAssetDetail[]} assets
148
142
  */
149
143
  export const fmtBid = (bid, assets) => {
150
144
  const fmt = makeFormatters(assets);
@@ -206,6 +200,10 @@ export const makeInterCommand = (
206
200
  const interCmd = createCommand('inter')
207
201
  .description('Inter Protocol commands for liquidation bidding etc.')
208
202
  .option('--home <dir>', 'agd CosmosSDK application home directory')
203
+ .option(
204
+ '--fees <amount>',
205
+ 'set fees for transaction broadcast (e.g. 5000ubld)',
206
+ )
209
207
  .option(
210
208
  '--keyring-backend <os|file|test>',
211
209
  `keyring's backend (os|file|test) (default "${
@@ -238,7 +236,6 @@ export const makeInterCommand = (
238
236
  try {
239
237
  // XXX pass fetch to getNetworkConfig() explicitly
240
238
  // await null above makes this await safe
241
- // eslint-disable-next-line @jessie.js/no-nested-await
242
239
  const networkConfig = await getNetworkConfig(env);
243
240
  return makeWalletUtils({ fetch, execFileSync, delay }, networkConfig);
244
241
  } catch (err) {
@@ -339,10 +336,10 @@ inter auction status
339
336
  const { networkConfig, agoricNames, pollOffer } = tools;
340
337
  const io = { ...networkConfig, execFileSync, delay, stdout };
341
338
 
342
- const { home, keyringBackend: backend } = interCmd.opts();
339
+ const { home, keyringBackend: backend, fees } = interCmd.opts();
343
340
  const result = await sendAction(
344
341
  { method: 'executeOffer', offer },
345
- { keyring: { home, backend }, from, verbose: false, dryRun, ...io },
342
+ { keyring: { home, backend }, from, fees, verbose: false, dryRun, ...io },
346
343
  );
347
344
  if (dryRun) {
348
345
  return;
@@ -416,14 +413,7 @@ inter auction status
416
413
  async ({ generateOnly, dryRun, ...opts }) => {
417
414
  const tools = await tryMakeUtils();
418
415
 
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
- });
416
+ const offer = Offers.auction.Bid(tools.agoricNames, opts);
427
417
 
428
418
  if (generateOnly) {
429
419
  outputActionAndHint(
@@ -464,14 +454,7 @@ inter auction status
464
454
  async ({ generateOnly, ...opts }) => {
465
455
  const tools = await tryMakeUtils();
466
456
 
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
- });
457
+ const offer = Offers.auction.Bid(tools.agoricNames, opts);
475
458
  if (generateOnly) {
476
459
  outputActionAndHint(
477
460
  { method: 'executeOffer', offer },
@@ -1,5 +1,3 @@
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
3
  /* global fetch, setTimeout, process */
@@ -9,6 +7,7 @@ import { Nat } from '@endo/nat';
9
7
  import { Command } from 'commander';
10
8
  import * as cp from 'child_process';
11
9
  import { inspect } from 'util';
10
+ import { oracleBrandFeedName } from '@agoric/inter-protocol/src/proposals/utils.js';
12
11
  import { normalizeAddressWithOptions } from '../lib/chain.js';
13
12
  import { getNetworkConfig, makeRpcUtils, storageHelper } from '../lib/rpc.js';
14
13
  import {
@@ -16,9 +15,12 @@ import {
16
15
  makeWalletUtils,
17
16
  outputAction,
18
17
  sendAction,
18
+ sendHint,
19
19
  } from '../lib/wallet.js';
20
20
  import { bigintReplacer } from '../lib/format.js';
21
21
 
22
+ /** @import {PriceAuthority, PriceDescription, PriceQuote, PriceQuoteValue, PriceQuery,} from '@agoric/zoe/tools/types.js'; */
23
+
22
24
  // XXX support other decimal places
23
25
  const COSMOS_UNIT = 1_000_000n;
24
26
  const scaleDecimals = num => BigInt(num * Number(COSMOS_UNIT));
@@ -71,13 +73,18 @@ export const makeOracleCommand = (logger, io = {}) => {
71
73
  env.AGORIC_KEYRING_BACKEND,
72
74
  );
73
75
 
76
+ const normalizeAddress = literalOrName =>
77
+ normalizeAddressWithOptions(literalOrName, oracle.opts(), {
78
+ execFileSync,
79
+ });
80
+
74
81
  const rpcTools = async () => {
75
82
  // XXX pass fetch to getNetworkConfig() explicitly
76
83
  const networkConfig = await getNetworkConfig(env);
77
84
  const utils = await makeRpcUtils({ fetch });
78
85
 
79
86
  const lookupPriceAggregatorInstance = ([brandIn, brandOut]) => {
80
- const name = `${brandIn}-${brandOut} price feed`;
87
+ const name = oracleBrandFeedName(brandIn, brandOut);
81
88
  const instance = utils.agoricNames.instance[name];
82
89
  if (!instance) {
83
90
  logger.debug('known instances:', utils.agoricNames.instance);
@@ -124,7 +131,7 @@ export const makeOracleCommand = (logger, io = {}) => {
124
131
  offer,
125
132
  });
126
133
 
127
- console.warn('Now execute the prepared offer');
134
+ console.warn(sendHint);
128
135
  });
129
136
 
130
137
  oracle
@@ -159,10 +166,10 @@ export const makeOracleCommand = (logger, io = {}) => {
159
166
  offer,
160
167
  });
161
168
 
162
- console.warn('Now execute the prepared offer');
169
+ console.warn(sendHint);
163
170
  });
164
171
 
165
- const findOracleCap = async (from, readLatestHead) => {
172
+ const findOracleCap = async (instance, from, readLatestHead) => {
166
173
  const current = await getCurrent(from, { readLatestHead });
167
174
 
168
175
  const { offerToUsedInvitation: entries } = /** @type {any} */ (current);
@@ -170,8 +177,8 @@ export const makeOracleCommand = (logger, io = {}) => {
170
177
 
171
178
  for (const [offerId, { value }] of entries) {
172
179
  /** @type {{ description: string, instance: unknown }[]} */
173
- const [{ description }] = value;
174
- if (description === 'oracle invitation') {
180
+ const [{ description, instance: candidate }] = value;
181
+ if (description === 'oracle invitation' && candidate === instance) {
175
182
  return offerId;
176
183
  }
177
184
  }
@@ -180,11 +187,22 @@ export const makeOracleCommand = (logger, io = {}) => {
180
187
  oracle
181
188
  .command('find-continuing-id')
182
189
  .description('print id of specified oracle continuing invitation')
183
- .requiredOption('--from <address>', 'from address', String)
190
+ .requiredOption(
191
+ '--from <address>',
192
+ 'wallet address literal or name',
193
+ normalizeAddress,
194
+ )
195
+ .requiredOption(
196
+ '--pair [brandIn.brandOut]',
197
+ 'token pair (brandIn.brandOut)',
198
+ s => s.split('.'),
199
+ )
184
200
  .action(async opts => {
185
- const { readLatestHead } = await makeRpcUtils({ fetch });
201
+ const { readLatestHead, lookupPriceAggregatorInstance } =
202
+ await rpcTools();
203
+ const instance = lookupPriceAggregatorInstance(opts.pair);
186
204
 
187
- const offerId = await findOracleCap(opts.from, readLatestHead);
205
+ const offerId = await findOracleCap(instance, opts.from, readLatestHead);
188
206
  if (!offerId) {
189
207
  console.error('No continuing ids found');
190
208
  }
@@ -212,11 +230,6 @@ export const makeOracleCommand = (logger, io = {}) => {
212
230
  console.log(inspect(capDatas[0], { depth: 10, colors: true }));
213
231
  });
214
232
 
215
- /** @param {string} literalOrName */
216
- const normalizeAddress = literalOrName =>
217
- normalizeAddressWithOptions(literalOrName, oracle.opts(), {
218
- execFileSync,
219
- });
220
233
  const show = (info, indent = false) =>
221
234
  stdout.write(
222
235
  `${JSON.stringify(info, bigintReplacer, indent ? 2 : undefined)}\n`,
@@ -250,7 +263,8 @@ export const makeOracleCommand = (logger, io = {}) => {
250
263
  * }}
251
264
  */ { pair, keys, price },
252
265
  ) => {
253
- const { readLatestHead, networkConfig } = await rpcTools();
266
+ const { readLatestHead, networkConfig, lookupPriceAggregatorInstance } =
267
+ await rpcTools();
254
268
  const wutil = await makeWalletUtils(
255
269
  { fetch, execFileSync, delay },
256
270
  networkConfig,
@@ -308,9 +322,12 @@ export const makeOracleCommand = (logger, io = {}) => {
308
322
  console.warn(err);
309
323
  });
310
324
 
325
+ const instance = lookupPriceAggregatorInstance(pair);
326
+
311
327
  console.error('pushPrice from each:', keyOrder);
312
328
  for await (const from of keyOrder) {
313
329
  const oracleAdminAcceptOfferId = await findOracleCap(
330
+ instance,
314
331
  from,
315
332
  readLatestHead,
316
333
  );
@@ -1,5 +1,3 @@
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
3
  /* global process */