diff --git a/packages/agoric-cli/src/commands/ec.js b/packages/agoric-cli/src/commands/ec.js index 145680aa670..33a43380a49 100644 --- a/packages/agoric-cli/src/commands/ec.js +++ b/packages/agoric-cli/src/commands/ec.js @@ -32,7 +32,6 @@ export const makeEconomicCommiteeCommand = async _logger => { id: opts.offerId, invitationSpec: { source: 'purse', - // @ts-expect-error xxx RpcRemote instance: economicCommittee, description: 'Voter0', // XXX it may not always be }, @@ -56,7 +55,6 @@ export const makeEconomicCommiteeCommand = async _logger => { id: opts.offerId, invitationSpec: { source: 'purse', - // @ts-expect-error xxx RpcRemote instance: econCommitteeCharter, description: 'charter member invitation', }, diff --git a/packages/agoric-cli/src/commands/oracle.js b/packages/agoric-cli/src/commands/oracle.js index 5787b4fed04..393c4c7c52a 100644 --- a/packages/agoric-cli/src/commands/oracle.js +++ b/packages/agoric-cli/src/commands/oracle.js @@ -66,7 +66,6 @@ export const makeOracleCommand = async logger => { id: Number(opts.offerId), invitationSpec: { source: 'purse', - // @ts-expect-error xxx RpcRemote instance, description: 'oracle invitation', }, diff --git a/packages/agoric-cli/src/commands/psm.js b/packages/agoric-cli/src/commands/psm.js index 12521d9f041..98b1d6a4a6d 100644 --- a/packages/agoric-cli/src/commands/psm.js +++ b/packages/agoric-cli/src/commands/psm.js @@ -150,10 +150,11 @@ export const makePsmCommand = async logger => { .action(async function (opts) { console.warn('running with options', opts); const instance = await lookupPsmInstance(opts.pair); - // @ts-expect-error xxx RpcRemote const offer = Offers.psm.swap(instance, agoricNames.brand, { offerId: opts.offerId, feePct: opts.feePct, + giveMinted: opts.giveMinted, + wantMinted: opts.wantMinted, }); outputExecuteOfferAction(offer); }); diff --git a/packages/agoric-cli/src/commands/wallet.js b/packages/agoric-cli/src/commands/wallet.js index 715b06c661f..673b1953270 100644 --- a/packages/agoric-cli/src/commands/wallet.js +++ b/packages/agoric-cli/src/commands/wallet.js @@ -155,9 +155,20 @@ export const makeWalletCommand = async () => { } catch (e) { console.error('CAUGHT HERE', e); } - execFileSync('agd', [`query`, 'bank', 'balances', opts.from], { - stdio: 'inherit', - }); + execFileSync( + 'agd', + [ + 'query', + '--node', + networkConfig.rpcAddrs[0], + 'bank', + 'balances', + opts.from, + ], + { + stdio: 'inherit', + }, + ); }); wallet diff --git a/packages/agoric-cli/src/lib/format.js b/packages/agoric-cli/src/lib/format.js index c19fcc785a3..d934e02647d 100644 --- a/packages/agoric-cli/src/lib/format.js +++ b/packages/agoric-cli/src/lib/format.js @@ -1,5 +1,5 @@ // @ts-check -/* eslint-disable @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */ +import { makeBoardRemote } from '@agoric/vats/tools/board-utils.js'; // eslint-disable-next-line no-unused-vars -- typeof below import { makeAgoricNames } from './rpc.js'; @@ -20,14 +20,17 @@ export const Natural = str => { return b; }; +/** @type {import('@agoric/vats/tools/board-utils.js').VBankAssetDetail} */ // eslint-disable-next-line no-unused-vars const exampleAsset = { - brand: { boardId: 'board0425', iface: 'Alleged: BLD brand' }, + // @ts-expect-error cast + brand: makeBoardRemote({ boardId: 'board0425', iface: 'Alleged: BLD brand' }), displayInfo: { assetKind: 'nat', decimalPlaces: 6 }, - issuer: { boardId: null, iface: undefined }, + // @ts-expect-error cast + issuer: makeBoardRemote({ boardId: null, iface: undefined }), petname: 'Agoric staking token', }; -/** @typedef {import('@agoric/smart-wallet/src/smartWallet').BrandDescriptor & {brand: import('./rpc').RpcRemote}} AssetDescriptor */ +/** @typedef {import('@agoric/vats/tools/board-utils.js').VBankAssetDetail & { brand: import('@agoric/vats/tools/board-utils.js').BoardRemote }} AssetDescriptor */ /** @param {AssetDescriptor[]} assets */ export const makeAmountFormatter = assets => amt => { @@ -35,24 +38,22 @@ export const makeAmountFormatter = assets => amt => { brand: { boardId }, value, } = amt; - const asset = assets.find(a => a.brand.boardId === boardId); + const asset = assets.find(a => a.brand.getBoardId() === boardId); if (!asset) return [NaN, boardId]; const { - petname, displayInfo: { assetKind, decimalPlaces = 0 }, + issuerName, } = asset; - const name = Array.isArray(petname) ? petname.join('.') : petname; switch (assetKind) { case 'nat': - /** @type {[petname: string, qty: number]} */ - return [name, Number(value) / 10 ** decimalPlaces]; + return [issuerName, Number(value) / 10 ** decimalPlaces]; case 'set': if (value[0]?.handle?.iface?.includes('InvitationHandle')) { - return [name, value.map(v => v.description)]; + return [issuerName, value.map(v => v.description)]; } - return [name, value]; + return [issuerName, value]; default: - return [name, ['?']]; + return [issuerName, ['?']]; } }; @@ -97,11 +98,7 @@ export const fmtRecordOfLines = record => { */ export const offerStatusTuples = (state, agoricNames) => { const { offerStatuses } = state; - const fmt = makeAmountFormatter( - // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */ - // @ts-ignore xxx RpcRemote - Object.values(agoricNames.vbankAsset), - ); + const fmt = makeAmountFormatter(Object.values(agoricNames.vbankAsset)); const fmtRecord = r => r ? Object.fromEntries( @@ -132,7 +129,6 @@ export const offerStatusTuples = (state, agoricNames) => { } = o; // xxx could be O(1) const entry = Object.entries(agoricNames.instance).find( - // @ts-ignore minimarshal types are off by a bit ([_name, candidate]) => candidate === instance, ); const instanceName = entry ? entry[0] : '???'; @@ -161,11 +157,7 @@ export const summarize = (current, coalesced, agoricNames) => { return { lastOfferId: [current.lastOfferId], purses: purseBalanceTuples( - // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */ - // @ts-ignore xxx RpcRemote [...current.purses.values()], - // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error -- https://github.com/Agoric/agoric-sdk/issues/4620 */ - // @ts-ignore xxx RpcRemote Object.values(agoricNames.vbankAsset), ), usedInvitations: Object.entries(current.offerToUsedInvitation).map( diff --git a/packages/agoric-cli/src/lib/rpc.js b/packages/agoric-cli/src/lib/rpc.js index b1971dba1ea..935b8964342 100644 --- a/packages/agoric-cli/src/lib/rpc.js +++ b/packages/agoric-cli/src/lib/rpc.js @@ -3,14 +3,13 @@ /* global Buffer, fetch, process */ import { NonNullish } from '@agoric/assert'; -import { boardSlottingMarshaller } from '@agoric/vats/tools/board-utils.js'; +import { + boardSlottingMarshaller, + makeBoardRemote, +} from '@agoric/vats/tools/board-utils.js'; export { boardSlottingMarshaller }; -/** - * @typedef {{boardId: string, iface: string}} RpcRemote - */ - export const networkConfigUrl = agoricNetSubdomain => `https://${agoricNetSubdomain}.agoric.net/network-config`; export const rpcUrl = agoricNetSubdomain => @@ -125,14 +124,14 @@ export const makeVStorage = powers => { }; /** @typedef {ReturnType} VStorage */ -export const makeFromBoard = (slotKey = 'boardId') => { +export const makeFromBoard = () => { const cache = new Map(); - const convertSlotToVal = (slot, iface) => { - if (cache.has(slot)) { - return cache.get(slot); + const convertSlotToVal = (boardId, iface) => { + if (cache.has(boardId)) { + return cache.get(boardId); } - const val = harden({ [slotKey]: slot, iface }); - cache.set(slot, val); + const val = makeBoardRemote({ boardId, iface }); + cache.set(boardId, val); return val; }; return harden({ convertSlotToVal }); @@ -189,9 +188,12 @@ export const makeAgoricNames = async (ctx, vstorage) => { const content = await vstorage.readLatest( `published.agoricNames.${kind}`, ); + /** @type {Array<[string, import('@agoric/vats/tools/board-utils.js').BoardRemote]>} */ const parts = storageHelper.unserializeTxt(content, ctx).at(-1); for (const [name, remote] of parts) { - reverse[remote.boardId] = name; + if ('getBoardId' in remote) { + reverse[remote.getBoardId()] = name; + } } return [kind, Object.fromEntries(parts)]; }), diff --git a/packages/inter-protocol/src/clientSupport.js b/packages/inter-protocol/src/clientSupport.js index 694ba808f27..504f2e78663 100644 --- a/packages/inter-protocol/src/clientSupport.js +++ b/packages/inter-protocol/src/clientSupport.js @@ -11,7 +11,7 @@ const COSMOS_UNIT = 1_000_000n; /** * Give/want * - * @param {Record} brands + * @param {Record} brands * @param {{ giveMinted?: number, wantMinted?: number } | { collateralBrandKey: string, giveCollateral?: number, wantCollateral?: number }} opts * @returns {Proposal} */ @@ -54,7 +54,7 @@ const makeVaultProposal = (brands, opts) => { // Then these can be used in tests as arguments to `executeOffer()` without a bridge. /** - * @param {Record} brands + * @param {Record} brands * @param {{ offerId: string, wantMinted: number, giveCollateral: number, collateralBrandKey: string }} opts * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec} */ @@ -85,7 +85,7 @@ const makeOpenOffer = (brands, opts) => { }; /** - * @param {Record} brands + * @param {Record} brands * @param {{ offerId: string, collateralBrandKey?: string, giveCollateral?: number, wantCollateral?: number, giveMinted?: number, wantMinted?: number }} opts * @param {string} previousOffer * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec} @@ -108,7 +108,7 @@ const makeAdjustOffer = (brands, opts, previousOffer) => { }; /** - * @param {Record} brands + * @param {Record} brands * @param {{ offerId: string, collateralBrandKey?: string, giveMinted: number }} opts * @param {string} previousOffer * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec} @@ -147,7 +147,7 @@ export const lookupOfferIdForVault = async (vaultId, currentP) => { }; /** - * @param {Record} brands + * @param {Record} brands * @param {({ wantMinted: number | undefined, giveMinted: number | undefined })} opts * @param {number} [fee=0] * @param {string} [anchor] @@ -168,11 +168,9 @@ const makePsmProposal = (brands, opts, fee = 0, anchor = 'AUSD') => { }; return { give: { - // @ts-expect-error XXX BoardRemote not real remote In: { brand: brand.in, value: adjusted.in }, }, want: { - // @ts-expect-error XXX BoardRemote not real remote Out: { brand: brand.out, value: adjusted.out }, }, }; @@ -180,7 +178,7 @@ const makePsmProposal = (brands, opts, fee = 0, anchor = 'AUSD') => { /** * @param {Instance} instance - * @param {Record} brands + * @param {Record} brands * @param {{ offerId: number, feePct?: number } & * ({ wantMinted: number | undefined, giveMinted: number | undefined })} opts * @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec} diff --git a/packages/smart-wallet/src/utils.js b/packages/smart-wallet/src/utils.js index 7f82d9e4dfc..addb7ca6b52 100644 --- a/packages/smart-wallet/src/utils.js +++ b/packages/smart-wallet/src/utils.js @@ -15,7 +15,7 @@ export const makeWalletStateCoalescer = (invitationBrand = undefined) => { /** * keyed by description; xxx assumes unique * - * @type {Map} + * @type {Map} */ const invitationsReceived = new Map(); diff --git a/packages/vats/test/bootstrapTests/supports.js b/packages/vats/test/bootstrapTests/supports.js index 9ac2af31539..96666f0f53d 100644 --- a/packages/vats/test/bootstrapTests/supports.js +++ b/packages/vats/test/bootstrapTests/supports.js @@ -150,7 +150,7 @@ export const makeWalletFactoryDriver = async ( return EV(walletPresence).handleBridgeAction(offerCapData, true); }, /** - * @template {(brands: Record, ...rest: any) => import('@agoric/smart-wallet/src/offers.js').OfferSpec} M offer maker function + * @template {(brands: Record, ...rest: any) => import('@agoric/smart-wallet/src/offers.js').OfferSpec} M offer maker function * @param {M} makeOffer * @param {Parameters[1]} firstArg * @param {Parameters[2]} [secondArg] diff --git a/packages/vats/test/test-board-utils.js b/packages/vats/test/test-board-utils.js index 7482ed29e51..d899aa51229 100644 --- a/packages/vats/test/test-board-utils.js +++ b/packages/vats/test/test-board-utils.js @@ -152,7 +152,7 @@ test('makeAgoricNamesRemotesFromFakeStorage', t => { for (const path of ['brand', 'instance']) { t.true( Object.values(agoricNamesRemotes[path]).every(v => - v.boardId.startsWith('board0'), + v.getBoardId().startsWith('board0'), ), ); } @@ -185,7 +185,7 @@ test( test( 'board ids', serialize, - { boardId: 'board123' }, + { getBoardId: () => 'board123' }, { body: '{"@qclass":"slot","index":0}', slots: ['board123'] }, ); @@ -193,8 +193,8 @@ test( 'nested board ids', serialize, { - istBrand: { boardId: 'board123Ist' }, - atomBrand: { boardId: 'board123Atom' }, + istBrand: { getBoardId: () => 'board123Ist' }, + atomBrand: { getBoardId: () => 'board123Atom' }, }, { body: '{"istBrand":{"@qclass":"slot","index":0},"atomBrand":{"@qclass":"slot","index":1}}', diff --git a/packages/vats/tools/board-utils.js b/packages/vats/tools/board-utils.js index 36225293627..96bfa741424 100644 --- a/packages/vats/tools/board-utils.js +++ b/packages/vats/tools/board-utils.js @@ -1,27 +1,40 @@ // @ts-check /** - * @typedef {{boardId: string, iface: string}} BoardRemote + * Should be a union with Remotable, but that's `any`, making this type meaningless + * + * @typedef {{ getBoardId: () => string }} BoardRemote */ /** * @typedef {{ - * brand: BoardRemote, + * brand: BoardRemote & Brand, * denom: string, * displayInfo: DisplayInfo, - * issuer: BoardRemote, + * issuer: BoardRemote & Issuer, * issuerName: string, * proposedName: string, * }} VBankAssetDetail */ /** * @typedef {{ - * brand: Record, - * instance: Record, - * vbankAsset?: Record, + * brand: Record, + * instance: Record, + * vbankAsset: Record, * reverse: Record, * }} AgoricNamesRemotes */ import { Fail } from '@agoric/assert'; +import { Far } from '@endo/marshal'; + +/** + * @param {*} slotInfo + * @returns {BoardRemote} + */ +export const makeBoardRemote = ({ boardId, iface }) => { + const nonalleged = + iface && iface.length ? iface.slice('Alleged: '.length) : ''; + return Far(`BoardRemote${nonalleged}`, { getBoardId: () => boardId }); +}; /** * @param {import("@agoric/internal/src/storage-test-utils.js").FakeStorageKit} fakeStorageKit @@ -39,12 +52,16 @@ export const makeAgoricNamesRemotesFromFakeStorage = fakeStorageKit => { (values && values.length > 0) || Fail`no data for ${key}`; /** @type {import("@endo/marshal").CapData} */ const latestCapData = JSON.parse(values.at(-1)); + /** @type {Array<[string, import('@agoric/vats/tools/board-utils.js').BoardRemote]>} */ const parts = JSON.parse(latestCapData.body).map(([name, slotInfo]) => [ name, - { boardId: latestCapData.slots[slotInfo.index], iface: slotInfo.iface }, + makeBoardRemote({ + boardId: latestCapData.slots[slotInfo.index], + iface: slotInfo.iface, + }), ]); for (const [name, remote] of parts) { - reverse[remote.boardId] = name; + reverse[remote.getBoardId()] = name; } return [kind, Object.fromEntries(parts)]; }); @@ -55,7 +72,7 @@ harden(makeAgoricNamesRemotesFromFakeStorage); /** * Like makeMarshal but, * - slotToVal takes an iface arg - * - if a part being serialized has a boardId property, it passes through as a slot value whereas the normal marshaller would treat it as a copyRecord + * - if a part being serialized has getBoardId(), it passes through as a slot value whereas the normal marshaller would treat it as a copyRecord * * @param {(slot: string, iface: string) => any} slotToVal * @returns {import('@endo/marshal').Marshal} @@ -102,8 +119,9 @@ export const boardSlottingMarshaller = (slotToVal = (s, _i) => s) => ({ return part.map(recur); } if (typeof part === 'object') { - if ('boardId' in part) { - return { '@qclass': 'slot', index: slotIndex(part.boardId) }; + if ('getBoardId' in part) { + const index = slotIndex(part.getBoardId()); + return { '@qclass': 'slot', index }; } return Object.fromEntries( Object.entries(part).map(([k, v]) => [k, recur(v)]),