Skip to content

Commit

Permalink
Declare many of our remotables (#2178)
Browse files Browse the repository at this point in the history
* fix: Declare many of our remotables
  • Loading branch information
erights authored Jan 19, 2021
1 parent 39ea22c commit 648b297
Show file tree
Hide file tree
Showing 33 changed files with 308 additions and 227 deletions.
4 changes: 2 additions & 2 deletions packages/ERTP/src/amountMath.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-check

import { assert, details } from '@agoric/assert';

import { Far } from '@agoric/marshal';
import { mustBeComparable } from '@agoric/same-structure';

import './types';
Expand Down Expand Up @@ -94,7 +94,7 @@ function makeAmountMath(brand, amountMathKind) {
const cache = new WeakSet();

/** @type {AmountMath} */
const amountMath = harden({
const amountMath = Far('amountMath', {
getBrand: () => brand,
getAmountMathKind: () => amountMathKind,

Expand Down
3 changes: 3 additions & 0 deletions packages/ERTP/src/interfaces.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export const ERTPKind = {
DEPOSIT_FACET: 'depositFacet',
};

/** @type {MakeFarName} */
export const makeFarName = (allegedName, kind) => `${allegedName} ${kind}`;

/** @type {MakeInterface} */
export const makeInterface = (allegedName, kind) =>
`Alleged: ${allegedName} ${kind}`;
278 changes: 132 additions & 146 deletions packages/ERTP/src/issuer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import { assert, details } from '@agoric/assert';
import { makeExternalStore } from '@agoric/store';
import { E } from '@agoric/eventual-send';
import { Remotable } from '@agoric/marshal';
import { Far } from '@agoric/marshal';
import { makeNotifierKit } from '@agoric/notifier';
import { isPromise } from '@agoric/promise-kit';

import { makeAmountMath, MathKind } from './amountMath';
import { makeInterface, ERTPKind } from './interfaces';
import { makeFarName, ERTPKind } from './interfaces';
import { coerceDisplayInfo } from './displayInfo';

import './types';
Expand All @@ -26,22 +26,18 @@ function makeIssuerKit(
assert.typeof(allegedName, 'string');
displayInfo = coerceDisplayInfo(displayInfo);

const brand = Remotable(
makeInterface(allegedName, ERTPKind.BRAND),
undefined,
{
isMyIssuer: allegedIssuerP => {
return E.when(allegedIssuerP, allegedIssuer => {
// eslint-disable-next-line no-use-before-define
return allegedIssuer === issuer;
});
},
getAllegedName: () => allegedName,

// Give information to UI on how to display the amount.
getDisplayInfo: () => displayInfo,
const brand = Far(makeFarName(allegedName, ERTPKind.BRAND), {
isMyIssuer: allegedIssuerP => {
return E.when(allegedIssuerP, allegedIssuer => {
// eslint-disable-next-line no-use-before-define
return allegedIssuer === issuer;
});
},
);
getAllegedName: () => allegedName,

// Give information to UI on how to display the amount.
getDisplayInfo: () => displayInfo,
});

const amountMath = makeAmountMath(brand, amountMathKind);
const { add } = amountMath;
Expand All @@ -51,7 +47,7 @@ function makeIssuerKit(
makeInstance: makePayment,
makeWeakStore: makePaymentWeakStore,
} = makeExternalStore('payment', () =>
Remotable(makeInterface(allegedName, ERTPKind.PAYMENT), undefined, {
Far(makeFarName(allegedName, ERTPKind.PAYMENT), {
getAllegedBrand: () => brand,
}),
);
Expand Down Expand Up @@ -85,7 +81,7 @@ function makeIssuerKit(
* @returns {DepositFacet}
*/
purse =>
Remotable(makeInterface(allegedName, ERTPKind.DEPOSIT_FACET), undefined, {
Far(makeFarName(allegedName, ERTPKind.DEPOSIT_FACET), {
receive: purse.deposit,
}),
);
Expand All @@ -99,51 +95,47 @@ function makeIssuerKit(
} = makeNotifierKit(currentBalance);

/** @type {Purse} */
const purse = Remotable(
makeInterface(allegedName, ERTPKind.PURSE),
undefined,
{
deposit: (srcPayment, optAmount = undefined) => {
if (isPromise(srcPayment)) {
throw new TypeError(
`deposit does not accept promises as first argument. Instead of passing the promise (deposit(paymentPromise)), consider unwrapping the promise first: paymentPromise.then(actualPayment => deposit(actualPayment))`,
);
}
assertKnownPayment(srcPayment);
const srcPaymentBalance = paymentLedger.get(srcPayment);
// Note: this does not guarantee that optAmount itself is a valid stable amount
assertAmountEqual(srcPaymentBalance, optAmount);
const newPurseBalance = amountMath.add(
srcPaymentBalance,
currentBalance,
const purse = Far(makeFarName(allegedName, ERTPKind.PURSE), {
deposit: (srcPayment, optAmount = undefined) => {
if (isPromise(srcPayment)) {
throw new TypeError(
`deposit does not accept promises as first argument. Instead of passing the promise (deposit(paymentPromise)), consider unwrapping the promise first: paymentPromise.then(actualPayment => deposit(actualPayment))`,
);
// Commit point
// Move the assets in `srcPayment` into this purse, using up the
// source payment, such that total assets are conserved.
paymentLedger.delete(srcPayment);
currentBalance = newPurseBalance;
balanceUpdater.updateState(currentBalance);
return srcPaymentBalance;
},
withdraw: amount => {
amount = amountMath.coerce(amount);
const newPurseBalance = amountMath.subtract(currentBalance, amount);
const payment = makePayment();
// Commit point
// Move the withdrawn assets from this purse into a new payment
// which is returned. Total assets must remain conserved.
currentBalance = newPurseBalance;
balanceUpdater.updateState(currentBalance);
paymentLedger.init(payment, amount);
return payment;
},
getCurrentAmount: () => currentBalance,
getCurrentAmountNotifier: () => balanceNotifier,
getAllegedBrand: () => brand,
// eslint-disable-next-line no-use-before-define
getDepositFacet: () => depositFacet,
}
assertKnownPayment(srcPayment);
const srcPaymentBalance = paymentLedger.get(srcPayment);
// Note: this does not guarantee that optAmount itself is a valid stable amount
assertAmountEqual(srcPaymentBalance, optAmount);
const newPurseBalance = amountMath.add(
srcPaymentBalance,
currentBalance,
);
// Commit point
// Move the assets in `srcPayment` into this purse, using up the
// source payment, such that total assets are conserved.
paymentLedger.delete(srcPayment);
currentBalance = newPurseBalance;
balanceUpdater.updateState(currentBalance);
return srcPaymentBalance;
},
);
withdraw: amount => {
amount = amountMath.coerce(amount);
const newPurseBalance = amountMath.subtract(currentBalance, amount);
const payment = makePayment();
// Commit point
// Move the withdrawn assets from this purse into a new payment
// which is returned. Total assets must remain conserved.
currentBalance = newPurseBalance;
balanceUpdater.updateState(currentBalance);
paymentLedger.init(payment, amount);
return payment;
},
getCurrentAmount: () => currentBalance,
getCurrentAmountNotifier: () => balanceNotifier,
getAllegedBrand: () => brand,
// eslint-disable-next-line no-use-before-define
getDepositFacet: () => depositFacet,
});

const depositFacet = makeDepositFacet(purse);
return purse;
Expand Down Expand Up @@ -201,95 +193,89 @@ function makeIssuerKit(
};

/** @type {Issuer} */
const issuer = Remotable(
makeInterface(allegedName, ERTPKind.ISSUER),
undefined,
{
getBrand: () => brand,
getAllegedName: () => allegedName,
getAmountMathKind: () => amountMathKind,
makeEmptyPurse: makePurse,
const issuer = Far(makeFarName(allegedName, ERTPKind.ISSUER), {
getBrand: () => brand,
getAllegedName: () => allegedName,
getAmountMathKind: () => amountMathKind,
makeEmptyPurse: makePurse,

isLive: paymentP => {
return E.when(paymentP, payment => {
return paymentLedger.has(payment);
});
},
getAmountOf: paymentP => {
return E.when(paymentP, payment => {
assertKnownPayment(payment);
return paymentLedger.get(payment);
});
},
isLive: paymentP => {
return E.when(paymentP, payment => {
return paymentLedger.has(payment);
});
},
getAmountOf: paymentP => {
return E.when(paymentP, payment => {
assertKnownPayment(payment);
return paymentLedger.get(payment);
});
},

burn: (paymentP, optAmount = undefined) => {
return E.when(paymentP, payment => {
assertKnownPayment(payment);
const paymentBalance = paymentLedger.get(payment);
assertAmountEqual(paymentBalance, optAmount);
// Commit point.
paymentLedger.delete(payment);
return paymentBalance;
});
},
claim: (paymentP, optAmount = undefined) => {
return E.when(paymentP, srcPayment => {
assertKnownPayment(srcPayment);
const srcPaymentBalance = paymentLedger.get(srcPayment);
assertAmountEqual(srcPaymentBalance, optAmount);
// Commit point.
const [payment] = reallocate([srcPayment], [srcPaymentBalance]);
return payment;
});
},
// Payments in `fromPaymentsPArray` must be distinct. Alias
// checking is delegated to the `reallocate` function.
combine: (fromPaymentsPArray, optTotalAmount = undefined) => {
return Promise.all(fromPaymentsPArray).then(fromPaymentsArray => {
fromPaymentsArray.every(assertKnownPayment);
const totalPaymentsBalance = fromPaymentsArray
.map(paymentLedger.get)
.reduce(add, empty);
assertAmountEqual(totalPaymentsBalance, optTotalAmount);
// Commit point.
const [payment] = reallocate(fromPaymentsArray, [
totalPaymentsBalance,
]);
return payment;
});
},
// payment to two payments, A and B
split: (paymentP, paymentAmountA) => {
return E.when(paymentP, srcPayment => {
paymentAmountA = amountMath.coerce(paymentAmountA);
assertKnownPayment(srcPayment);
const srcPaymentBalance = paymentLedger.get(srcPayment);
const paymentAmountB = amountMath.subtract(
srcPaymentBalance,
paymentAmountA,
);
// Commit point
const newPayments = reallocate(
[srcPayment],
[paymentAmountA, paymentAmountB],
);
return newPayments;
});
},
splitMany: (paymentP, amounts) => {
return E.when(paymentP, srcPayment => {
assertKnownPayment(srcPayment);
amounts = amounts.map(amountMath.coerce);
// Commit point
const newPayments = reallocate([srcPayment], amounts);
return newPayments;
});
},
burn: (paymentP, optAmount = undefined) => {
return E.when(paymentP, payment => {
assertKnownPayment(payment);
const paymentBalance = paymentLedger.get(payment);
assertAmountEqual(paymentBalance, optAmount);
// Commit point.
paymentLedger.delete(payment);
return paymentBalance;
});
},
);
claim: (paymentP, optAmount = undefined) => {
return E.when(paymentP, srcPayment => {
assertKnownPayment(srcPayment);
const srcPaymentBalance = paymentLedger.get(srcPayment);
assertAmountEqual(srcPaymentBalance, optAmount);
// Commit point.
const [payment] = reallocate([srcPayment], [srcPaymentBalance]);
return payment;
});
},
// Payments in `fromPaymentsPArray` must be distinct. Alias
// checking is delegated to the `reallocate` function.
combine: (fromPaymentsPArray, optTotalAmount = undefined) => {
return Promise.all(fromPaymentsPArray).then(fromPaymentsArray => {
fromPaymentsArray.every(assertKnownPayment);
const totalPaymentsBalance = fromPaymentsArray
.map(paymentLedger.get)
.reduce(add, empty);
assertAmountEqual(totalPaymentsBalance, optTotalAmount);
// Commit point.
const [payment] = reallocate(fromPaymentsArray, [totalPaymentsBalance]);
return payment;
});
},
// payment to two payments, A and B
split: (paymentP, paymentAmountA) => {
return E.when(paymentP, srcPayment => {
paymentAmountA = amountMath.coerce(paymentAmountA);
assertKnownPayment(srcPayment);
const srcPaymentBalance = paymentLedger.get(srcPayment);
const paymentAmountB = amountMath.subtract(
srcPaymentBalance,
paymentAmountA,
);
// Commit point
const newPayments = reallocate(
[srcPayment],
[paymentAmountA, paymentAmountB],
);
return newPayments;
});
},
splitMany: (paymentP, amounts) => {
return E.when(paymentP, srcPayment => {
assertKnownPayment(srcPayment);
amounts = amounts.map(amountMath.coerce);
// Commit point
const newPayments = reallocate([srcPayment], amounts);
return newPayments;
});
},
});

/** @type {Mint} */
const mint = Remotable(makeInterface(allegedName, ERTPKind.MINT), undefined, {
const mint = Far(makeFarName(allegedName, ERTPKind.MINT), {
getIssuer: () => issuer,
mintPayment: newAmount => {
newAmount = amountMath.coerce(newAmount);
Expand Down
14 changes: 14 additions & 0 deletions packages/ERTP/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,17 @@
* @param {string} kind The ERTPKind
* @returns {InterfaceSpec}
*/

/**
* @callback MakeFarName
* Make the farName using the allegedName and kind. The particular
* structure may change in the future to be more sophisticated.
* Therefore, ERTP and Zoe should not depend on this particular
* implementation. `makeFar` converts its farName argument into
* the iface argument it passes to `Remotable`.
*
* @param {string} allegedName The allegedName, as passed to
* `makeIssuerKit`
* @param {string} kind The ERTPKind
* @returns {string}
*/
4 changes: 2 additions & 2 deletions packages/SwingSet/src/kernel/initializeKernel.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-use-before-define */

import { makeMarshal } from '@agoric/marshal';
import { makeMarshal, Far } from '@agoric/marshal';
import { assert } from '@agoric/assert';
import { assertKnownOptions } from '../assertOptions';
import { insistVatID } from './id';
Expand Down Expand Up @@ -133,7 +133,7 @@ export function initializeKernel(config, hostStorage, verbose = false) {
// non-empty object as vatObj0s, since an empty object would be
// serialized as pass-by-presence. It wouldn't make much sense for the
// bootstrap object to call itself, though.
const vref = harden({
const vref = Far('vref', {
toString() {
return name;
},
Expand Down
Loading

0 comments on commit 648b297

Please sign in to comment.