Skip to content

Commit

Permalink
feat: handle VPURSE_BALANCE_UPDATE as return value from GIVE/GRAB
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed May 4, 2021
1 parent 116fcd2 commit 6e62c24
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 25 deletions.
2 changes: 1 addition & 1 deletion packages/vats/src/bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Far } from '@agoric/marshal';
* @property {(srcId: string, obj: any) => Promise<any>} fromBridge Handle an inbound message
*
* @typedef {Object} BridgeManager The object to manage this bridge
* @property {(dstID: string, obj: any) => void} toBridge
* @property {(dstID: string, obj: any) => any} toBridge
* @property {(srcID: string, handler: BridgeHandler) => void} register
* @property {(srcID: string, handler: BridgeHandler) => void} unregister
*/
Expand Down
77 changes: 53 additions & 24 deletions packages/vats/src/vat-bank.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ import '@agoric/notifier/exported';
* @typedef {ReturnType<typeof makeVirtualPurse>} VirtualPurse
*/

/**
* @callback BalanceUpdater
* @param {any} value
* @param {any} [nonce]
*/

/**
* @param {(obj: any) => Promise<any>} bankCall
* @param {string} denom
* @param {Brand} brand
* @param {string} address
* @param {Notifier<Amount>} balanceNotifier
* @param {(obj: any) => boolean} updateBalances
* @returns {VirtualPurseController}
*/
const makePurseController = (
Expand All @@ -29,8 +36,9 @@ const makePurseController = (
brand,
address,
balanceNotifier,
) =>
harden({
updateBalances,
) => {
return harden({
async *getBalances(b) {
assert.equal(b, brand);
let updateRecord = await balanceNotifier.getUpdateSince();
Expand All @@ -45,23 +53,26 @@ const makePurseController = (
},
async pushAmount(amt) {
const value = amountMath.getValue(brand, amt);
return bankCall({
const update = await bankCall({
type: 'VPURSE_GIVE',
recipient: address,
denom,
amount: `${value}`,
});
updateBalances(update);
},
async pullAmount(amt) {
const value = amountMath.getValue(brand, amt);
return bankCall({
const update = await bankCall({
type: 'VPURSE_GRAB',
sender: address,
denom,
amount: `${value}`,
});
updateBalances(update);
},
});
};

/**
* @typedef {Object} AssetIssuerKit
Expand Down Expand Up @@ -93,33 +104,40 @@ export function buildRootObject(_vatPowers) {
/** @type {WeakStore<Brand, AssetRecord>} */
const brandToAssetRecord = makeWeakStore('brand');

/** @type {Store<string, Store<string, (amount: any) => void>>} */
/** @type {Store<string, Store<string, BalanceUpdater>>} */
const denomToAddressUpdater = makeStore('denom');

const updateBalances = obj => {
switch (obj && obj.type) {
case 'VPURSE_BALANCE_UPDATE': {
for (const update of obj.updated) {
try {
const { address, denom, amount: value } = update;
const addressToUpdater = denomToAddressUpdater.get(denom);
const updater = addressToUpdater.get(address);

updater(value, obj.nonce);
console.error('Successful update', update);
} catch (e) {
console.error('Unregistered update', update);
}
}
return true;
}
default:
return false;
}
};

/**
* @param {import('./bridge').BridgeManager} bankBridgeMgr
*/
async function makeBankCaller(bankBridgeMgr) {
// We need to synchronise with the remote bank.
const handler = Far('bankHandler', {
async fromBridge(_srcID, obj) {
switch (obj.type) {
case 'VPURSE_BALANCE_UPDATE': {
for (const update of obj.updated) {
try {
const { address, denom, amount: value } = update;
const addressToUpdater = denomToAddressUpdater.get(denom);
const updater = addressToUpdater.get(address);

updater(value);
} catch (e) {
console.error('Unregistered update', update);
}
}
break;
}
default:
assert.fail(X`Unrecognized request ${obj.type}`);
if (!updateBalances(obj)) {
assert.fail(X`Unrecognized request ${obj && obj.type}`);
}
},
});
Expand Down Expand Up @@ -233,9 +251,19 @@ export function buildRootObject(_vatPowers) {
assetRecord.denom,
);

/** @typedef {NotifierRecord<Amount>} */
/** @type {NotifierRecord<Amount>} */
const { updater, notifier } = makeNotifierKit();
const balanceUpdater = value => {
/** @type {bigint} */
let lastBalanceUpdate = -1n;
/** @type {BalanceUpdater} */
const balanceUpdater = (value, nonce = undefined) => {
if (nonce !== undefined) {
const thisBalanceUpdate = BigInt(nonce);
if (thisBalanceUpdate <= lastBalanceUpdate) {
return;
}
lastBalanceUpdate = thisBalanceUpdate;
}
// Convert the string value to a bigint.
const amt = amountMath.make(brand, BigInt(value));
updater.updateState(amt);
Expand All @@ -257,6 +285,7 @@ export function buildRootObject(_vatPowers) {
brand,
address,
notifier,
updateBalances,
);
const vpurse = makeVirtualPurse(vpc, assetRecord);
brandToVPurse.init(brand, vpurse);
Expand Down

0 comments on commit 6e62c24

Please sign in to comment.