diff --git a/packages/run-protocol/scripts/build-bundles.js b/packages/run-protocol/scripts/build-bundles.js index cab21173742..25dda2a083d 100644 --- a/packages/run-protocol/scripts/build-bundles.js +++ b/packages/run-protocol/scripts/build-bundles.js @@ -35,6 +35,7 @@ async function main() { `${bundlesDir}/bundle-vaultFactory.js`, ], [`${srcDir}/centralSupply.js`, `${bundlesDir}/bundle-centralSupply.js`], + [`${srcDir}/mintHolder.js`, `${bundlesDir}/bundle-mintHolder.js`], [ `${srcDir}/vaultFactory/liquidateMinimum.js`, `${bundlesDir}/bundle-liquidateMinimum.js`, diff --git a/packages/run-protocol/src/importedBundles.js b/packages/run-protocol/src/importedBundles.js index ce48c2084d4..a9474a15cbb 100644 --- a/packages/run-protocol/src/importedBundles.js +++ b/packages/run-protocol/src/importedBundles.js @@ -7,8 +7,8 @@ import liquidateBundle from '../bundles/bundle-liquidateMinimum.js'; import ammBundle from '../bundles/bundle-amm.js'; import vaultFactoryBundle from '../bundles/bundle-vaultFactory.js'; import centralSupplyBundle from '../bundles/bundle-centralSupply.js'; +import mintHolderBundle from '../bundles/bundle-mintHolder.js'; -/** @type { Record} */ export const governanceBundles = { contractGovernor: contractGovernorBundle, committee: committeeBundle, @@ -17,12 +17,12 @@ export const governanceBundles = { }; harden(governanceBundles); -/** @type { Record} */ export const economyBundles = { liquidate: liquidateBundle, amm: ammBundle, VaultFactory: vaultFactoryBundle, centralSupply: centralSupplyBundle, + mintHolder: mintHolderBundle, }; harden(economyBundles); diff --git a/packages/run-protocol/src/mintHolder.js b/packages/run-protocol/src/mintHolder.js new file mode 100644 index 00000000000..82c43f13360 --- /dev/null +++ b/packages/run-protocol/src/mintHolder.js @@ -0,0 +1,30 @@ +// @ts-check +// @jessie-check + +import { makeIssuerKit } from '@agoric/ertp'; + +/** + * This contract holds one mint; it basically wraps + * makeIssuerKit in its own contract, and hence in + * its own vat. + * + * @param {ContractFacet} zcf + * @returns {{ publicFacet: Issuer, creatorFacet: Mint }} + * + * @typedef {{ + * keyword: string, + * assetKind: AssetKind, + * displayInfo: DisplayInfo, + * }} CustomTerms + */ +export const start = zcf => { + const { keyword, assetKind, displayInfo } = zcf.getTerms(); + + const { mint, issuer } = makeIssuerKit(keyword, assetKind, displayInfo); + + return { + publicFacet: issuer, + creatorFacet: mint, + }; +}; +harden(start); diff --git a/packages/vats/src/core/basic-behaviors.js b/packages/vats/src/core/basic-behaviors.js index 33d7efcae05..a62c38d9197 100644 --- a/packages/vats/src/core/basic-behaviors.js +++ b/packages/vats/src/core/basic-behaviors.js @@ -1,6 +1,6 @@ // @ts-check import { E, Far } from '@endo/far'; -import { AssetKind, makeIssuerKit } from '@agoric/ertp'; +import { AssetKind } from '@agoric/ertp'; import { Nat } from '@agoric/nat'; import { makeNameHubKit } from '../nameHub.js'; @@ -219,7 +219,7 @@ harden(mintInitialSupply); * }} powers */ export const addBankAssets = async ({ - consume: { initialSupply, bridgeManager, loadVat, zoe }, + consume: { initialSupply, bridgeManager, loadVat, zoe, mintHolderBundle }, produce: { bankManager, bldIssuerKit }, issuer: { produce: produceIssuer }, brand: { produce: produceBrand }, @@ -231,11 +231,22 @@ export const addBankAssets = async ({ ]); const runKit = { issuer: runIssuer, brand: runBrand, payment }; - const bldKit = makeIssuerKit( - Tokens.BLD.name, - AssetKind.NAT, - Tokens.BLD.displayInfo, - ); // TODO(#4578): move BLD issuerKit to its own vat + const bundle = await mintHolderBundle; + + /** @type {{ creatorFacet: ERef, publicFacet: ERef }} */ + const { creatorFacet: bldMint, publicFacet: bldIssuer } = E.get( + E(zoe).startInstance( + E(zoe).install(bundle), + harden({}), + harden({ + keyword: Tokens.BLD.name, + assetKind: AssetKind.NAT, + displayInfo: Tokens.BLD.displayInfo, + }), + ), + ); + const bldBrand = await E(bldIssuer).getBrand(); + const bldKit = { mint: bldMint, issuer: bldIssuer, brand: bldBrand }; bldIssuerKit.resolve(bldKit); const bankMgr = E(E(loadVat)('bank')).makeBankManager(bridgeManager); diff --git a/packages/vats/src/core/chain-behaviors.js b/packages/vats/src/core/chain-behaviors.js index a891571737b..18dca0c1c4a 100644 --- a/packages/vats/src/core/chain-behaviors.js +++ b/packages/vats/src/core/chain-behaviors.js @@ -275,11 +275,17 @@ export const connectChainFaucet = async ({ consume: { client } }) => { }; harden(connectChainFaucet); +// XXX: move shareBootContractBundles belongs in basic-behaviors.js /** @param {BootstrapPowers} powers */ export const shareBootContractBundles = async ({ - produce: { centralSupplyBundle: centralP, pegasusBundle: pegasusP }, + produce: { + centralSupplyBundle: centralP, + pegasusBundle: pegasusP, + mintHolderBundle, + }, }) => { centralP.resolve(economyBundles.centralSupply); + mintHolderBundle.resolve(economyBundles.mintHolder); pegasusP.resolve(pegasusBundle); }; diff --git a/packages/vats/src/core/manifest.js b/packages/vats/src/core/manifest.js index b4986413d06..7524dad1577 100644 --- a/packages/vats/src/core/manifest.js +++ b/packages/vats/src/core/manifest.js @@ -72,7 +72,11 @@ const SHARED_BOOTSTRAP_MANIFEST = harden({ home: { produce: { bank: 'bank' } }, }, shareBootContractBundles: { - produce: { centralSupplyBundle: true, pegasusBundle: true }, + produce: { + centralSupplyBundle: true, + mintHolderBundle: true, + pegasusBundle: true, + }, }, mintInitialSupply: { vatParameters: { @@ -94,13 +98,14 @@ const SHARED_BOOTSTRAP_MANIFEST = harden({ // TODO: re-org loadVat to be subject to permits loadVat: true, zoe: true, + mintHolderBundle: true, }, produce: { bankManager: 'bank', bldIssuerKit: true, }, - issuer: { produce: { BLD: true, RUN: 'zoe' } }, - brand: { produce: { BLD: true, RUN: 'zoe' } }, + issuer: { produce: { BLD: 'BLD', RUN: 'zoe' } }, + brand: { produce: { BLD: 'BLD', RUN: 'zoe' } }, }, makeProvisioner: { consume: { @@ -365,6 +370,7 @@ export const SIM_CHAIN_POST_BOOT_MANIFEST = harden({ fundAMM: { consume: { centralSupplyBundle: true, + mintHolderBundle: true, chainTimerService: 'timer', bldIssuerKit: true, feeMintAccess: true, diff --git a/packages/vats/src/core/types.js b/packages/vats/src/core/types.js index 8104f2bfa08..e78dabac60d 100644 --- a/packages/vats/src/core/types.js +++ b/packages/vats/src/core/types.js @@ -78,7 +78,7 @@ */ /** - * @typedef {{ resolve: (v: T) => void }} Producer + * @typedef {{ resolve: (v: ERef) => void }} Producer * @template T */ /** @@ -174,6 +174,7 @@ * ammBundle: ERef, * vaultBundles: ERef>, * centralSupplyBundle: ERef, + * mintHolderBundle: ERef, * feeMintAccess: ERef, * governanceBundles: ERef>, * initialSupply: ERef, @@ -199,6 +200,7 @@ * governanceBundles: Producer>, * initialSupply: Producer, * centralSupplyBundle: Producer, + * mintHolderBundle: Producer, * feeMintAccess: Producer, * priceAuthorityVat: Producer, * priceAuthority: Producer, @@ -237,7 +239,7 @@ * consume: EconomyBootstrapPowers['consume'] & { * bankManager: BankManager, * board: ERef, - * bldIssuerKit: ERef, + * bldIssuerKit: ERef, * bridgeManager: ERef, * client: ERef, * clientCreator: ERef, @@ -249,7 +251,7 @@ * }, * produce: EconomyBootstrapPowers['produce'] & { * bankManager: Producer, - * bldIssuerKit: Producer, + * bldIssuerKit: Producer, * board: Producer>, * bridgeManager: Producer, * client: Producer, @@ -262,6 +264,7 @@ * namesByAddressAdmin: Producer, * }, * }} BootstrapSpace + * @typedef {{ mint: ERef, issuer: ERef, brand: Brand }} RemoteIssuerKit * @typedef {ReturnType['makeBankManager']>} BankManager * @typedef {ERef>} BankVat * @typedef {ERef>} ProvisioningVat diff --git a/packages/vats/src/demoIssuers.js b/packages/vats/src/demoIssuers.js index e42959cbbad..49a8c1bb275 100644 --- a/packages/vats/src/demoIssuers.js +++ b/packages/vats/src/demoIssuers.js @@ -233,7 +233,7 @@ const provideCoin = async (name, mints) => { * * TODO: sync this type with end-user docs? * @typedef {{ - * issuer: Issuer, + * issuer: ERef, * issuerPetname: string, * payment: Payment, * brand: Brand, @@ -395,7 +395,7 @@ export const ammPoolRunDeposits = issuers => { /** * @param {Payment} bootstrapPayment * @param {Record} balances - * @param {{ issuer: Issuer, brand: Brand }} central + * @param {{ issuer: ERef, brand: Brand }} central */ export const splitAllCentralPayments = async ( bootstrapPayment, @@ -427,8 +427,8 @@ export const splitAllCentralPayments = async ( /** * @param {string} issuerName * @param {typeof AMMDemoState['ATOM']} record - * @param {Record} kits - * @param {{ issuer: Issuer, brand: Brand }} central + * @param {Record, brand: Brand }>} kits + * @param {{ issuer: ERef, brand: Brand }} central */ export const poolRates = (issuerName, record, kits, central) => { /** @param { bigint } n */ @@ -557,6 +557,7 @@ export const fundAMM = async ({ assert(kit.issuer, `No issuer for ${issuerName}`); const liquidityIssuer = E(ammPublicFacet).addPool( + // @ts-expect-error TODO: addPool should take ERef kit.issuer, issuerName, ); @@ -581,8 +582,9 @@ export const fundAMM = async ({ }), ); + const issuerPresence = await kit.issuer; return E(vaultFactoryCreator).addVaultType( - kit.issuer, + issuerPresence, issuerName, rates, ); diff --git a/packages/vats/src/vat-bank.js b/packages/vats/src/vat-bank.js index 253410df43c..25fc7bb85e6 100644 --- a/packages/vats/src/vat-bank.js +++ b/packages/vats/src/vat-bank.js @@ -76,8 +76,8 @@ const makePurseController = ( /** * @typedef {Object} AssetIssuerKit - * @property {Mint} [mint] - * @property {Issuer} issuer + * @property {ERef} [mint] + * @property {ERef} issuer * @property {Brand} brand */ @@ -88,7 +88,7 @@ const makePurseController = ( /** * @typedef {Object} AssetDescriptor * @property {Brand} brand - * @property {Issuer} issuer + * @property {ERef} issuer * @property {string} issuerName * @property {string} denom * @property {string} proposedName diff --git a/packages/vats/test/test-clientBundle.js b/packages/vats/test/test-clientBundle.js index 95c064c3d85..89ef3b18cd1 100644 --- a/packages/vats/test/test-clientBundle.js +++ b/packages/vats/test/test-clientBundle.js @@ -55,6 +55,7 @@ test('connectFaucet produces payments', async t => { produce.bldIssuerKit.resolve(bldKit); const runIssuer = E(zoe).getFeeIssuer(); produce.bankManager.resolve( + // @ts-ignore never mind other methods Promise.resolve( // @ts-ignore never mind other methods Far('mockBankManager', { diff --git a/packages/vats/test/test-vat-bank.js b/packages/vats/test/test-vat-bank.js index 7ff49f276d0..e8dfda0ade1 100644 --- a/packages/vats/test/test-vat-bank.js +++ b/packages/vats/test/test-vat-bank.js @@ -111,7 +111,7 @@ test('communication', async t => { message: /"brand" not found/, }); - /** @type {undefined | IteratorResult<{brand: Brand, issuer: Issuer, proposedName: string}>} */ + /** @type {undefined | IteratorResult<{brand: Brand, issuer: ERef, proposedName: string}>} */ let itResult; const p = it.next().then(r => (itResult = r)); t.is(itResult, undefined); @@ -206,6 +206,7 @@ test('mintInitialSupply, addBankAssets bootstrap actions', async t => { produce.agoricNames.resolve(agoricNames); produce.centralSupplyBundle.resolve(economyBundles.centralSupply); + produce.mintHolderBundle.resolve(economyBundles.mintHolder); const { zoeService, feeMintAccess } = makeZoeKit( makeFakeVatAdmin(() => {}).admin,