diff --git a/packages/orchestration/src/exos/orchestrator.js b/packages/orchestration/src/exos/orchestrator.js index e18505b8e9a..d6982f8bd39 100644 --- a/packages/orchestration/src/exos/orchestrator.js +++ b/packages/orchestration/src/exos/orchestrator.js @@ -1,7 +1,7 @@ /** @file ChainAccount exo */ import { AmountShape } from '@agoric/ertp'; import { makeTracer } from '@agoric/internal'; -import { V } from '@agoric/vow/vat.js'; +import { E } from '@endo/far'; import { M } from '@endo/patterns'; import { ChainInfoShape, @@ -10,6 +10,7 @@ import { BrandInfoShape, DenomAmountShape, } from '../typeGuards.js'; +import { getChainsAndConnection } from './chain-hub.js'; /** * @import {Zone} from '@agoric/base-zone'; @@ -20,6 +21,7 @@ import { * @import {LocalChain} from '@agoric/vats/src/localchain.js'; * @import {RecorderKit, MakeRecorderKit} from '@agoric/zoe/src/contractSupport/recorder.js'. * @import {Remote} from '@agoric/internal'; + * @import {PickFacet} from '@agoric/swingset-liveslots'; * @import {OrchestrationService} from '../service.js'; * @import {MakeLocalOrchestrationAccountKit} from './local-orchestration-account.js'; * @import {MakeLocalChainFacade} from './local-chain-facade.js'; @@ -54,47 +56,85 @@ export const OrchestratorI = M.interface('Orchestrator', { * zcf: ZCF; * }} powers */ -export const prepareOrchestrator = ( +export const prepareOrchestratorKit = ( zone, { chainHub, localchain, makeLocalChainFacade, makeRemoteChainFacade, - vowTools: _vowTools, + vowTools: { watch, when }, }, ) => - zone.exoClass( + zone.exoClassKit( 'Orchestrator', - OrchestratorI, + { + orchestrator: OrchestratorI, + makeLocalChainFacadeWatcher: M.interface('makeLocalChainFacadeWatcher', { + onFulfilled: M.call(M.record()) + .optional(M.arrayOf(M.undefined())) + .returns(M.any()), // FIXME narrow + }), + makeRemoteChainFacadeWatcher: M.interface( + 'makeRemoteChainFacadeWatcher', + { + onFulfilled: M.call(M.arrayOf(M.record())) + .optional(M.arrayOf(M.undefined())) + .returns(M.any()), // FIXME narrow + }, + ), + }, () => { trace('making an Orchestrator'); return {}; }, { - /** @type {Orchestrator['getChain']} */ - getChain: async name => { - const agoricChainInfo = await chainHub.getChainInfo('agoric'); - - if (name === 'agoric') { - // @ts-expect-error XXX chainInfo generic + /** Waits for `chainInfo` and returns a LocalChainFacade */ + makeLocalChainFacadeWatcher: { + /** @param {ChainInfo} agoricChainInfo */ + onFulfilled(agoricChainInfo) { return makeLocalChainFacade(agoricChainInfo); - } - - const remoteChainInfo = await chainHub.getChainInfo(name); - const connectionInfo = await chainHub.getConnectionInfo( - agoricChainInfo.chainId, - remoteChainInfo.chainId, - ); - - // @ts-expect-error XXX chainInfo generic - return makeRemoteChainFacade(remoteChainInfo, connectionInfo); + }, + }, + /** + * Waits for `chainInfo` for `agoric` and a remote chain and returns a + * RemoteChainFacade + */ + makeRemoteChainFacadeWatcher: { + /** + * Waits for `chainInfo` for `agoric` and a remote chain and returns a + * RemoteChainFacade + * + * @param {[ChainInfo, ChainInfo, IBCConnectionInfo]} chainsAndConnection + */ + onFulfilled([_agoricChainInfo, remoteChainInfo, connectionInfo]) { + return makeRemoteChainFacade(remoteChainInfo, connectionInfo); + }, }, - makeLocalAccount() { - return V(localchain).makeAccount(); + orchestrator: { + /** @type {Orchestrator['getChain']} */ + getChain(name) { + if (name === 'agoric') { + return when( + watch( + chainHub.getChainInfo('agoric'), + this.facets.makeLocalChainFacadeWatcher, + ), + ); + } + return when( + watch( + getChainsAndConnection(chainHub, 'agoric', name), + this.facets.makeRemoteChainFacadeWatcher, + ), + ); + }, + makeLocalAccount() { + return when(watch(E(localchain).makeAccount())); + }, + getBrandInfo: () => Fail`not yet implemented`, + asAmount: () => Fail`not yet implemented`, }, - getBrandInfo: () => Fail`not yet implemented`, - asAmount: () => Fail`not yet implemented`, }, ); -harden(prepareOrchestrator); +harden(prepareOrchestratorKit); diff --git a/packages/orchestration/src/facade.js b/packages/orchestration/src/facade.js index e52d87c85a4..35de5e2b4bb 100644 --- a/packages/orchestration/src/facade.js +++ b/packages/orchestration/src/facade.js @@ -1,8 +1,8 @@ /** @file Orchestration service */ import { Fail } from '@agoric/assert'; - -import { prepareOrchestrator } from './exos/orchestrator.js'; +import { pickFacet } from '@agoric/vat-data'; +import { prepareOrchestratorKit } from './exos/orchestrator.js'; /** * @import {AsyncFlowTools} from '@agoric/async-flow'; @@ -67,7 +67,7 @@ export const makeOrchestrationFacade = ({ asyncFlowTools) || Fail`params missing`; - const makeOrchestrator = prepareOrchestrator(zone, { + const makeOrchestratorKit = prepareOrchestratorKit(zone, { asyncFlowTools, chainHub, localchain, @@ -80,6 +80,7 @@ export const makeOrchestrationFacade = ({ vowTools, zcf, }); + const makeOrchestrator = pickFacet(makeOrchestratorKit, 'orchestrator'); return { /** diff --git a/packages/orchestration/src/utils/time.js b/packages/orchestration/src/utils/time.js index a7e63504a12..8e8dc062f6e 100644 --- a/packages/orchestration/src/utils/time.js +++ b/packages/orchestration/src/utils/time.js @@ -9,7 +9,11 @@ import { TimeMath } from '@agoric/time'; export const SECONDS_PER_MINUTE = 60n; export const NANOSECONDS_PER_SECOND = 1_000_000_000n; -/** @param {Remote} timer */ +/** + * XXX should this be durable? resumable? + * + * @param {Remote} timer + */ export function makeTimestampHelper(timer) { /** @type {TimerBrand | undefined} */ let brandCache;