Skip to content

Commit

Permalink
9207 fake bank (#9402)
Browse files Browse the repository at this point in the history
refs: #9207

## Description

Working balances through `makeFakeBankBridge`.

### Security Considerations

none, test code

### Scaling Considerations

none, test code


### Documentation Considerations

Contract devs may want to use these utilities eventually. I think
they're too early to document yet.

### Testing Considerations
per se

### Upgrade Considerations

none, test code
  • Loading branch information
mergify[bot] authored May 24, 2024
2 parents 4202f3e + ce7886e commit 60cffcf
Show file tree
Hide file tree
Showing 24 changed files with 392 additions and 173 deletions.
2 changes: 1 addition & 1 deletion packages/inter-protocol/src/proposals/addAssetToVault.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export const publishInterchainAssetFromBank = async (
});

const brand = await E(issuer).getBrand();
const kit = { mint, issuer, brand };
const kit = /** @type {IssuerKit<'nat'>} */ ({ mint, issuer, brand });

await E(E.get(reserveKit).creatorFacet).addIssuer(issuer, keyword);

Expand Down
2 changes: 0 additions & 2 deletions packages/inter-protocol/src/provisionPoolKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,6 @@ export const prepareProvisionPoolKit = (
* @param {ERef<StorageNode>} opts.storageNode
*/
const makeProvisionPoolKit = async ({ poolBrand, storageNode }) => {
/** @type {Purse<'nat'>} */
// @ts-expect-error vbank purse is close enough for our use.
const fundPurse = await E(poolBank).getPurse(poolBrand);
const metricsNode = await E(storageNode).makeChildNode('metrics');

Expand Down
16 changes: 6 additions & 10 deletions packages/inter-protocol/test/provisionPool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@ import { CONTRACT_ELECTORATE, ParamTypes } from '@agoric/governance';
import committeeBundle from '@agoric/governance/bundles/bundle-committee.js';
import { WalletName } from '@agoric/internal';
import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';
import { publishDepositFacet } from '@agoric/smart-wallet/src/walletFactory.js';
import { unsafeMakeBundleCache } from '@agoric/swingset-vat/tools/bundleTool.js';
import { makeScalarBigMapStore } from '@agoric/vat-data';
import centralSupplyBundle from '@agoric/vats/bundles/bundle-centralSupply.js';
import { makeNameHubKit } from '@agoric/vats/src/nameHub.js';
import { buildRootObject as buildBankRoot } from '@agoric/vats/src/vat-bank.js';
import { PowerFlags } from '@agoric/vats/src/walletFlags.js';
import { makeFakeBankKit } from '@agoric/vats/tools/bank-utils.js';
import {
makeFakeBankKit,
makeFakeBankManagerKit,
} from '@agoric/vats/tools/bank-utils.js';
import { makeFakeBoard } from '@agoric/vats/tools/board-utils.js';
import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import { E, Far } from '@endo/far';
import path from 'path';
import { publishDepositFacet } from '@agoric/smart-wallet/src/walletFactory.js';
import { makeBridgeProvisionTool } from '../src/provisionPoolKit.js';
import {
makeMockChainStorageRoot,
Expand Down Expand Up @@ -275,12 +276,7 @@ test('provisionPool trades provided assets for IST', async t => {
* @param {string[]} addresses
*/
const makeWalletFactoryKitForAddresses = async addresses => {
const baggage = makeScalarBigMapStore('bank baggage');
const bankManager = await buildBankRoot(
undefined,
undefined,
baggage,
).makeBankManager();
const { bankManager } = await makeFakeBankManagerKit();

const feeKit = makeIssuerKit('FEE');
const fees = withAmountUtils(feeKit);
Expand Down
1 change: 0 additions & 1 deletion packages/orchestration/src/facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const makeLocalChainFacade = localchain => {
return {
deposit(payment) {
console.log('deposit got', payment);
// XXX yet again tripped up on remote methods looking local statically
return E(account).deposit(payment);
},
transferSteps(amount, msg) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ test('stakeBld contract - makeAccount, deposit, withdraw', async t => {

t.log('withdraw 1 bld from account');
const withdrawResp = await E(account).withdraw(oneHundredStakeAmt);
// @ts-expect-error Argument of type 'Payment' is not assignable to parameter of type 'ERef<Payment<"nat", Key>>'.
const withdrawAmt = await stake.issuer.getAmountOf(withdrawResp);
t.true(AmountMath.isEqual(withdrawAmt, oneHundredStakeAmt), 'withdraw');

Expand Down
23 changes: 16 additions & 7 deletions packages/orchestration/test/examples/swapExample.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import path from 'path';
import { makeFakeStorageKit } from '@agoric/internal/src/storage-test-utils.js';
import { makeHeapZone } from '@agoric/zone';
import { prepareLocalChainTools } from '@agoric/vats/src/localchain.js';
import { buildRootObject as buildBankVatRoot } from '@agoric/vats/src/vat-bank.js';
import { withAmountUtils } from '@agoric/zoe/tools/test-utils.js';
import { makeFakeBankManagerKit } from '@agoric/vats/tools/bank-utils.js';
import { LOCALCHAIN_DEFAULT_ADDRESS } from '@agoric/vats/tools/fake-bridge.js';
import { makeFakeLocalchainBridge } from '../supports.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);
Expand All @@ -26,11 +27,8 @@ test('start', async t => {

const zone = makeHeapZone();
const { makeLocalChain } = prepareLocalChainTools(zone.subZone('localchain'));
const bankManager = await buildBankVatRoot(
undefined,
undefined,
zone.mapStore('bankManager'),
).makeBankManager();

const { bankManager, pourPayment } = await makeFakeBankManagerKit();

await E(bankManager).addAsset('uist', 'IST', 'Inter Stable Token', issuerKit);

Expand Down Expand Up @@ -67,11 +65,19 @@ test('start', async t => {
'Swap for TIA and stake',
);

const bank = await E(bankManager).getBankForAddress(
LOCALCHAIN_DEFAULT_ADDRESS,
);

const istPurse = await E(bank).getPurse(issuerKit.brand);
// bank purse is empty
t.like(await E(istPurse).getCurrentAmount(), stable.makeEmpty());

const ten = stable.units(10);
const userSeat = await E(zoe).offer(
inv,
{ give: { Stable: ten } },
{ Stable: stable.mint.mintPayment(ten) },
{ Stable: await pourPayment(ten) },
{
staked: ten,
validator: {
Expand All @@ -83,4 +89,7 @@ test('start', async t => {
);
const result = await E(userSeat).getOfferResult();
t.is(result, undefined);

// bank purse now has the 10 IST
t.like(await E(istPurse).getCurrentAmount(), ten);
});
7 changes: 2 additions & 5 deletions packages/orchestration/test/examples/unbondExample.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { withAmountUtils } from '@agoric/zoe/tools/test-utils.js';
import { makeHeapZone } from '@agoric/zone';
import { E } from '@endo/far';
import path from 'path';
import { makeFakeBankManagerKit } from '@agoric/vats/tools/bank-utils.js';
import { makeFakeLocalchainBridge } from '../supports.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);
Expand All @@ -26,11 +27,7 @@ test('start', async t => {

const zone = makeHeapZone();
const { makeLocalChain } = prepareLocalChainTools(zone.subZone('localchain'));
const bankManager = await buildBankVatRoot(
undefined,
undefined,
zone.mapStore('bankManager'),
).makeBankManager();
const { bankManager } = await makeFakeBankManagerKit();

await E(bankManager).addAsset('uist', 'IST', 'Inter Stable Token', issuerKit);

Expand Down
1 change: 1 addition & 0 deletions packages/smart-wallet/src/smartWallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,7 @@ export const prepareSmartWallet = (baggage, shared) => {
// When there is a purse deposit into it
if (registry.has(brand)) {
const purse = E(bank).getPurse(brand);
// @ts-expect-error narrow assetKind to 'nat'
return E(purse).deposit(payment);
} else if (invitationBrand === brand) {
// @ts-expect-error narrow assetKind to 'set'
Expand Down
10 changes: 3 additions & 7 deletions packages/smart-wallet/test/addAsset.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
/* eslint @typescript-eslint/no-floating-promises: "warn" */
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';
import { E, Far } from '@endo/far';
import { buildRootObject as buildBankVatRoot } from '@agoric/vats/src/vat-bank.js';
import { AmountMath, makeIssuerKit } from '@agoric/ertp';
import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';
import { makeCopyBag, makeScalarMapStore } from '@agoric/store';
import { makeCopyBag } from '@agoric/store';
import { makePromiseKit } from '@endo/promise-kit';
import bundleSource from '@endo/bundle-source';
import { makeMarshal } from '@endo/marshal';
import { resolve as importMetaResolve } from 'import-meta-resolve';
import { makeFakeBankManagerKit } from '@agoric/vats/tools/bank-utils.js';
import { makeDefaultTestContext } from './contexts.js';
import { ActionType, headValue, makeMockTestSpace } from './supports.js';
import { makeImportContext } from '../src/marshal-contexts.js';
Expand All @@ -24,11 +24,7 @@ const test = anyTest;

test.before(async t => {
const withBankManager = async () => {
const noBridge = undefined;
const baggage = makeScalarMapStore('baggage');
const bankManager = E(
buildBankVatRoot(undefined, undefined, baggage),
).makeBankManager(noBridge);
const { bankManager } = await makeFakeBankManagerKit();
const noop = () => {};
const space0 = await makeMockTestSpace(noop);
space0.produce.bankManager.reset();
Expand Down
17 changes: 4 additions & 13 deletions packages/smart-wallet/test/supports.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { setupClientManager } from '@agoric/vats/src/core/chain-behaviors.js';
import { buildRootObject as boardRoot } from '@agoric/vats/src/vat-board.js';
import { buildRootObject as mintsRoot } from '@agoric/vats/src/vat-mints.js';
import { makeFakeBankKit } from '@agoric/vats/tools/bank-utils.js';
import { makeFakeBankManagerKit } from '@agoric/vats/tools/bank-utils.js';
import { makeRatio } from '@agoric/zoe/src/contractSupport/ratio.js';
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js';
import { E, Far } from '@endo/far';
Expand Down Expand Up @@ -136,18 +136,9 @@ export const makeMockTestSpace = async log => {

produce.testFirstAnchorKit.resolve(makeIssuerKit('AUSD', 'nat'));

const fakeBankKit = makeFakeBankKit([]);

produce.bankManager.resolve(
Promise.resolve(
Far(
'mockBankManager',
/** @type {any} */ ({
getBankForAddress: _a => fakeBankKit.bank,
}),
),
),
);
const { bankManager } = await makeFakeBankManagerKit();

produce.bankManager.resolve(bankManager);

await Promise.all([
// @ts-expect-error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { makeTracer } from '@agoric/internal';
import { makeFakeStorageKit } from '@agoric/internal/src/storage-test-utils.js';
import { makeNameHubKit } from '@agoric/vats';
import { makeAgoricNamesAccess } from '@agoric/vats/src/core/utils.js';
import { makeFakeBankManagerKit } from '@agoric/vats/tools/bank-utils.js';
import { makeFakeBoard } from '@agoric/vats/tools/board-utils.js';
import { makeFakeBankKit } from '@agoric/vats/tools/bank-utils.js';
import { E } from '@endo/eventual-send';
import { Far } from '@endo/marshal';
import { makePromiseKit } from '@endo/promise-kit';
Expand All @@ -20,7 +20,7 @@ const walletAddr = 'agoric1whatever';
const moolaKit = makeIssuerKit('moola');

export const buildRootObject = async () => {
const { bank, addAsset } = makeFakeBankKit([]);
const { bankManager } = await makeFakeBankManagerKit();
const storageKit = makeFakeStorageKit('walletFactoryUpgradeTest');
const statusPath = `walletFactoryUpgradeTest.${walletAddr}`;
const currentPath = `${statusPath}.current`;
Expand All @@ -40,6 +40,8 @@ export const buildRootObject = async () => {
/** @type {import('../../../src/smartWallet.js').SmartWallet} */
let wallet;

const bank = await E(bankManager).getBankForAddress(walletAddr);

// for startInstance
/** @type {Installation<import('../../../src/walletFactory.js').start>} */
let installation;
Expand Down Expand Up @@ -104,7 +106,7 @@ export const buildRootObject = async () => {
).storagePath;
currentStoragePath === currentPath || Fail`bad storage path`;

addAsset('umoola', 'moola', 'moola', moolaKit);
await E(bankManager).addAsset('umoola', 'moola', 'moola', moolaKit);
const depositFacet = E(wallet).getDepositFacet();
const payment = moolaKit.mint.mintPayment(
AmountMath.make(moolaKit.brand, 100n),
Expand Down
4 changes: 3 additions & 1 deletion packages/vats/src/core/basic-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,9 @@ export const addBankAssets = async ({
});

const bldBrand = await E(bldIssuer).getBrand();
const bldKit = harden({ mint: bldMint, issuer: bldIssuer, brand: bldBrand });
const bldKit = /** @type {IssuerKit<'nat'>} */ (
harden({ mint: bldMint, issuer: bldIssuer, brand: bldBrand })
);
bldIssuerKit.resolve(bldKit);

const assetAdmin = E(agoricNamesAdmin).lookupAdmin('vbankAsset');
Expand Down
2 changes: 1 addition & 1 deletion packages/vats/src/core/types-ambient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ type ChainBootstrapSpaceT = {
GovernanceFacetKit<any> & { label: string }
>;
/** Used only for testing. Should not appear in any production proposals. */
testFirstAnchorKit: import('../vat-bank.js').AssetIssuerKit<'nat'>;
testFirstAnchorKit: import('../vat-bank.js').AssetIssuerKit;
walletBridgeManager: import('../types.js').ScopedBridgeManager | undefined;
walletFactoryStartResult: import('./startWalletFactory.js').WalletFactoryStartResult;
provisionPoolStartResult: GovernanceFacetKit<
Expand Down
11 changes: 9 additions & 2 deletions packages/vats/src/localchain.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-check
import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { AmountShape, PaymentShape } from '@agoric/ertp';
import { AmountShape, BrandShape, PaymentShape } from '@agoric/ertp';

const { Fail } = assert;

Expand All @@ -27,6 +27,7 @@ const { Fail } = assert;

export const LocalChainAccountI = M.interface('LocalChainAccount', {
getAddress: M.callWhen().returns(M.string()),
getBalance: M.callWhen(BrandShape).returns(AmountShape),
deposit: M.callWhen(PaymentShape).optional(M.pattern()).returns(AmountShape),
withdraw: M.callWhen(AmountShape).returns(PaymentShape),
executeTx: M.callWhen(M.arrayOf(M.record())).returns(M.arrayOf(M.record())),
Expand All @@ -47,6 +48,12 @@ const prepareLocalChainAccount = zone =>
async getAddress() {
return this.state.address;
},
/** @param {Brand<'nat'>} brand */
async getBalance(brand) {
const { bank } = this.state;
const purse = E(bank).getPurse(brand);
return E(purse).getCurrentAmount();
},
/**
* Deposit a payment into the bank purse that matches the alleged brand.
* This is safe, since even if the payment lies about its brand, ERTP will
Expand All @@ -68,7 +75,7 @@ const prepareLocalChainAccount = zone =>
* Withdraw a payment from the account's bank purse of the amount's brand.
*
* @param {Amount<'nat'>} amount
* @returns {Promise<Payment>} payment
* @returns {Promise<Payment<'nat'>>} payment
*/
async withdraw(amount) {
const { bank } = this.state;
Expand Down
8 changes: 4 additions & 4 deletions packages/vats/src/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Bytes } from '@agoric/network';
import type { PromiseVow } from '@agoric/vow';
import type { PromiseVow, Remote } from '@agoric/vow';
import type { Guarded } from '@endo/exo';
import type { ERef } from '@endo/far';
import type { BridgeIdValue } from '@agoric/internal';
Expand Down Expand Up @@ -106,15 +106,15 @@ export type ScopedBridgeManager<BridgeId extends BridgeIdValue> = Guarded<{
getBridgeId?: () => BridgeId;
toBridge: (obj: any) => Promise<any>;
fromBridge: (obj: any) => PromiseVow<void>;
initHandler: (handler: ERef<BridgeHandler>) => void;
setHandler: (handler: ERef<BridgeHandler>) => void;
initHandler: (handler: Remote<BridgeHandler>) => void;
setHandler: (handler: Remote<BridgeHandler>) => void;
}>;

/** The object to manage this bridge */
export type BridgeManager = {
register: <BridgeId extends BridgeIdValue>(
bridgeId: BridgeId,
handler?: ERef<BridgeHandler | undefined>,
handler?: Remote<BridgeHandler | undefined>,
) => ScopedBridgeManager<BridgeId>;
};

Expand Down
Loading

0 comments on commit 60cffcf

Please sign in to comment.