From 339fd446fd855e70667e6a162423e915ac4dab68 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Fri, 17 Nov 2023 11:47:15 -0800 Subject: [PATCH 1/7] chore(types): BridgeMessage and CoreEvalAction --- packages/cosmic-swingset/src/types.d.ts | 19 +++++++++++++++++++ packages/cosmic-swingset/src/types.js | 2 ++ packages/vats/src/core/chain-behaviors.js | 6 +++++- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 packages/cosmic-swingset/src/types.d.ts create mode 100644 packages/cosmic-swingset/src/types.js diff --git a/packages/cosmic-swingset/src/types.d.ts b/packages/cosmic-swingset/src/types.d.ts new file mode 100644 index 00000000000..2dc8ffbf1bd --- /dev/null +++ b/packages/cosmic-swingset/src/types.d.ts @@ -0,0 +1,19 @@ +import type { + CoreEval, + CoreEvalSDKType, +} from '@agoric/cosmic-proto/agoric/swingset/swingset.js'; + +interface BlockInfo { + blockHeight: number; + blockTime: number; +} + +/** + * @see coreEvalAction in proposal.go + */ +export type CoreEvalAction = BlockInfo & { + type: ActionTypes.CORE_EVAL; + evals: CoreEvalSDKType[]; +}; + +export type BridgeMessage = CoreEvalAction; diff --git a/packages/cosmic-swingset/src/types.js b/packages/cosmic-swingset/src/types.js new file mode 100644 index 00000000000..cda223f55aa --- /dev/null +++ b/packages/cosmic-swingset/src/types.js @@ -0,0 +1,2 @@ +// Empty JS file to correspond with types.d.ts +export {}; diff --git a/packages/vats/src/core/chain-behaviors.js b/packages/vats/src/core/chain-behaviors.js index b8b14c01c11..3640a3d1697 100644 --- a/packages/vats/src/core/chain-behaviors.js +++ b/packages/vats/src/core/chain-behaviors.js @@ -20,6 +20,10 @@ import { BASIC_BOOTSTRAP_PERMITS } from './basic-behaviors.js'; import { agoricNamesReserved, callProperties, extractPowers } from './utils.js'; import { makeScopedBridge } from '../bridge.js'; +/** + * @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js'; + */ + const { keys } = Object; /** @@ -57,10 +61,10 @@ export const bridgeCoreEval = async allPowers => { // Register a coreEval handler over the bridge. const handler = Far('coreHandler', { + /** @param {BridgeMessage} obj */ async fromBridge(obj) { switch (obj.type) { case 'CORE_EVAL': { - /** @type {import('@agoric/cosmic-proto/swingset/swingset.js').CoreEvalProposalSDKType} */ const { evals } = obj; return Promise.all( evals.map(({ json_permits: jsonPermit, js_code: code }) => From 95e7617b93613a4fe3d359ba72fd5f93bd7afe0b Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 20 Jan 2025 12:08:10 -0800 Subject: [PATCH 2/7] refactor(types): PleaseProvisionAction --- packages/cosmic-swingset/src/types.d.ts | 16 ++++++++++++++-- packages/inter-protocol/src/provisionPoolKit.js | 9 +++++++-- .../inter-protocol/test/provisionPool.test.js | 4 ++++ packages/vats/src/core/chain-behaviors.js | 1 + 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/cosmic-swingset/src/types.d.ts b/packages/cosmic-swingset/src/types.d.ts index 2dc8ffbf1bd..bc5e5e1d709 100644 --- a/packages/cosmic-swingset/src/types.d.ts +++ b/packages/cosmic-swingset/src/types.d.ts @@ -1,3 +1,4 @@ +import { QueuedActionType } from '@agoric/internal/src/action-types.js'; import type { CoreEval, CoreEvalSDKType, @@ -12,8 +13,19 @@ interface BlockInfo { * @see coreEvalAction in proposal.go */ export type CoreEvalAction = BlockInfo & { - type: ActionTypes.CORE_EVAL; + type: 'CORE_EVAL'; evals: CoreEvalSDKType[]; }; -export type BridgeMessage = CoreEvalAction; +/** + * @see provisionAction in msg_server.go + */ +export type PleaseProvisionAction = { + type: 'PLEASE_PROVISION'; + address: string; + nickname: string; + powerFlags: PowerFlags.SMART_WALLET; + submitter: string; +}; + +export type BridgeMessage = CoreEvalAction | PleaseProvisionAction; diff --git a/packages/inter-protocol/src/provisionPoolKit.js b/packages/inter-protocol/src/provisionPoolKit.js index 6c3694e6097..cb0ae0cf7c1 100644 --- a/packages/inter-protocol/src/provisionPoolKit.js +++ b/packages/inter-protocol/src/provisionPoolKit.js @@ -23,6 +23,10 @@ import { import { InstanceHandleShape } from '@agoric/zoe/src/typeGuards.js'; import { isUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js'; +/** + * @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js'; + */ + const trace = makeTracer('ProvPool'); const FIRST_UPPER_KEYWORD = /^[A-Z][a-zA-Z0-9_$]*$/; @@ -88,9 +92,10 @@ export const prepareBridgeProvisionTool = zone => forHandler, }), { + /** @param {BridgeMessage} obj */ async fromBridge(obj) { - obj.type === 'PLEASE_PROVISION' || - Fail`Unrecognized request ${obj.type}`; + if (obj.type !== 'PLEASE_PROVISION') + throw Fail`Unrecognized request ${obj.type}`; trace('PLEASE_PROVISION', obj); const { address, powerFlags } = obj; powerFlags.includes(PowerFlags.SMART_WALLET) || diff --git a/packages/inter-protocol/test/provisionPool.test.js b/packages/inter-protocol/test/provisionPool.test.js index e591643a927..16ff93272af 100644 --- a/packages/inter-protocol/test/provisionPool.test.js +++ b/packages/inter-protocol/test/provisionPool.test.js @@ -378,7 +378,9 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => { await handler.fromBridge({ type: 'PLEASE_PROVISION', address, + nickname: 'test', powerFlags: PowerFlags.SMART_WALLET, + submitter: address, }); t.deepEqual( @@ -395,7 +397,9 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => { await handler.fromBridge({ type: 'PLEASE_PROVISION', address, + nickname: 'test', powerFlags: PowerFlags.SMART_WALLET, + submitter: address, }); t.is( myDepositFacet, diff --git a/packages/vats/src/core/chain-behaviors.js b/packages/vats/src/core/chain-behaviors.js index 3640a3d1697..83f76af8022 100644 --- a/packages/vats/src/core/chain-behaviors.js +++ b/packages/vats/src/core/chain-behaviors.js @@ -155,6 +155,7 @@ export const bridgeProvisioner = async ({ // Register a provisioning handler over the bridge. const handler = provisioning ? Far('provisioningHandler', { + /** @param {BridgeMessage} obj */ async fromBridge(obj) { switch (obj.type) { case 'PLEASE_PROVISION': { From 7e0b825ae86a57983690bf68a208b6b1f0e081d3 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 20 Jan 2025 12:18:07 -0800 Subject: [PATCH 3/7] refactor(types): VbankBalanceUpdateAction --- packages/cosmic-swingset/src/types.d.ts | 14 +++++++++++++- packages/vats/src/vat-bank.js | 6 ++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/cosmic-swingset/src/types.d.ts b/packages/cosmic-swingset/src/types.d.ts index bc5e5e1d709..88c4fc2c428 100644 --- a/packages/cosmic-swingset/src/types.d.ts +++ b/packages/cosmic-swingset/src/types.d.ts @@ -28,4 +28,16 @@ export type PleaseProvisionAction = { submitter: string; }; -export type BridgeMessage = CoreEvalAction | PleaseProvisionAction; +/** + * @see VbankBalanceUpdate in vbank.go + */ +export type VbankBalanceUpdateAction = { + type: 'VBANK_BALANCE_UPDATE'; + nonce: string; + updated: Array<{ address: string; denom: string; amount: string }>; +}; + +export type BridgeMessage = + | CoreEvalAction + | PleaseProvisionAction + | VbankBalanceUpdateAction; diff --git a/packages/vats/src/vat-bank.js b/packages/vats/src/vat-bank.js index e7dd101408f..59bd2d61f26 100644 --- a/packages/vats/src/vat-bank.js +++ b/packages/vats/src/vat-bank.js @@ -24,7 +24,7 @@ import { /** * @import {Guarded} from '@endo/exo'; * @import {Passable, RemotableObject} from '@endo/pass-style'; - * @import {VirtualPurseController} from './virtual-purse.js'; + * @import {BridgeMessage} from '@agoric/cosmic-swingset/src/types.js'; */ const { VirtualPurseControllerI } = makeVirtualPurseKitIKit(); @@ -186,11 +186,13 @@ const prepareBankChannelHandler = zone => /** @param {MapStore>} denomToAddressUpdater */ denomToAddressUpdater => ({ denomToAddressUpdater }), { + /** @param {BridgeMessage} obj */ async fromBridge(obj) { - switch (obj && obj.type) { + switch (obj?.type) { case 'VBANK_BALANCE_UPDATE': { const { denomToAddressUpdater } = this.state; for (const update of obj.updated) { + // @ts-expect-error FIXME vbank.go says 'nonce' is on `obj` const { address, denom, amount: value, nonce } = update; /** @type {BalanceUpdater | undefined} */ let updater; From 01ee86258ad904adb7439e118208ee5eb639fc0c Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Mon, 20 Jan 2025 12:20:22 -0800 Subject: [PATCH 4/7] fix: nonce handling in vbank --- packages/vats/src/vat-bank.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/vats/src/vat-bank.js b/packages/vats/src/vat-bank.js index 59bd2d61f26..73ce1b391bc 100644 --- a/packages/vats/src/vat-bank.js +++ b/packages/vats/src/vat-bank.js @@ -192,8 +192,7 @@ const prepareBankChannelHandler = zone => case 'VBANK_BALANCE_UPDATE': { const { denomToAddressUpdater } = this.state; for (const update of obj.updated) { - // @ts-expect-error FIXME vbank.go says 'nonce' is on `obj` - const { address, denom, amount: value, nonce } = update; + const { address, denom, amount } = update; /** @type {BalanceUpdater | undefined} */ let updater; try { @@ -206,7 +205,7 @@ const prepareBankChannelHandler = zone => } if (updater) { try { - updater.update(value, nonce); + updater.update(amount, obj.nonce); } catch (e) { // ??? Is this an invariant that should complain louder? From 65e15b9eb726f184fe41c2d3afdfec31f81ded91 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Tue, 21 Jan 2025 10:05:41 -0800 Subject: [PATCH 5/7] lint(types): typecheck d.ts in cosmic-swingset --- packages/cosmic-swingset/tsconfig.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cosmic-swingset/tsconfig.json b/packages/cosmic-swingset/tsconfig.json index ac54f062118..a4aea10a6de 100644 --- a/packages/cosmic-swingset/tsconfig.json +++ b/packages/cosmic-swingset/tsconfig.json @@ -1,6 +1,9 @@ // This file can contain .js-specific Typescript compiler config. { "extends": "../../tsconfig.json", + "compilerOptions": { + "skipLibCheck": false + }, "include": [ "calc-*.js", "src/**/*.js", From 4c7a89e7f0856b04e22467ce6085d1a149d5efae Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Tue, 21 Jan 2025 10:07:03 -0800 Subject: [PATCH 6/7] feat(types): BridgeMessage ActionContext --- packages/cosmic-swingset/src/types.d.ts | 26 +++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/cosmic-swingset/src/types.d.ts b/packages/cosmic-swingset/src/types.d.ts index 88c4fc2c428..c68185d9271 100644 --- a/packages/cosmic-swingset/src/types.d.ts +++ b/packages/cosmic-swingset/src/types.d.ts @@ -4,35 +4,41 @@ import type { CoreEvalSDKType, } from '@agoric/cosmic-proto/agoric/swingset/swingset.js'; -interface BlockInfo { - blockHeight: number; - blockTime: number; +// TODO move `walletFlags.js` from @agoric/vats to @agoric/cosmic-proto +type PowerFlag = 'SMART_WALLET' | 'REMOTE_WALLET'; + +// NB: keep these manually synced until we build these types out of the Golang +// structs or use some other shared type truth +// https://github.com/Agoric/agoric-sdk/issues/8545 + +interface ActionContext> { + type: T; + blockHeight: string; + blockTime: string; } /** * @see coreEvalAction in proposal.go */ -export type CoreEvalAction = BlockInfo & { - type: 'CORE_EVAL'; +export type CoreEvalAction = ActionContext<'CORE_EVAL'> & { evals: CoreEvalSDKType[]; }; /** * @see provisionAction in msg_server.go */ -export type PleaseProvisionAction = { - type: 'PLEASE_PROVISION'; +export type PleaseProvisionAction = ActionContext<'PLEASE_PROVISION'> & { address: string; nickname: string; - powerFlags: PowerFlags.SMART_WALLET; + powerFlags: PowerFlag[]; submitter: string; + autoProvision: boolean; }; /** * @see VbankBalanceUpdate in vbank.go */ -export type VbankBalanceUpdateAction = { - type: 'VBANK_BALANCE_UPDATE'; +export type VbankBalanceUpdateAction = ActionContext<'VBANK_BALANCE_UPDATE'> & { nonce: string; updated: Array<{ address: string; denom: string; amount: string }>; }; From 6da73285d5be02c142ce5123398344a0681e5f9d Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Tue, 21 Jan 2025 10:00:16 -0800 Subject: [PATCH 7/7] test: correct fromBridge calls --- packages/inter-protocol/src/provisionPoolKit.js | 2 ++ packages/inter-protocol/test/provisionPool.test.js | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/inter-protocol/src/provisionPoolKit.js b/packages/inter-protocol/src/provisionPoolKit.js index cb0ae0cf7c1..3c5b5550cc7 100644 --- a/packages/inter-protocol/src/provisionPoolKit.js +++ b/packages/inter-protocol/src/provisionPoolKit.js @@ -98,6 +98,8 @@ export const prepareBridgeProvisionTool = zone => throw Fail`Unrecognized request ${obj.type}`; trace('PLEASE_PROVISION', obj); const { address, powerFlags } = obj; + // XXX expects powerFlags to be an array, but if it's a string then + // this allows a string that has 'SMART_WALLET' in it. powerFlags.includes(PowerFlags.SMART_WALLET) || Fail`missing SMART_WALLET in powerFlags`; diff --git a/packages/inter-protocol/test/provisionPool.test.js b/packages/inter-protocol/test/provisionPool.test.js index 16ff93272af..bf1dc8b193a 100644 --- a/packages/inter-protocol/test/provisionPool.test.js +++ b/packages/inter-protocol/test/provisionPool.test.js @@ -377,9 +377,12 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => { t.log('1st request to provision a SMART_WALLET for', address); await handler.fromBridge({ type: 'PLEASE_PROVISION', + blockHeight: '123', + blockTime: '1737432662', address, + autoProvision: true, nickname: 'test', - powerFlags: PowerFlags.SMART_WALLET, + powerFlags: [PowerFlags.SMART_WALLET], submitter: address, }); @@ -396,9 +399,12 @@ test('makeBridgeProvisionTool handles duplicate requests', async t => { t.log('2nd request to provision a SMART_WALLET for', address); await handler.fromBridge({ type: 'PLEASE_PROVISION', + blockHeight: '123', + blockTime: '1737432662', address, + autoProvision: true, nickname: 'test', - powerFlags: PowerFlags.SMART_WALLET, + powerFlags: [PowerFlags.SMART_WALLET], submitter: address, }); t.is(