@agoric/inter-protocol 0.16.2-dev-73364fa.0 → 0.16.2-dev-8604b01.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/inter-protocol",
3
- "version": "0.16.2-dev-73364fa.0+73364fa",
3
+ "version": "0.16.2-dev-8604b01.0+8604b01",
4
4
  "description": "Core cryptoeconomy contracts",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -31,16 +31,16 @@
31
31
  },
32
32
  "homepage": "https://github.com/Agoric/agoric-sdk#readme",
33
33
  "dependencies": {
34
- "@agoric/assert": "0.6.1-dev-73364fa.0+73364fa",
35
- "@agoric/ertp": "0.16.3-dev-73364fa.0+73364fa",
36
- "@agoric/governance": "0.10.4-dev-73364fa.0+73364fa",
37
- "@agoric/internal": "0.3.3-dev-73364fa.0+73364fa",
38
- "@agoric/notifier": "0.6.3-dev-73364fa.0+73364fa",
39
- "@agoric/store": "0.9.3-dev-73364fa.0+73364fa",
40
- "@agoric/time": "0.3.3-dev-73364fa.0+73364fa",
41
- "@agoric/vat-data": "0.5.3-dev-73364fa.0+73364fa",
42
- "@agoric/vats": "0.15.2-dev-73364fa.0+73364fa",
43
- "@agoric/zoe": "0.26.3-dev-73364fa.0+73364fa",
34
+ "@agoric/assert": "0.6.1-dev-8604b01.0+8604b01",
35
+ "@agoric/ertp": "0.16.3-dev-8604b01.0+8604b01",
36
+ "@agoric/governance": "0.10.4-dev-8604b01.0+8604b01",
37
+ "@agoric/internal": "0.3.3-dev-8604b01.0+8604b01",
38
+ "@agoric/notifier": "0.6.3-dev-8604b01.0+8604b01",
39
+ "@agoric/store": "0.9.3-dev-8604b01.0+8604b01",
40
+ "@agoric/time": "0.3.3-dev-8604b01.0+8604b01",
41
+ "@agoric/vat-data": "0.5.3-dev-8604b01.0+8604b01",
42
+ "@agoric/vats": "0.15.2-dev-8604b01.0+8604b01",
43
+ "@agoric/zoe": "0.26.3-dev-8604b01.0+8604b01",
44
44
  "@endo/captp": "^4.0.1",
45
45
  "@endo/eventual-send": "^1.0.1",
46
46
  "@endo/far": "^1.0.1",
@@ -50,10 +50,10 @@
50
50
  "jessie.js": "^0.3.2"
51
51
  },
52
52
  "devDependencies": {
53
- "@agoric/smart-wallet": "0.5.4-dev-73364fa.0+73364fa",
54
- "@agoric/swingset-liveslots": "0.10.3-dev-73364fa.0+73364fa",
55
- "@agoric/swingset-vat": "0.32.3-dev-73364fa.0+73364fa",
56
- "@agoric/zone": "0.2.3-dev-73364fa.0+73364fa",
53
+ "@agoric/smart-wallet": "0.5.4-dev-8604b01.0+8604b01",
54
+ "@agoric/swingset-liveslots": "0.10.3-dev-8604b01.0+8604b01",
55
+ "@agoric/swingset-vat": "0.32.3-dev-8604b01.0+8604b01",
56
+ "@agoric/zone": "0.2.3-dev-8604b01.0+8604b01",
57
57
  "@endo/bundle-source": "^3.0.1",
58
58
  "@endo/init": "^1.0.1",
59
59
  "@endo/promise-kit": "^1.0.1",
@@ -85,5 +85,5 @@
85
85
  "typeCoverage": {
86
86
  "atLeast": 95.83
87
87
  },
88
- "gitHead": "73364fab9ba4d12a64c8b5e6f464d4be2dd09f56"
88
+ "gitHead": "8604b011b072d7bef43df59c075bcff9582b8804"
89
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auctionBook.d.ts","sourceRoot":"","sources":["auctionBook.js"],"names":[],"mappings":"AAyEO,6CAHI,MAAM,KAAK,CAAC,mBACZ,MAAM,KAAK,CAAC,oCAiBtB;AA0BM,4CAJI,OAAO,OACP,GAAG,mBACH,OAAO,6CAA6C,EAAE,eAAe;IAwWxE;;;;;;;;OAQG;2BAPQ,OAAO,KAAK,CAAC,cACb,OAAO;IA6ElB,yCAAyC;+BAAlB,KAAK,GAAK,IAAI;;;;;IAsGrC;;;;OAIG;wBAHQ,SAAS,QACT,OAAO,aACP,OAAO;;;;;;;;;;;GAsHzB;wBA9sBY;IACZ,MAAU,EAAE,OAAO,KAAK,CAAC,CAAC;CACvB,GAAG;IACN,YAAgB,CAAC,EAAE,OAAO,CAAC;CACxB,GAAG,CACE;IACR,UAAoB,EAAE,KAAK,CAAC;CACnB,GACD;IACR,eAAyB,EAAE,KAAK,CAAC;CACxB,CACJ;sBAuBQ,OAAO,kBAAkB,EAAE,OAAO;;;;;gBAIlC,KAAK,GAAG,IAAI;;;;;uBACZ,KAAK,GAAG,IAAI;;;;;uBAEZ,OAAO,KAAK,CAAC,GAAG,IAAI;;;;;2BAEpB,OAAO,KAAK,CAAC,GAAG,IAAI;;;;;oBAEpB,OAAO,KAAK,CAAC,GAAG,SAAS;;;;;qBAEzB,OAAO,KAAK,CAAC;;;;;yBAEb,OAAO,KAAK,CAAC,GAAG,IAAI;;0BAgqBpB,WAAW,WAAW,yBAAyB,CAAC,CAAC"}
1
+ {"version":3,"file":"auctionBook.d.ts","sourceRoot":"","sources":["auctionBook.js"],"names":[],"mappings":"AAyEO,6CAHI,MAAM,KAAK,CAAC,mBACZ,MAAM,KAAK,CAAC,oCAiBtB;AA0BM,4CAJI,OAAO,OACP,GAAG,mBACH,OAAO,6CAA6C,EAAE,eAAe;IA6YxE;;;;;;;;OAQG;2BAPQ,OAAO,KAAK,CAAC,cACb,OAAO;IA6ElB,yCAAyC;+BAAlB,KAAK,GAAK,IAAI;;;;;IA4GrC;;;;OAIG;wBAHQ,SAAS,QACT,OAAO,aACP,OAAO;;;;;;;;;;;GAyFzB;wBA5tBY;IACZ,MAAU,EAAE,OAAO,KAAK,CAAC,CAAC;CACvB,GAAG;IACN,YAAgB,CAAC,EAAE,OAAO,CAAC;CACxB,GAAG,CACE;IACR,UAAoB,EAAE,KAAK,CAAC;CACnB,GACD;IACR,eAAyB,EAAE,KAAK,CAAC;CACxB,CACJ;sBAuBQ,OAAO,kBAAkB,EAAE,OAAO;;;;;gBAIlC,KAAK,GAAG,IAAI;;;;;uBACZ,KAAK,GAAG,IAAI;;;;;uBAEZ,OAAO,KAAK,CAAC,GAAG,IAAI;;;;;2BAEpB,OAAO,KAAK,CAAC,GAAG,IAAI;;;;;oBAEpB,OAAO,KAAK,CAAC,GAAG,SAAS;;;;;qBAEzB,OAAO,KAAK,CAAC;;;;;yBAEb,OAAO,KAAK,CAAC,GAAG,IAAI;;0BA8qBpB,WAAW,WAAW,yBAAyB,CAAC,CAAC"}
@@ -2,7 +2,7 @@ import '@agoric/governance/exported.js';
2
2
  import '@agoric/zoe/exported.js';
3
3
  import '@agoric/zoe/src/contracts/exported.js';
4
4
 
5
- import { AmountMath } from '@agoric/ertp';
5
+ import { AmountMath, RatioShape } from '@agoric/ertp';
6
6
  import { mustMatch } from '@agoric/store';
7
7
  import { M, prepareExoClassKit } from '@agoric/vat-data';
8
8
 
@@ -124,7 +124,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
124
124
  bidHoldingSeat: M.any(),
125
125
  bidAmountShape: M.any(),
126
126
  priceAuthority: M.any(),
127
- updatingOracleQuote: M.any(),
127
+ updatingOracleQuote: M.or(RatioShape, M.null()),
128
128
  bookDataKit: M.any(),
129
129
  priceBook: M.any(),
130
130
  scaledBidBook: M.any(),
@@ -147,11 +147,6 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
147
147
  */
148
148
  (bidBrand, collateralBrand, pAuthority, node) => {
149
149
  assertAllDefined({ bidBrand, collateralBrand, pAuthority });
150
- const zeroBid = makeEmpty(bidBrand);
151
- const zeroRatio = makeRatioFromAmounts(
152
- zeroBid,
153
- AmountMath.make(collateralBrand, 1n),
154
- );
155
150
 
156
151
  // these don't have to be durable, since we're currently assuming that upgrade
157
152
  // from a quiescent state is sufficient. When the auction is quiescent, there
@@ -188,7 +183,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
188
183
  bidAmountShape,
189
184
 
190
185
  priceAuthority: pAuthority,
191
- updatingOracleQuote: zeroRatio,
186
+ updatingOracleQuote: /** @type {Ratio | null} */ (null),
192
187
 
193
188
  bookDataKit,
194
189
 
@@ -468,6 +463,48 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
468
463
  });
469
464
  return state.bookDataKit.recorder.write(bookData);
470
465
  },
466
+ observeQuoteNotifier() {
467
+ const { state, facets } = this;
468
+ const { collateralBrand, bidBrand, priceAuthority } = state;
469
+
470
+ trace('observing');
471
+
472
+ void E.when(
473
+ E(collateralBrand).getDisplayInfo(),
474
+ ({ decimalPlaces = DEFAULT_DECIMALS }) => {
475
+ const quoteNotifier = E(priceAuthority).makeQuoteNotifier(
476
+ AmountMath.make(collateralBrand, 10n ** BigInt(decimalPlaces)),
477
+ bidBrand,
478
+ );
479
+ void observeNotifier(quoteNotifier, {
480
+ updateState: quote => {
481
+ trace(
482
+ `BOOK notifier ${priceFrom(quote).numerator.value}/${
483
+ priceFrom(quote).denominator.value
484
+ }`,
485
+ );
486
+ state.updatingOracleQuote = priceFrom(quote);
487
+ },
488
+ fail: reason => {
489
+ trace(
490
+ `Failure from quoteNotifier (${reason}) setting to null`,
491
+ );
492
+ // lack of quote will trigger restart
493
+ state.updatingOracleQuote = null;
494
+ },
495
+ finish: done => {
496
+ trace(
497
+ `quoteNotifier invoked finish(${done}). setting quote to null`,
498
+ );
499
+ // lack of quote will trigger restart
500
+ state.updatingOracleQuote = null;
501
+ },
502
+ });
503
+ },
504
+ );
505
+
506
+ void facets.helper.publishBookData();
507
+ },
471
508
  },
472
509
  self: {
473
510
  /**
@@ -630,6 +667,12 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
630
667
  const { facets, state } = this;
631
668
 
632
669
  trace(`capturing oracle price `, state.updatingOracleQuote);
670
+ if (!state.updatingOracleQuote) {
671
+ // if the price has feed has died, try restarting it.
672
+ facets.helper.observeQuoteNotifier();
673
+ return;
674
+ }
675
+
633
676
  state.capturedPriceForRound = state.updatingOracleQuote;
634
677
  void facets.helper.publishBookData();
635
678
  },
@@ -729,37 +772,8 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
729
772
  finish: ({ state, facets }) => {
730
773
  const { collateralBrand, bidBrand, priceAuthority } = state;
731
774
  assertAllDefined({ collateralBrand, bidBrand, priceAuthority });
732
- void E.when(
733
- E(collateralBrand).getDisplayInfo(),
734
- ({ decimalPlaces = DEFAULT_DECIMALS }) => {
735
- // TODO(#6946) use this to keep a current price that can be published in state.
736
- const quoteNotifier = E(priceAuthority).makeQuoteNotifier(
737
- AmountMath.make(collateralBrand, 10n ** BigInt(decimalPlaces)),
738
- bidBrand,
739
- );
740
- void observeNotifier(quoteNotifier, {
741
- updateState: quote => {
742
- trace(
743
- `BOOK notifier ${priceFrom(quote).numerator.value}/${
744
- priceFrom(quote).denominator.value
745
- }`,
746
- );
747
- state.updatingOracleQuote = priceFrom(quote);
748
- },
749
- fail: reason => {
750
- throw Error(
751
- `auction observer of ${collateralBrand} failed: ${reason}`,
752
- );
753
- },
754
- finish: done => {
755
- throw Error(
756
- `auction observer for ${collateralBrand} died: ${done}`,
757
- );
758
- },
759
- });
760
- },
761
- );
762
- void facets.helper.publishBookData();
775
+
776
+ facets.helper.observeQuoteNotifier();
763
777
  },
764
778
  stateShape: AuctionBookStateShape,
765
779
  },
@@ -1,3 +1,4 @@
1
+ export function watchQuoteNotifier<T, A extends any[] = unknown[]>(notifierP: ERef<LatestTopic<T>>, watcher: import("@agoric/swingset-liveslots").PromiseWatcher<T, A>, ...args: A): Promise<void>;
1
2
  export function prepareVaultManagerKit(baggage: import('@agoric/ertp').Baggage, { zcf, marshaller, makeRecorderKit, factoryPowers }: {
2
3
  zcf: import('./vaultFactory.js').VaultFactoryZCF;
3
4
  marshaller: ERef<Marshaller>;
@@ -26,6 +27,7 @@ export function prepareVaultManagerKit(baggage: import('@agoric/ertp').Baggage,
26
27
  helper: {
27
28
  /** Start non-durable processes (or restart if needed after vat restart) */
28
29
  start(): void;
30
+ observeQuoteNotifier(): void;
29
31
  /** @param {Timestamp} updateTime */
30
32
  chargeAllVaults(updateTime: Timestamp): Promise<void>;
31
33
  assetNotify(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"vaultManager.d.ts","sourceRoot":"","sources":["vaultManager.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vaultManager.d.ts","sourceRoot":"","sources":["vaultManager.js"],"names":[],"mappings":"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"}
@@ -69,6 +69,38 @@ const { details: X, Fail, quote: q } = assert;
69
69
 
70
70
  const trace = makeTracer('VM');
71
71
 
72
+ /**
73
+ * Watch a notifier that isn't expected to fail or finish unless the vat hosting
74
+ * the notifier is upgraded. This watcher supports that by providing a
75
+ * straightforward way to get a replacement if the notifier breaks.
76
+ *
77
+ * @template T notifier topic
78
+ * @template {any[]} [A=unknown[]] arbitrary arguments
79
+ * @param {ERef<LatestTopic<T>>} notifierP
80
+ * @param {import('@agoric/swingset-liveslots').PromiseWatcher<T, A>} watcher
81
+ * @param {A} args
82
+ */
83
+ export const watchQuoteNotifier = async (notifierP, watcher, ...args) => {
84
+ await undefined;
85
+
86
+ let updateCount;
87
+ for (;;) {
88
+ let value;
89
+ try {
90
+ ({ value, updateCount } = await E(notifierP).getUpdateSince(updateCount));
91
+ watcher.onFulfilled && watcher.onFulfilled(value, ...args);
92
+ } catch (e) {
93
+ watcher.onRejected && watcher.onRejected(e, ...args);
94
+ break;
95
+ }
96
+ if (updateCount === undefined) {
97
+ watcher.onRejected &&
98
+ watcher.onRejected(Error('stream finished'), ...args);
99
+ break;
100
+ }
101
+ }
102
+ };
103
+
72
104
  /** @typedef {import('./storeUtils.js').NormalizedDebt} NormalizedDebt */
73
105
  /** @typedef {import('@agoric/time').RelativeTime} RelativeTime */
74
106
 
@@ -170,7 +202,7 @@ const trace = makeTracer('VM');
170
202
  * @type {(brand: Brand) => {
171
203
  * prioritizedVaults: ReturnType<typeof makePrioritizedVaults>;
172
204
  * storedQuotesNotifier: import('@agoric/notifier').StoredNotifier<PriceQuote>;
173
- * storedCollateralQuote: PriceQuote;
205
+ * storedCollateralQuote: PriceQuote | null;
174
206
  * }}
175
207
  */
176
208
  // any b/c will be filled after start()
@@ -355,13 +387,7 @@ export const prepareVaultManagerKit = (
355
387
  start() {
356
388
  const { state, facets } = this;
357
389
  trace(state.collateralBrand, 'helper.start()', state.vaultCounter);
358
- const {
359
- collateralBrand,
360
- collateralUnit,
361
- debtBrand,
362
- storageNode,
363
- unsettledVaults,
364
- } = state;
390
+ const { collateralBrand, unsettledVaults } = state;
365
391
 
366
392
  const ephemera = collateralEphemera(collateralBrand);
367
393
  ephemera.prioritizedVaults = makePrioritizedVaults(unsettledVaults);
@@ -394,7 +420,17 @@ export const prepareVaultManagerKit = (
394
420
  },
395
421
  });
396
422
 
397
- trace('helper.start() making quoteNotifier from', priceAuthority);
423
+ void facets.helper.observeQuoteNotifier();
424
+
425
+ trace('helper.start() done');
426
+ },
427
+ observeQuoteNotifier() {
428
+ const { state } = this;
429
+
430
+ const { collateralBrand, collateralUnit, debtBrand, storageNode } =
431
+ state;
432
+ const ephemera = collateralEphemera(collateralBrand);
433
+
398
434
  const quoteNotifier = E(priceAuthority).makeQuoteNotifier(
399
435
  collateralUnit,
400
436
  debtBrand,
@@ -404,20 +440,29 @@ export const prepareVaultManagerKit = (
404
440
  E(storageNode).makeChildNode('quotes'),
405
441
  marshaller,
406
442
  );
407
- trace('helper.start() awaiting observe storedQuotesNotifier');
443
+ trace(
444
+ 'helper.start() awaiting observe storedQuotesNotifier',
445
+ collateralBrand,
446
+ );
408
447
  // NB: upon restart, there may not be a price for a while. If manager
409
- // operations are permitted, ones the depend on price information will
410
- // throw. See https://github.com/Agoric/agoric-sdk/issues/4317
411
- void observeNotifier(quoteNotifier, {
412
- updateState(value) {
413
- trace('storing new quote', value.quoteAmount.value);
448
+ // operations are permitted, ones that depend on price information
449
+ // will throw. See https://github.com/Agoric/agoric-sdk/issues/4317
450
+ const quoteWatcher = harden({
451
+ onFulfilled(value) {
414
452
  ephemera.storedCollateralQuote = value;
415
453
  },
416
- fail(reason) {
417
- console.error('quoteNotifier failed to iterate', reason);
454
+ onRejected() {
455
+ // NOTE: drastic action, if the quoteNotifier fails, we don't know
456
+ // the value of the asset, nor do we know how long we'll be in
457
+ // ignorance. Best choice is to disable actions that require
458
+ // prices and restart when we have a new price. If we restart the
459
+ // notifier immediately, we'll trigger an infinite loop, so try
460
+ // to restart each time we get a request.
461
+
462
+ ephemera.storedCollateralQuote = null;
418
463
  },
419
464
  });
420
- trace('helper.start() done');
465
+ void watchQuoteNotifier(quoteNotifier, quoteWatcher);
421
466
  },
422
467
  /** @param {Timestamp} updateTime */
423
468
  async chargeAllVaults(updateTime) {
@@ -785,10 +830,15 @@ export const prepareVaultManagerKit = (
785
830
  * @param {Amount<'nat'>} collateralAmount
786
831
  */
787
832
  maxDebtFor(collateralAmount) {
788
- const { collateralBrand } = this.state;
833
+ const { state, facets } = this;
834
+ const { collateralBrand } = state;
789
835
  const { storedCollateralQuote } = collateralEphemera(collateralBrand);
790
- if (!storedCollateralQuote)
791
- throw Fail`maxDebtFor called before a collateral quote was available`;
836
+ if (!storedCollateralQuote) {
837
+ facets.helper.observeQuoteNotifier();
838
+
839
+ // it might take an arbitrary amount of time to get a new quote
840
+ throw Fail`maxDebtFor called before a collateral quote was available for ${collateralBrand}`;
841
+ }
792
842
  // use the lower price to prevent vault adjustments that put them imminently underwater
793
843
  const collateralPrice = minimumPrice(
794
844
  storedCollateralQuote,
@@ -1025,11 +1075,17 @@ export const prepareVaultManagerKit = (
1025
1075
  },
1026
1076
 
1027
1077
  getCollateralQuote() {
1078
+ const { state, facets } = this;
1028
1079
  const { storedCollateralQuote } = collateralEphemera(
1029
- this.state.collateralBrand,
1080
+ state.collateralBrand,
1030
1081
  );
1031
- if (!storedCollateralQuote)
1082
+ if (!storedCollateralQuote) {
1083
+ facets.helper.observeQuoteNotifier();
1084
+
1085
+ // it might take an arbitrary amount of time to get a new quote
1032
1086
  throw Fail`getCollateralQuote called before a collateral quote was available`;
1087
+ }
1088
+
1033
1089
  return storedCollateralQuote;
1034
1090
  },
1035
1091
 
@@ -1042,8 +1098,13 @@ export const prepareVaultManagerKit = (
1042
1098
  const { storedCollateralQuote } = collateralEphemera(
1043
1099
  state.collateralBrand,
1044
1100
  );
1045
- if (!storedCollateralQuote)
1101
+ if (!storedCollateralQuote) {
1102
+ facets.helper.observeQuoteNotifier();
1103
+
1104
+ // it might take an arbitrary amount of time to get a new quote
1046
1105
  throw Fail`lockOraclePrices called before a collateral quote was available for ${state.collateralBrand}`;
1106
+ }
1107
+
1047
1108
  trace(
1048
1109
  `lockOraclePrices`,
1049
1110
  getAmountIn(storedCollateralQuote),
@@ -1078,6 +1139,15 @@ export const prepareVaultManagerKit = (
1078
1139
  return;
1079
1140
  }
1080
1141
 
1142
+ const { storedCollateralQuote: collateralQuoteBefore } =
1143
+ collateralEphemera(this.state.collateralBrand);
1144
+ if (!collateralQuoteBefore) {
1145
+ console.error(
1146
+ 'Skipping liquidation because collateralQuote is missing',
1147
+ );
1148
+ return;
1149
+ }
1150
+
1081
1151
  const { prioritizedVaults } = collateralEphemera(collateralBrand);
1082
1152
  prioritizedVaults || Fail`prioritizedVaults missing from ephemera`;
1083
1153
 
@@ -1141,7 +1211,10 @@ export const prepareVaultManagerKit = (
1141
1211
  const { plan, vaultsInPlan } = helper.planProceedsDistribution(
1142
1212
  proceeds,
1143
1213
  totalDebt,
1144
- storedCollateralQuote,
1214
+ // If a quote was available at the start of liquidation, but is no
1215
+ // longer, using the earlier price is better than failing to
1216
+ // distribute proceeds
1217
+ storedCollateralQuote || collateralQuoteBefore,
1145
1218
  vaultData,
1146
1219
  totalCollateral,
1147
1220
  );