diff --git a/packages/async-flow/index.js b/packages/async-flow/index.js index a795feb1424..cd3db12eb51 100644 --- a/packages/async-flow/index.js +++ b/packages/async-flow/index.js @@ -1,3 +1,2 @@ export * from './src/async-flow.js'; export * from './src/types-index.js'; -export { makeSharedStateRecord } from './src/endowments.js'; diff --git a/packages/async-flow/src/endowments.js b/packages/async-flow/src/endowments.js index 1aba97efaaf..909fb06389f 100644 --- a/packages/async-flow/src/endowments.js +++ b/packages/async-flow/src/endowments.js @@ -53,38 +53,6 @@ export const forwardingMethods = rem => { return fromEntries(keys.map(makeMethodEntry)); }; -/** - * Given a possibly mutable (and therefore unhardened) record, return a - * corresponding state record that acts identically for normal - * gets and sets, but is implemented using accessors, so it will be recognized - * as a state record. - * - * @template { string | number | symbol } K - * @template {Record} R - * @param {R} dataRecord - * @returns {R} - */ -export const makeSharedStateRecord = dataRecord => - harden( - create( - objectPrototype, - fromEntries( - ownKeys(dataRecord).flatMap(key => - entries( - getOwnPropertyDescriptors({ - get [key]() { - return dataRecord[key]; - }, - set [key](newValue) { - dataRecord[key] = newValue; - }, - }), - ), - ), - ), - ), - ); - /** * @param {Zone} outerZone * @param {PreparationOptions} [outerOptions] diff --git a/packages/orchestration/src/examples/send-anywhere.contract.js b/packages/orchestration/src/examples/send-anywhere.contract.js index f555817d7dd..3cfab6ec922 100644 --- a/packages/orchestration/src/examples/send-anywhere.contract.js +++ b/packages/orchestration/src/examples/send-anywhere.contract.js @@ -1,5 +1,3 @@ -import { makeSharedStateRecord } from '@agoric/async-flow'; - import { InvitationShape } from '@agoric/zoe/src/typeGuards.js'; import { E } from '@endo/far'; import { M } from '@endo/patterns'; @@ -7,6 +5,7 @@ import { prepareChainHubAdmin } from '../exos/chain-hub-admin.js'; import { AnyNatAmountShape } from '../typeGuards.js'; import { withOrchestration } from '../utils/start-helper.js'; import * as flows from './send-anywhere.flows.js'; +import * as sharedFlows from './shared.flows.js'; /** * @import {Vow} from '@agoric/vow'; @@ -38,12 +37,6 @@ export const contract = async ( zone, { chainHub, orchestrateAll, vowTools, zoeTools }, ) => { - const contractState = makeSharedStateRecord( - /** @type {{ account: OrchestrationAccount | undefined }} */ { - localAccount: undefined, - }, - ); - const creatorFacet = prepareChainHubAdmin(zone, chainHub); // UNTIL https://github.com/Agoric/agoric-sdk/issues/9066 @@ -51,10 +44,24 @@ export const contract = async ( /** @type {(msg: string) => Vow} */ const log = msg => vowTools.watch(E(logNode).setValue(msg)); + const { makeLocalAccount } = orchestrateAll(sharedFlows, {}); + /** + * Setup a shared local account for use in async-flow functions. Typically, + * exo initState functions need to resolve synchronously, but `makeOnce` + * allows us to provide a Promise. When using this inside a flow, we must + * await it to ensure the account is available for use. + * + * @type {any} sharedLocalAccountP expects a Promise but this is a vow + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccountP = zone.makeOnce('localAccount', () => + makeLocalAccount(), + ); + // orchestrate uses the names on orchestrationFns to do a "prepare" of the associated behavior const orchFns = orchestrateAll(flows, { - contractState, log, + sharedLocalAccountP, zoeTools, }); diff --git a/packages/orchestration/src/examples/send-anywhere.flows.js b/packages/orchestration/src/examples/send-anywhere.flows.js index 74ab64b5f03..6022fcb40f1 100644 --- a/packages/orchestration/src/examples/send-anywhere.flows.js +++ b/packages/orchestration/src/examples/send-anywhere.flows.js @@ -5,8 +5,9 @@ import { M, mustMatch } from '@endo/patterns'; /** * @import {GuestInterface, GuestOf} from '@agoric/async-flow'; * @import {Vow} from '@agoric/vow'; + * @import {LocalOrchestrationAccountKit} from '../exos/local-orchestration-account.js'; * @import {ZoeTools} from '../utils/zoe-tools.js'; - * @import {Orchestrator, LocalAccountMethods, OrchestrationAccountI, OrchestrationFlow} from '../types.js'; + * @import {Orchestrator, OrchestrationFlow, LocalAccountMethods} from '../types.js'; */ const { entries } = Object; @@ -18,7 +19,7 @@ const { entries } = Object; * @satisfies {OrchestrationFlow} * @param {Orchestrator} orch * @param {object} ctx - * @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState + * @param {Promise>} ctx.sharedLocalAccountP * @param {GuestInterface} ctx.zoeTools * @param {GuestOf<(msg: string) => Vow>} ctx.log * @param {ZCFSeat} seat @@ -26,7 +27,7 @@ const { entries } = Object; */ export const sendIt = async ( orch, - { contractState, log, zoeTools: { localTransfer, withdrawToSeat } }, + { sharedLocalAccountP, log, zoeTools: { localTransfer, withdrawToSeat } }, seat, offerArgs, ) => { @@ -44,23 +45,23 @@ export const sendIt = async ( `${amt.brand} not registered in vbank`, ); - // FIXME racy - if (!contractState.localAccount) { - contractState.localAccount = await agoric.makeAccount(); - } - const chain = await orch.getChain(chainName); const info = await chain.getChainInfo(); const { chainId } = info; assert(typeof chainId === 'string', 'bad chainId'); void log(`got info for chain: ${chainName} ${chainId}`); - await localTransfer(seat, contractState.localAccount, give); + /** + * @type {any} XXX methods returning vows + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccount = await sharedLocalAccountP; + await localTransfer(seat, sharedLocalAccount, give); void log(`completed transfer to localAccount`); try { - await contractState.localAccount.transfer( + await sharedLocalAccount.transfer( { value: destAddr, encoding: 'bech32', @@ -70,7 +71,7 @@ export const sendIt = async ( ); void log(`completed transfer to ${destAddr}`); } catch (e) { - await withdrawToSeat(contractState.localAccount, seat, give); + await withdrawToSeat(sharedLocalAccount, seat, give); const errorMsg = `IBC Transfer failed ${q(e)}`; void log(`ERROR: ${errorMsg}`); seat.exit(errorMsg); diff --git a/packages/orchestration/src/examples/shared.flows.js b/packages/orchestration/src/examples/shared.flows.js new file mode 100644 index 00000000000..80d2e8d25fd --- /dev/null +++ b/packages/orchestration/src/examples/shared.flows.js @@ -0,0 +1,21 @@ +/** + * @file Flows shared by multiple examples + * + * A module with flows can be used be reused across multiple contracts. They are + * bound to a particular contract's context via orchestrateAll. See + * ./send-anywhere.contract.js for example usage. + */ +/** + * @import {Orchestrator, OrchestrationFlow, LocalAccountMethods} from '../types.js'; + */ + +/** + * @satisfies {OrchestrationFlow} + * @param {Orchestrator} orch + * @returns {Promise} + */ +export const makeLocalAccount = async orch => { + const agoricChain = await orch.getChain('agoric'); + return agoricChain.makeAccount(); +}; +harden(makeLocalAccount); diff --git a/packages/orchestration/src/examples/stake-bld.contract.js b/packages/orchestration/src/examples/stake-bld.contract.js index f51136e2629..db657e1235c 100644 --- a/packages/orchestration/src/examples/stake-bld.contract.js +++ b/packages/orchestration/src/examples/stake-bld.contract.js @@ -111,6 +111,8 @@ export const start = async (zcf, privateArgs, baggage) => { const { give } = seat.getProposal(); trace('makeStakeBldInvitation', give); const { holder } = await makeLocalAccountKit(); + /** @type {Record>} */ + // @ts-expect-error XXX PaymentPKeywordRecord throught deeplyFulfilled will be a PaymnentKeywordRecord const { In } = await deeplyFulfilled( withdrawFromSeat(zcf, seat, give), ); diff --git a/packages/orchestration/src/examples/staking-combinations.contract.js b/packages/orchestration/src/examples/staking-combinations.contract.js index 2158a4560bb..0f233c85fdf 100644 --- a/packages/orchestration/src/examples/staking-combinations.contract.js +++ b/packages/orchestration/src/examples/staking-combinations.contract.js @@ -5,7 +5,6 @@ * The primary offer result is a power for invitation makers that can perform * actions with an ICA account. */ -import { makeSharedStateRecord } from '@agoric/async-flow'; import { AmountShape } from '@agoric/ertp'; import { M } from '@endo/patterns'; import { prepareCombineInvitationMakers } from '../exos/combine-invitation-makers.js'; @@ -13,6 +12,7 @@ import { CosmosOrchestrationInvitationMakersI } from '../exos/cosmos-orchestrati import { ChainAddressShape, DelegationShape } from '../typeGuards.js'; import { withOrchestration } from '../utils/start-helper.js'; import * as flows from './staking-combinations.flows.js'; +import * as sharedFlows from './shared.flows.js'; import { prepareChainHubAdmin } from '../exos/chain-hub-admin.js'; /** @@ -46,16 +46,6 @@ const contract = async ( zone, { orchestrateAll, zoeTools, chainHub }, ) => { - const contractState = makeSharedStateRecord( - /** - * @type {{ - * account: (OrchestrationAccount & LocalAccountMethods) | undefined; - * }} - */ { - localAccount: undefined, - }, - ); - const StakingCombinationsInvitationMakersI = M.interface( 'StakingCombinationsInvitationMakersI', { @@ -128,8 +118,22 @@ const contract = async ( StakingCombinationsInvitationMakersI, ); + const { makeLocalAccount } = orchestrateAll(sharedFlows, {}); + /** + * Setup a shared local account for use in async-flow functions. Typically, + * exo initState functions need to resolve synchronously, but `makeOnce` + * allows us to provide a Promise. When using this inside a flow, we must + * await it to ensure the account is available for use. + * + * @type {any} sharedLocalAccountP expects a Promise but this is a vow + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccountP = zone.makeOnce('localAccount', () => + makeLocalAccount(), + ); + const orchFns = orchestrateAll(flows, { - contractState, + sharedLocalAccountP, makeCombineInvitationMakers, makeExtraInvitationMaker, flows, diff --git a/packages/orchestration/src/examples/staking-combinations.flows.js b/packages/orchestration/src/examples/staking-combinations.flows.js index 9bfaba08d54..23b1583ce58 100644 --- a/packages/orchestration/src/examples/staking-combinations.flows.js +++ b/packages/orchestration/src/examples/staking-combinations.flows.js @@ -2,6 +2,7 @@ * @import {GuestInterface} from '@agoric/async-flow'; * @import {Orchestrator, OrchestrationFlow, AmountArg, CosmosValidatorAddress, ChainAddress, LocalAccountMethods, OrchestrationAccountI} from '../types.js' * @import {ContinuingOfferResult, InvitationMakers} from '@agoric/smart-wallet/src/types.js'; + * @import {LocalOrchestrationAccountKit} from '../exos/local-orchestration-account.js'; * @import {MakeCombineInvitationMakers} from '../exos/combine-invitation-makers.js'; * @import {CosmosOrchestrationAccount} from '../exos/cosmos-orchestration-account.js'; * @import {ResolvedContinuingOfferResult, ZoeTools} from '../utils/zoe-tools.js'; @@ -47,7 +48,7 @@ harden(makeAccount); * @satisfies {OrchestrationFlow} * @param {Orchestrator} orch * @param {object} ctx - * @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState + * @param {Promise>} ctx.sharedLocalAccountP * @param {GuestInterface} ctx.zoeTools * @param {GuestInterface} account * @param {ZCFSeat} seat @@ -56,7 +57,7 @@ harden(makeAccount); */ export const depositAndDelegate = async ( orch, - { contractState, zoeTools }, + { sharedLocalAccountP, zoeTools }, account, seat, validator, @@ -64,18 +65,20 @@ export const depositAndDelegate = async ( await null; trace('depositAndDelegate', account, seat, validator); mustMatch(validator, ChainAddressShape); - if (!contractState.localAccount) { - const agoricChain = await orch.getChain('agoric'); - contractState.localAccount = await agoricChain.makeAccount(); - } + const { give } = seat.getProposal(); - await zoeTools.localTransfer(seat, contractState.localAccount, give); + /** + * @type {any} XXX methods returning vows + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccount = await sharedLocalAccountP; + await zoeTools.localTransfer(seat, sharedLocalAccount, give); const address = account.getAddress(); try { - await contractState.localAccount.transfer(address, give.Stake); + await sharedLocalAccount.transfer(address, give.Stake); } catch (cause) { - await zoeTools.withdrawToSeat(contractState.localAccount, seat, give); + await zoeTools.withdrawToSeat(sharedLocalAccount, seat, give); const errMsg = makeError(`ibc transfer failed ${q(cause)}`); seat.exit(errMsg); throw errMsg; diff --git a/packages/orchestration/src/exos/local-orchestration-account.js b/packages/orchestration/src/exos/local-orchestration-account.js index cb75695dc35..bc5e1f2a48a 100644 --- a/packages/orchestration/src/exos/local-orchestration-account.js +++ b/packages/orchestration/src/exos/local-orchestration-account.js @@ -28,7 +28,7 @@ import { coerceCoin, coerceDenomAmount } from '../utils/amounts.js'; /** * @import {HostOf} from '@agoric/async-flow'; * @import {LocalChain, LocalChainAccount} from '@agoric/vats/src/localchain.js'; - * @import {AmountArg, ChainAddress, DenomAmount, IBCMsgTransferOptions, IBCConnectionInfo, OrchestrationAccountI} from '@agoric/orchestration'; + * @import {AmountArg, ChainAddress, DenomAmount, IBCMsgTransferOptions, IBCConnectionInfo, OrchestrationAccountI, LocalAccountMethods} from '@agoric/orchestration'; * @import {RecorderKit, MakeRecorderKit} from '@agoric/zoe/src/contractSupport/recorder.js'. * @import {Zone} from '@agoric/zone'; * @import {Remote} from '@agoric/internal'; @@ -613,14 +613,14 @@ export const prepareLocalOrchestrationAccountKit = ( * updater will get a special notification that the account is being * transferred. */ - /** @type {HostOf} */ + /** @type {HostOf} */ deposit(payment) { return watch( E(this.state.account).deposit(payment), this.facets.returnVoidWatcher, ); }, - /** @type {HostOf} */ + /** @type {HostOf} */ withdraw(amount) { return watch(E(this.state.account).withdraw(amount)); }, @@ -733,7 +733,7 @@ export const prepareLocalOrchestrationAccountKit = ( matchFirstPacket(patternV) { return watch(E(this.state.packetTools).matchFirstPacket(patternV)); }, - /** @type {HostOf} */ + /** @type {HostOf} */ monitorTransfers(tap) { return watch(E(this.state.packetTools).monitorTransfers(tap)); }, diff --git a/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.md b/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.md index 38ac9729bdd..d168ee29da0 100644 --- a/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.md +++ b/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.md @@ -19,16 +19,30 @@ Generated by [AVA](https://avajs.dev). FunctionUnwrapper_singleton: 'Alleged: FunctionUnwrapper', LogStore_kindHandle: 'Alleged: kind', StateUnwrapper_kindHandle: 'Alleged: kind', - asyncFuncEagerWakers: [], + asyncFuncEagerWakers: [ + Object @Alleged: asyncFlow flow {}, + ], asyncFuncFailures: {}, - flowForOutcomeVow: {}, + flowForOutcomeVow: { + 'Alleged: VowInternalsKit vowV0': 'Alleged: asyncFlow flow', + }, unwrapMap: 'Alleged: weakMapStore', }, chainHub: { ChainHub_kindHandle: 'Alleged: kind', ChainHub_singleton: 'Alleged: ChainHub', brandDenom: {}, - chainInfos: {}, + chainInfos: { + agoric: { + chainId: 'agoric-3', + icqEnabled: false, + stakingTokens: [ + { + denom: 'ubld', + }, + ], + }, + }, connectionInfos: {}, denom: {}, lookupChainInfo_kindHandle: 'Alleged: kind', @@ -40,13 +54,15 @@ Generated by [AVA](https://avajs.dev). 'ChainHub Admin_singleton': 'Alleged: ChainHub Admin', 'Send PF_kindHandle': 'Alleged: kind', 'Send PF_singleton': 'Alleged: Send PF', + localAccount: 'Vow', orchestration: { + makeLocalAccount: { + asyncFlow_kindHandle: 'Alleged: kind', + }, sendIt: { asyncFlow_kindHandle: 'Alleged: kind', endowments: { 0: { - contractState_kindHandle: 'Alleged: kind', - contractState_singleton: 'Alleged: contractState', log_kindHandle: 'Alleged: kind', log_singleton: 'Alleged: log', zoeTools: { diff --git a/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.snap b/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.snap index 897c3c4e64b..70f6bb08d28 100644 Binary files a/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.snap and b/packages/orchestration/test/examples/snapshots/send-anywhere.test.ts.snap differ diff --git a/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.md b/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.md index 8d65dc66fcb..2c914a1bdf9 100644 --- a/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.md +++ b/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.md @@ -105,13 +105,12 @@ Generated by [AVA](https://avajs.dev). 'ChainHub Admin_singleton': 'Alleged: ChainHub Admin', CombinedInvitationMakers_kindHandle: 'Alleged: kind', StakingCombinationsInvitationMakers_kindHandle: 'Alleged: kind', + localAccount: 'Vow', orchestration: { depositAndDelegate: { asyncFlow_kindHandle: 'Alleged: kind', endowments: { 0: { - contractState_kindHandle: 'Alleged: kind', - contractState_singleton: 'Alleged: contractState', flows: { depositAndDelegate_kindHandle: 'Alleged: kind', depositAndDelegate_singleton: 'Alleged: depositAndDelegate', @@ -137,8 +136,6 @@ Generated by [AVA](https://avajs.dev). asyncFlow_kindHandle: 'Alleged: kind', endowments: { 0: { - contractState_kindHandle: 'Alleged: kind', - contractState_singleton: 'Alleged: contractState', flows: { depositAndDelegate_kindHandle: 'Alleged: kind', depositAndDelegate_singleton: 'Alleged: depositAndDelegate', @@ -160,12 +157,13 @@ Generated by [AVA](https://avajs.dev). }, }, }, + makeLocalAccount: { + asyncFlow_kindHandle: 'Alleged: kind', + }, undelegateAndTransfer: { asyncFlow_kindHandle: 'Alleged: kind', endowments: { 0: { - contractState_kindHandle: 'Alleged: kind', - contractState_singleton: 'Alleged: contractState', flows: { depositAndDelegate_kindHandle: 'Alleged: kind', depositAndDelegate_singleton: 'Alleged: depositAndDelegate', diff --git a/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.snap b/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.snap index 45b56186c15..9af887fc4b1 100644 Binary files a/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.snap and b/packages/orchestration/test/examples/snapshots/staking-combinations.test.ts.snap differ diff --git a/packages/orchestration/test/fixtures/zoe-tools.contract.js b/packages/orchestration/test/fixtures/zoe-tools.contract.js index 4e501563f40..0c60b42c54e 100644 --- a/packages/orchestration/test/fixtures/zoe-tools.contract.js +++ b/packages/orchestration/test/fixtures/zoe-tools.contract.js @@ -3,13 +3,13 @@ * around `zoeTools.localTransfer` and `zoeTools.withdrawToSeat` */ -import { makeSharedStateRecord } from '@agoric/async-flow'; import { InvitationShape } from '@agoric/zoe/src/typeGuards.js'; import { E } from '@endo/far'; import { M } from '@endo/patterns'; import { withOrchestration } from '../../src/utils/start-helper.js'; import { prepareChainHubAdmin } from '../../src/exos/chain-hub-admin.js'; import * as flows from './zoe-tools.flows.js'; +import * as sharedFlows from '../../src/examples/shared.flows.js'; import fetchedChainInfo from '../../src/fetched-chain-info.js'; const { values } = Object; @@ -49,16 +49,24 @@ const contract = async ( zone, { chainHub, orchestrateAll, zoeTools }, ) => { - const contractState = makeSharedStateRecord( - /** @type {{ account: OrchestrationAccount | undefined }} */ { - localAccount: undefined, - }, - ); - const creatorFacet = prepareChainHubAdmin(zone, chainHub); + const { makeLocalAccount } = orchestrateAll(sharedFlows, {}); + /** + * Setup a shared local account for use in async-flow functions. Typically, + * exo initState functions need to resolve synchronously, but `makeOnce` + * allows us to provide a Promise. When using this inside a flow, we must + * await it to ensure the account is available for use. + * + * @type {any} sharedLocalAccountP expects a Promise but this is a vow + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccountP = zone.makeOnce('localAccount', () => + makeLocalAccount(), + ); + const orchFns = orchestrateAll(flows, { - contractState, + sharedLocalAccountP, zoeTools, }); diff --git a/packages/orchestration/test/fixtures/zoe-tools.flows.js b/packages/orchestration/test/fixtures/zoe-tools.flows.js index 15338b63d2a..4994984bafc 100644 --- a/packages/orchestration/test/fixtures/zoe-tools.flows.js +++ b/packages/orchestration/test/fixtures/zoe-tools.flows.js @@ -11,6 +11,8 @@ const { values } = Object; /** * @import {GuestInterface} from '@agoric/async-flow'; + * @import {AtomicProvider} from '@agoric/store/src/stores/store-utils.js'; + * @import {LocalOrchestrationAccountKit} from '../../src/exos/local-orchestration-account.js'; * @import {Orchestrator, LocalAccountMethods, OrchestrationAccountI, OrchestrationFlow, ChainAddress} from '@agoric/orchestration'; * @import {ZoeTools} from '../../src/utils/zoe-tools.js'; */ @@ -23,14 +25,14 @@ const { values } = Object; * @satisfies {OrchestrationFlow} * @param {Orchestrator} orch * @param {object} ctx - * @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState + * @param {Promise>} ctx.sharedLocalAccountP * @param {GuestInterface} ctx.zoeTools * @param {ZCFSeat} seat * @param {{ destAddr: ChainAddress }} offerArgs */ export const depositSend = async ( orch, - { contractState, zoeTools: { localTransfer, withdrawToSeat } }, + { sharedLocalAccountP, zoeTools: { localTransfer, withdrawToSeat } }, seat, offerArgs, ) => { @@ -40,18 +42,17 @@ export const depositSend = async ( const { give } = seat.getProposal(); - await null; - if (!contractState.localAccount) { - const agoricChain = await orch.getChain('agoric'); - contractState.localAccount = await agoricChain.makeAccount(); - } - - await localTransfer(seat, contractState.localAccount, give); + /** + * @type {any} XXX methods returning vows + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccount = await sharedLocalAccountP; + await localTransfer(seat, sharedLocalAccount, give); try { - await contractState.localAccount.sendAll(destAddr, values(give)); + await sharedLocalAccount.sendAll(destAddr, values(give)); } catch (error) { - await withdrawToSeat(contractState.localAccount, seat, give); + await withdrawToSeat(sharedLocalAccount, seat, give); const errMsg = makeError(`SendAll failed ${q(error)}`); seat.exit(errMsg); throw errMsg; @@ -67,25 +68,24 @@ harden(depositSend); * @satisfies {OrchestrationFlow} * @param {Orchestrator} orch * @param {object} ctx - * @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState + * @param {Promise>} ctx.sharedLocalAccountP * @param {GuestInterface} ctx.zoeTools * @param {ZCFSeat} seat */ export const deposit = async ( orch, - { contractState, zoeTools: { localTransfer } }, + { sharedLocalAccountP, zoeTools: { localTransfer } }, seat, ) => { const { give } = seat.getProposal(); - await null; - if (!contractState.localAccount) { - const agoricChain = await orch.getChain('agoric'); - contractState.localAccount = await agoricChain.makeAccount(); - } - + /** + * @type {any} XXX methods returning vows + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccount = await sharedLocalAccountP; try { - await localTransfer(seat, contractState.localAccount, give); + await localTransfer(seat, sharedLocalAccount, give); } catch (e) { seat.exit(e); throw e; @@ -100,25 +100,25 @@ harden(deposit); * @satisfies {OrchestrationFlow} * @param {Orchestrator} orch * @param {object} ctx - * @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState + * @param {Promise>} ctx.sharedLocalAccountP * @param {GuestInterface} ctx.zoeTools * @param {ZCFSeat} seat */ export const withdraw = async ( orch, - { contractState, zoeTools: { withdrawToSeat } }, + { sharedLocalAccountP, zoeTools: { withdrawToSeat } }, seat, ) => { const { want } = seat.getProposal(); - await null; - if (!contractState.localAccount) { - const agoricChain = await orch.getChain('agoric'); - contractState.localAccount = await agoricChain.makeAccount(); - } + /** + * @type {any} XXX methods returning vows + * https://github.com/Agoric/agoric-sdk/issues/9822 + */ + const sharedLocalAccount = await sharedLocalAccountP; try { - await withdrawToSeat(contractState.localAccount, seat, want); + await withdrawToSeat(sharedLocalAccount, seat, want); } catch (e) { seat.exit(e); throw e;