Skip to content

Commit a060b5f

Browse files
committed
feat(ertp): add purse.getCurrentAmountNotifier
1 parent c90fb61 commit a060b5f

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

packages/ERTP/NEWS.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
User-visible changes in ERTP:
22

3+
## Next Release
4+
5+
* Purses now support `getCurrentAmountNotifier()` that notifies of balance
6+
changes.
7+
38
## Release v0.7.0 (21-July-2020)
49

510
* Rename `extent` to `value`

packages/ERTP/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@agoric/import-manager": "^0.1.3",
4747
"@agoric/marshal": "^0.2.7",
4848
"@agoric/nat": "^2.0.1",
49+
"@agoric/notifier": "^0.2.3",
4950
"@agoric/promise-kit": "^0.1.7",
5051
"@agoric/same-structure": "^0.0.12",
5152
"@agoric/store": "^0.3.1"

packages/ERTP/src/issuer.js

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { assert, details } from '@agoric/assert';
66
import { makeExternalStore } from '@agoric/store';
77
import { E } from '@agoric/eventual-send';
88
import { Remotable } from '@agoric/marshal';
9+
import { makeNotifierKit } from '@agoric/notifier';
910
import { isPromise } from '@agoric/promise-kit';
1011

1112
import { makeAmountMath, MathKind } from './amountMath';
@@ -91,6 +92,11 @@ function makeIssuerKit(
9192

9293
const { makeInstance: makePurse } = makeExternalStore('purse', () => {
9394
let currentBalance = amountMath.getEmpty();
95+
/** @type {NotifierRecord<Amount>} */
96+
const {
97+
notifier: balanceNotifier,
98+
updater: balanceUpdater,
99+
} = makeNotifierKit(currentBalance);
94100

95101
/** @type {Purse} */
96102
const purse = Remotable(
@@ -116,6 +122,7 @@ function makeIssuerKit(
116122
// source payment, such that total assets are conserved.
117123
paymentLedger.delete(srcPayment);
118124
currentBalance = newPurseBalance;
125+
balanceUpdater.updateState(currentBalance);
119126
return srcPaymentBalance;
120127
},
121128
withdraw: amount => {
@@ -126,10 +133,12 @@ function makeIssuerKit(
126133
// Move the withdrawn assets from this purse into a new payment
127134
// which is returned. Total assets must remain conserved.
128135
currentBalance = newPurseBalance;
136+
balanceUpdater.updateState(currentBalance);
129137
paymentLedger.init(payment, amount);
130138
return payment;
131139
},
132140
getCurrentAmount: () => currentBalance,
141+
getCurrentAmountNotifier: () => balanceNotifier,
133142
getAllegedBrand: () => brand,
134143
// eslint-disable-next-line no-use-before-define
135144
getDepositFacet: () => depositFacet,

packages/ERTP/src/types.js

+3
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@
264264
* @property {() => Amount} getCurrentAmount
265265
* Get the amount contained in this purse.
266266
*
267+
* @property {() => Notifier<Amount>} getCurrentAmountNotifier
268+
* Get a lossy notifier for changes to this purse's balance.
269+
*
267270
* @property {(payment: Payment, optAmount: Amount=) => Amount} deposit
268271
* Deposit all the contents of payment into this purse, returning the
269272
* amount. If the optional argument `optAmount` does not equal the

packages/ERTP/test/unitTests/test-issuerObj.js

+49-7
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,32 @@ test('issuer.getAmountMathKind', t => {
7171
});
7272

7373
test('issuer.makeEmptyPurse', async t => {
74-
t.plan(6);
74+
t.plan(9);
7575
const { issuer, mint, amountMath, brand } = makeIssuerKit('fungible');
7676
const purse = issuer.makeEmptyPurse();
7777
const payment = mint.mintPayment(amountMath.make(837));
7878

79+
const notifier = purse.getCurrentAmountNotifier();
80+
let nextUpdate = notifier.getUpdateSince();
81+
82+
const checkNotifier = async () => {
83+
const { value: balance, updateCount } = await nextUpdate;
84+
t.assert(
85+
amountMath.isEqual(purse.getCurrentAmount(), balance),
86+
`the notifier balance is the same as the purse`,
87+
);
88+
nextUpdate = notifier.getUpdateSince(updateCount);
89+
};
90+
7991
t.assert(
8092
amountMath.isEqual(purse.getCurrentAmount(), amountMath.getEmpty()),
8193
`empty purse is empty`,
8294
);
95+
await checkNotifier();
8396
t.is(purse.getAllegedBrand(), brand, `purse's brand is correct`);
8497
const fungible837 = amountMath.make(837);
8598

86-
const checkDeposit = newPurseBalance => {
99+
const checkDeposit = async newPurseBalance => {
87100
t.assert(
88101
amountMath.isEqual(newPurseBalance, fungible837),
89102
`the balance returned is the purse balance`,
@@ -92,11 +105,12 @@ test('issuer.makeEmptyPurse', async t => {
92105
amountMath.isEqual(purse.getCurrentAmount(), fungible837),
93106
`the new purse balance is the payment's old balance`,
94107
);
108+
await checkNotifier();
95109
};
96110

97111
const performWithdrawal = () => purse.withdraw(fungible837);
98112

99-
const checkWithdrawal = newPayment => {
113+
const checkWithdrawal = async newPayment => {
100114
issuer.getAmountOf(newPayment).then(amount => {
101115
t.assert(
102116
amountMath.isEqual(amount, fungible837),
@@ -107,6 +121,7 @@ test('issuer.makeEmptyPurse', async t => {
107121
amountMath.isEqual(purse.getCurrentAmount(), amountMath.getEmpty()),
108122
`the purse is empty again`,
109123
);
124+
await checkNotifier();
110125
};
111126

112127
await E(purse)
@@ -117,21 +132,33 @@ test('issuer.makeEmptyPurse', async t => {
117132
});
118133

119134
test('purse.deposit', async t => {
120-
t.plan(4);
135+
t.plan(7);
121136
const { issuer, mint, amountMath } = makeIssuerKit('fungible');
122137
const fungible0 = amountMath.getEmpty();
123138
const fungible17 = amountMath.make(17);
124139
const fungible25 = amountMath.make(25);
125140
const fungibleSum = amountMath.add(fungible17, fungible25);
126141

127142
const purse = issuer.makeEmptyPurse();
143+
const notifier = purse.getCurrentAmountNotifier();
128144
const payment17 = mint.mintPayment(fungible17);
129145
const payment25 = mint.mintPayment(fungible25);
130146

147+
let nextUpdate = notifier.getUpdateSince();
148+
149+
const checkNotifier = async () => {
150+
const { value: balance, updateCount } = await nextUpdate;
151+
t.assert(
152+
amountMath.isEqual(purse.getCurrentAmount(), balance),
153+
`the notifier balance is the same as the purse`,
154+
);
155+
nextUpdate = notifier.getUpdateSince(updateCount);
156+
};
157+
131158
const checkDeposit = (
132159
expectedOldBalance,
133160
expectedNewBalance,
134-
) => depositResult => {
161+
) => async depositResult => {
135162
const delta = amountMath.subtract(expectedNewBalance, expectedOldBalance);
136163
t.assert(
137164
amountMath.isEqual(depositResult, delta),
@@ -141,8 +168,10 @@ test('purse.deposit', async t => {
141168
amountMath.isEqual(purse.getCurrentAmount(), expectedNewBalance),
142169
`the new purse balance ${depositResult.value} is the expected amount: ${expectedNewBalance.value}`,
143170
);
171+
await checkNotifier();
144172
};
145173

174+
await checkNotifier();
146175
await E(purse)
147176
.deposit(payment17, fungible17)
148177
.then(checkDeposit(fungible0, fungible17));
@@ -169,14 +198,25 @@ test('purse.deposit promise', async t => {
169198
});
170199

171200
test('purse.getDepositFacet', async t => {
172-
t.plan(2);
201+
t.plan(4);
173202
const { issuer, mint, amountMath } = makeIssuerKit('fungible');
174203
const fungible25 = amountMath.make(25);
175204

176205
const purse = issuer.makeEmptyPurse();
177206
const payment = mint.mintPayment(fungible25);
207+
const notifier = purse.getCurrentAmountNotifier();
208+
209+
let nextUpdate = notifier.getUpdateSince();
210+
const checkNotifier = async () => {
211+
const { value: balance, updateCount } = await nextUpdate;
212+
nextUpdate = notifier.getUpdateSince(updateCount);
213+
t.assert(
214+
amountMath.isEqual(purse.getCurrentAmount(), balance),
215+
`the notifier balance is the same as the purse's`,
216+
);
217+
};
178218

179-
const checkDeposit = newPurseBalance => {
219+
const checkDeposit = async newPurseBalance => {
180220
t.assert(
181221
amountMath.isEqual(newPurseBalance, fungible25),
182222
`the balance returned is the purse balance`,
@@ -185,8 +225,10 @@ test('purse.getDepositFacet', async t => {
185225
amountMath.isEqual(purse.getCurrentAmount(), fungible25),
186226
`the new purse balance is the payment's old balance`,
187227
);
228+
await checkNotifier();
188229
};
189230

231+
await checkNotifier();
190232
await E(purse)
191233
.getDepositFacet()
192234
.then(({ receive }) => receive(payment))

0 commit comments

Comments
 (0)