Skip to content

Commit

Permalink
feat: smartWallet verstion 2 with watchedPromises
Browse files Browse the repository at this point in the history
pulled offers.js and payments.js into smartWallet.js as they shared
plenty of state that needs to be durable in order to be callable from
the watchedPromise.

build an upgrade proposal; tested in
Agoric/agoric-3-proposals#34
  • Loading branch information
turadg authored and Chris-Hibbert committed Jan 4, 2024
1 parent 7f58a76 commit 73bed28
Show file tree
Hide file tree
Showing 17 changed files with 985 additions and 411 deletions.
115 changes: 115 additions & 0 deletions packages/boot/test/bootstrapTests/test-walletSurvivesZoeRestart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/** @file Bootstrap test of liquidation across multiple collaterals */
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import process from 'process';
import type { TestFn } from 'ava';

import { BridgeHandler } from '@agoric/vats';
import { Offers } from '@agoric/inter-protocol/src/clientSupport.js';
import {
LiquidationTestContext,
makeLiquidationTestContext,
LiquidationSetup,
} from '../../tools/liquidation.ts';

const test = anyTest as TestFn<LiquidationTestContext>;

const setup: LiquidationSetup = {
vaults: [
{
atom: 15,
ist: 100,
debt: 100.5,
},
],
bids: [
{
give: '80IST',
discount: 0.1,
},
],
price: {
starting: 12.34,
trigger: 9.99,
},
auction: {
start: {
collateral: 45,
debt: 309.54,
},
end: {
collateral: 9.659301,
debt: 0,
},
},
};

test.before(async t => {
t.context = await makeLiquidationTestContext(t);
});

test.after.always(t => {
return t.context.shutdown && t.context.shutdown();
});

test.serial('wallet survives zoe null upgrade', async t => {
// fail if there are any unhandled rejections
process.on('unhandledRejection', (error: Error) => {
t.fail(error.message);
});
const collateralBrandKey = 'ATOM';
const managerIndex = 0;

const { walletFactoryDriver, setupVaults, controller, buildProposal } =
t.context;

const { EV } = t.context.runUtils;

const buyer = await walletFactoryDriver.provideSmartWallet('agoric1buyer');

const buildAndExecuteProposal = async (packageSpec: string) => {
const proposal = await buildProposal(packageSpec);

for await (const bundle of proposal.bundles) {
await controller.validateAndInstallBundle(bundle);
}

const bridgeMessage = {
type: 'CORE_EVAL',
evals: proposal.evals,
};

const coreEvalBridgeHandler: ERef<BridgeHandler> = await EV.vat(
'bootstrap',
).consumeItem('coreEvalBridgeHandler');
await EV(coreEvalBridgeHandler).fromBridge(bridgeMessage);
};

await setupVaults(collateralBrandKey, managerIndex, setup);

// restart Zoe

// /////// Upgrading ////////////////////////////////
await buildAndExecuteProposal('@agoric/builders/scripts/vats/upgrade-zoe.js');

t.like(await buyer.getLatestUpdateRecord(), {
currentAmount: {
// brand from EV() doesn't compare correctly
// brand: invitationBrand,
value: [],
},
updated: 'balance',
});

await buyer.executeOfferMaker(Offers.vaults.OpenVault, {
offerId: 'open1',
collateralBrandKey: 'ATOM',
wantMinted: 5.0,
giveCollateral: 9.0,
});

t.like(buyer.getLatestUpdateRecord(), {
updated: 'offerStatus',
status: { id: 'open1', numWantsSatisfied: 1 },
});
});
4 changes: 3 additions & 1 deletion packages/inter-protocol/src/price/roundsManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,10 @@ export const prepareRoundsManagerKit = baggage =>
);
}

if (status.lastReportedRound >= roundId)
if (status.lastReportedRound >= roundId) {
return 'cannot report on previous rounds';
}

if (
roundId !== reportingRoundId &&
roundId !== add(reportingRoundId, 1) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ const acceptInvitation = async (wallet, priceAggregator) => {

let pushPriceCounter = 0;
/**
* @param {*} wallet
* @param {import('@agoric/smart-wallet/src/smartWallet.js').SmartWallet} wallet
* @param {string} adminOfferId
* @param {import('@agoric/inter-protocol/src/price/roundsManager.js').PriceRound} priceRound
* @returns {Promise<string>} offer id
Expand Down Expand Up @@ -322,6 +322,7 @@ test.serial('errors', async t => {
'In "pushPrice" method of (OracleKit oracle): arg 0: unitPrice: number 1 - Must be a bigint',
},
);

await eventLoopIteration();

// Success, round starts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,6 @@ test('want stable (insufficient funds)', async t => {
'Withdrawal of {"brand":"[Alleged: AUSD brand]","value":"[20000n]"} failed because the purse only contained {"brand":"[Alleged: AUSD brand]","value":"[10000n]"}';
const status = computedState.offerStatuses.get('insufficientFunds');
t.is(status?.error, `Error: ${msg}`);
/** @type {[PromiseRejectedResult]} */
// @ts-expect-error cast
const result = status.result;
t.is(result[0].status, 'rejected');
t.is(result[0].reason.message, msg);
});

test('govern offerFilter', async t => {
Expand Down Expand Up @@ -384,6 +379,8 @@ test('deposit multiple payments to unknown brand', async t => {
}
});

// related to recovering dropped Payments

// XXX belongs in smart-wallet package, but needs lots of set-up that's handy here.
test('recover when some withdrawals succeed and others fail', async t => {
const { fromEntries } = Object;
Expand Down
2 changes: 2 additions & 0 deletions packages/smart-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"devDependencies": {
"@agoric/cosmic-proto": "^0.3.0",
"@agoric/vats": "^0.15.2-u13.0",
"@endo/bundle-source": "2.5.2-upstream-rollup",
"@endo/captp": "3.1.1",
"@endo/init": "0.5.56",
Expand All @@ -26,6 +27,7 @@
"dependencies": {
"@agoric/assert": "^0.6.1-u11wf.0",
"@agoric/casting": "^0.4.3-u13.0",
"@agoric/deploy-script-support": "^0.10.4-u13.0",
"@agoric/ertp": "^0.16.3-u13.0",
"@agoric/internal": "^0.4.0-u13.0",
"@agoric/notifier": "^0.6.3-u13.0",
Expand Down
Loading

0 comments on commit 73bed28

Please sign in to comment.