Skip to content

Commit

Permalink
chore: clean up persistence
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris-Hibbert committed Jul 5, 2023
1 parent ed21579 commit 223451a
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 105 deletions.
1 change: 1 addition & 0 deletions packages/inter-protocol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@endo/far": "^0.2.18",
"@endo/marshal": "^0.8.5",
"@endo/nat": "^4.1.27",
"@endo/promise-kit": "^0.2.56",
"jessie.js": "^0.3.2"
},
"devDependencies": {
Expand Down
32 changes: 14 additions & 18 deletions packages/inter-protocol/src/auction/auctionBook.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import '@agoric/zoe/exported.js';
import '@agoric/zoe/src/contracts/exported.js';

import { AmountMath } from '@agoric/ertp';
import { mustMatch, makeScalarMapStore } from '@agoric/store';
import { M, prepareExoClassKit, provide } from '@agoric/vat-data';
import { mustMatch } from '@agoric/store';
import {
M,
prepareExoClassKit,
provideDurableMapStore,
} from '@agoric/vat-data';

import { assertAllDefined, makeTracer } from '@agoric/internal';
import {
Expand All @@ -18,7 +22,6 @@ import {
} from '@agoric/zoe/src/contractSupport/index.js';
import { E } from '@endo/captp';
import { observeNotifier } from '@agoric/notifier';
import { ToFarFunction } from '@endo/marshal';

import { makeNatAmountShape } from '../contractSupport.js';
import { preparePriceBook, prepareScaledBidBook } from './offerBook.js';
Expand Down Expand Up @@ -69,8 +72,8 @@ const trace = makeTracer('AucBook', true);
* @param {Brand<'nat'>} collateralBrand
*/
export const makeOfferSpecShape = (bidBrand, collateralBrand) => {
const bidAmountShape = makeNatAmountShape(bidBrand);
const collateralAmountShape = makeNatAmountShape(collateralBrand);
const bidAmountShape = makeNatAmountShape(bidBrand, 0n);
const collateralAmountShape = makeNatAmountShape(collateralBrand, 0n);
return M.splitRecord(
{ maxBuy: collateralAmountShape },
{
Expand Down Expand Up @@ -131,9 +134,7 @@ export const makeOfferSpecShape = (bidBrand, collateralBrand) => {
* @param {import('@agoric/zoe/src/contractSupport/recorder.js').MakeRecorderKit} makeRecorderKit
*/
export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
const bidDataKits = provide(baggage, 'bidDataKits', () =>
makeScalarMapStore('BidDataKits'),
);
const bidDataKits = provideDurableMapStore(baggage, 'bidDataKits');
const makeScaledBidBook = prepareScaledBidBook(baggage, makeRecorderKit);
const makePriceBook = preparePriceBook(baggage, makeRecorderKit);

Expand Down Expand Up @@ -166,7 +167,7 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
* @param {Brand<'nat'>} bidBrand
* @param {Brand<'nat'>} collateralBrand
* @param {PriceAuthority} pAuthority
* @param {Array<ERef<StorageNode>>} nodes
* @param {Array<StorageNode>} nodes
*/
(bidBrand, collateralBrand, pAuthority, nodes) => {
assertAllDefined({ bidBrand, collateralBrand, pAuthority });
Expand All @@ -184,33 +185,28 @@ export const prepareAuctionBook = (baggage, zcf, makeRecorderKit) => {
const { zcfSeat: bidHoldingSeat } = zcf.makeEmptySeatKit();
const [scheduleNode, bidsNode] = nodes;

const bidAmountShape = makeNatAmountShape(bidBrand);
const collateralAmountShape = makeNatAmountShape(collateralBrand);
const makeBidNode = ToFarFunction('makeBidNode', bidId =>
E(bidsNode).makeChildNode(`bids${bidId}`),
);
const bidAmountShape = makeNatAmountShape(bidBrand, 0n);
const collateralAmountShape = makeNatAmountShape(collateralBrand, 0n);

const scaledBidBook = makeScaledBidBook(
makeBrandedRatioPattern(bidAmountShape, bidAmountShape),
collateralBrand,
makeBidNode,
bidsNode,
);

const priceBook = makePriceBook(
makeBrandedRatioPattern(bidAmountShape, collateralAmountShape),
collateralBrand,
makeBidNode,
bidsNode,
);

const bookDataKit = makeRecorderKit(
// @ts-expect-error ERef<ScheduleNodes> should be acceptable
scheduleNode,
/** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher<BookDataNotification>} */ (
M.any()
),
);
const bidsDataKit = makeRecorderKit(
// @ts-expect-error ERef<ScheduleNodes> should be acceptable
bidsNode,
/** @type {import('@agoric/zoe/src/contractSupport/recorder.js').TypedMatcher<BidDataNotification>} */ (
M.any()
Expand Down
9 changes: 6 additions & 3 deletions packages/inter-protocol/src/auction/auctioneer.js
Original file line number Diff line number Diff line change
Expand Up @@ -691,9 +691,12 @@ export const start = async (zcf, privateArgs, baggage) => {
const bookId = `book${bookCounter}`;
bookCounter += 1;

const bookNode = E(privateArgs.storageNode).makeChildNode(bookId);
const scheduleNode = E(bookNode).makeChildNode('schedule');
const bidsNode = E(bookNode).makeChildNode('bids');
const bookNodeP = E(privateArgs.storageNode).makeChildNode(bookId);
const [scheduleNode, bidsNode] = await Promise.all([
bookNodeP,
E(bookNodeP).makeChildNode('schedule'),
E(bookNodeP).makeChildNode('bids'),
]);

const newBook = await makeAuctionBook(
brands.Bid,
Expand Down
128 changes: 84 additions & 44 deletions packages/inter-protocol/src/auction/offerBook.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
// book of offers to buy liquidating vaults with prices in terms of
// discount/markup from the current oracle price.

import { AmountMath } from '@agoric/ertp';
import { E } from '@endo/captp';
import { AmountMath, BrandShape } from '@agoric/ertp';
import { StorageNodeShape } from '@agoric/internal';
import { M, mustMatch } from '@agoric/store';
import {
makeScalarBigMapStore,
makeScalarMapStore,
prepareExoClass,
provide,
} from '@agoric/vat-data';
import { makePromiseKit } from '@endo/promise-kit';

import {
toBidScalingComparator,
Expand Down Expand Up @@ -39,11 +43,25 @@ const nextSequenceNumber = baggage => {

const ScaledBidBookStateShape = harden({
bidScalingPattern: M.any(),
collateralBrand: M.any(),
collateralBrand: BrandShape,
records: M.any(),
makeBidNode: M.any(),
bidsNode: StorageNodeShape,
});

const makeBidNode = (bidsNode, bidId) =>
E(bidsNode).makeChildNode(`bid${bidId}`);

const makeGetBidDataRecorder = (bidDataKits, bidDataKitPromises) => {
return key => {
if (bidDataKitPromises.has(key)) {
return E.get(bidDataKitPromises.get(key)).recorder;
}
return bidDataKits.get(key).recorder;
};
};

/** @typedef {ReturnType<import('@agoric/zoe/src/contractSupport/recorder.js').MakeRecorderKit>} RecorderKit */

/**
* Prices in this book are expressed as percentage of the full oracle price
* snapshot taken when the auction started. .4 is 60% off. 1.1 is 10% above par.
Expand All @@ -57,23 +75,28 @@ export const prepareScaledBidBook = (baggage, makeRecorderKit) => {
// each offer for uniqueness.

const bidDataKits = baggage.get('bidDataKits');
/** @type {MapStore<string, Promise<RecorderKit>>} */
const bidDataKitPromises = makeScalarMapStore('bidDataKit Promises');
const getBidDataRecorder = makeGetBidDataRecorder(
bidDataKits,
bidDataKitPromises,
);

return prepareExoClass(
baggage,
'scaledBidBook',
undefined,
/**
*
* @param {Pattern} bidScalingPattern
* @param {Brand} collateralBrand
* @param {(BigInteger) => Promise<StorageNode>} makeBidNode
* @param {StorageNode} bidsNode
*/
(bidScalingPattern, collateralBrand, makeBidNode) => ({
(bidScalingPattern, collateralBrand, bidsNode) => ({
bidScalingPattern,
collateralBrand,
/** @type {MapStore<string, BidderRecord>} */
records: makeScalarBigMapStore('scaledBidRecords', { durable: true }),
makeBidNode,
bidsNode,
}),
{
/**
Expand All @@ -84,31 +107,36 @@ export const prepareScaledBidBook = (baggage, makeRecorderKit) => {
* @param {Timestamp} timestamp
*/
add(seat, bidScaling, wanted, exitAfterBuy, timestamp) {
const { bidScalingPattern, collateralBrand, records, makeBidNode } =
const { bidScalingPattern, collateralBrand, records, bidsNode } =
this.state;
mustMatch(bidScaling, bidScalingPattern);

const seqNum = nextSequenceNumber(baggage);
const key = toScaledRateOfferKey(bidScaling, seqNum);

// @ts-expect-error makeRecorderKit accepts ERef<Node>
const bidDataKit = makeRecorderKit(makeBidNode(seqNum), M.any());
bidDataKits.init(key, bidDataKit);
/** @type {PromiseKit<RecorderKit>} */
const bidDataKitP = makePromiseKit();
bidDataKitPromises.init(key, bidDataKitP.promise);
E.when(makeBidNode(bidsNode, seqNum), childBidNode => {
const recorderKit = makeRecorderKit(childBidNode);
bidDataKits.init(key, recorderKit);
bidDataKitP.resolve(recorderKit);
bidDataKitPromises.delete(key);
return recorderKit;
});

const empty = AmountMath.makeEmpty(collateralBrand);
/** @type {BidderRecord} */
const bidderRecord = {
bidScaling,
price: undefined,
received: empty,
received: AmountMath.makeEmpty(collateralBrand),
seat,
seqNum,
wanted,
exitAfterBuy,
timestamp,
};
records.init(key, harden(bidderRecord));
bidDataKits.init(seqNum);
return key;
},
/** @param {Ratio} bidScaling */
Expand All @@ -119,7 +147,7 @@ export const prepareScaledBidBook = (baggage, makeRecorderKit) => {
publishOffer(record) {
const key = toScaledRateOfferKey(record.bidScaling, record.seqNum);

bidDataKits.get(key).recorder.write(
return E(getBidDataRecorder(key)).write(
harden({
bidScaling: record.bidScaling,
wanted: record.wanted,
Expand Down Expand Up @@ -161,7 +189,9 @@ export const prepareScaledBidBook = (baggage, makeRecorderKit) => {
for (const [key, { seat }] of records.entries()) {
if (!seat.hasExited()) {
seat.exit();
bidDataKits.delete(key);
if (bidDataKits.has(key)) {
bidDataKits.delete(key);
}
records.delete(key);
}
}
Expand All @@ -175,9 +205,9 @@ export const prepareScaledBidBook = (baggage, makeRecorderKit) => {

const PriceBookStateShape = harden({
priceRatioPattern: M.any(),
collateralBrand: M.any(),
collateralBrand: BrandShape,
records: M.any(),
makeBidNode: M.any(),
bidsNode: StorageNodeShape,
});

/**
Expand All @@ -189,23 +219,28 @@ const PriceBookStateShape = harden({
*/
export const preparePriceBook = (baggage, makeRecorderKit) => {
const bidDataKits = baggage.get('bidDataKits');
/** @type {MapStore<string, Promise<RecorderKit>>} */
const bidDataKitPromises = makeScalarMapStore('bidDataKit Promises');
const getBidDataRecorder = makeGetBidDataRecorder(
bidDataKits,
bidDataKitPromises,
);

return prepareExoClass(
baggage,
'priceBook',
undefined,
/**
*
* @param {Pattern} priceRatioPattern
* @param {Brand} collateralBrand
* @param {(BigInteger) => Promise<StorageNode>} makeBidNode
* @param {StorageNode} bidsNode
*/
(priceRatioPattern, collateralBrand, makeBidNode) => ({
(priceRatioPattern, collateralBrand, bidsNode) => ({
priceRatioPattern,
collateralBrand,
/** @type {MapStore<string, BidderRecord>} */
records: makeScalarBigMapStore('scaledBidRecords', { durable: true }),
makeBidNode,
bidsNode,
}),
{
/**
Expand All @@ -216,33 +251,36 @@ export const preparePriceBook = (baggage, makeRecorderKit) => {
* @param {Timestamp} timestamp
*/
add(seat, price, wanted, exitAfterBuy, timestamp) {
const { priceRatioPattern, collateralBrand, records, makeBidNode } =
const { priceRatioPattern, collateralBrand, records, bidsNode } =
this.state;
mustMatch(price, priceRatioPattern);

const seqNum = nextSequenceNumber(baggage);
const key = toPriceOfferKey(price, seqNum);

// @ts-expect-error makeRecorderKit accepts ERef<Node>
const bidDataKit = makeRecorderKit(makeBidNode(seqNum), M.any());
bidDataKits.init(key, bidDataKit);

const empty = AmountMath.makeEmpty(collateralBrand);
records.init(
key,
harden({
bidScaling: undefined,
price,
received: empty,
seat,
seqNum,
wanted,
exitAfterBuy,
timestamp,
}),
);
/** @type {PromiseKit<RecorderKit>} */
const bidDataKitP = makePromiseKit();
bidDataKitPromises.init(key, bidDataKitP.promise);
E.when(makeBidNode(bidsNode, seqNum), childBidNode => {
const recorderKit = makeRecorderKit(childBidNode);
bidDataKits.init(key, recorderKit);
bidDataKitP.resolve(recorderKit);
bidDataKitPromises.delete(key);
return recorderKit;
});

bidDataKits.init(seqNum);
/** @type {BidderRecord} */
const bidderRecord = harden({
bidScaling: undefined,
price,
received: AmountMath.makeEmpty(collateralBrand),
seat,
seqNum,
wanted,
exitAfterBuy,
timestamp,
});
records.init(key, bidderRecord);
return key;
},
offersAbove(price) {
Expand All @@ -252,7 +290,7 @@ export const preparePriceBook = (baggage, makeRecorderKit) => {
publishOffer(record) {
const key = toPriceOfferKey(record.price, record.seqNum);

bidDataKits.get(key).recorder.write(
return E(getBidDataRecorder(key)).write(
harden({
price: record.price,
wanted: record.wanted,
Expand Down Expand Up @@ -293,7 +331,9 @@ export const preparePriceBook = (baggage, makeRecorderKit) => {
for (const [key, { seat }] of records.entries()) {
if (!seat.hasExited()) {
seat.exit();
bidDataKits.delete(key);
if (bidDataKits.has(key)) {
bidDataKits.delete(key);
}
records.delete(key);
}
}
Expand Down
Loading

0 comments on commit 223451a

Please sign in to comment.