Skip to content

Commit

Permalink
chore: sharedLocalAccount pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg committed Oct 1, 2024
1 parent 395a465 commit 195c1f5
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 88 deletions.
18 changes: 9 additions & 9 deletions packages/orchestration/src/examples/send-anywhere.contract.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
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 { 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';
Expand Down Expand Up @@ -38,23 +37,24 @@ export const contract = async (
zone,
{ chainHub, orchestrateAll, vowTools, zoeTools },
) => {
const contractState = makeSharedStateRecord(
/** @type {{ account: OrchestrationAccount<any> | undefined }} */ {
localAccount: undefined,
},
);

const creatorFacet = prepareChainHubAdmin(zone, chainHub);

// UNTIL https://github.com/Agoric/agoric-sdk/issues/9066
const logNode = E(privateArgs.storageNode).makeChildNode('log');
/** @type {(msg: string) => Vow<void>} */
const log = msg => vowTools.watch(E(logNode).setValue(msg));

const { makeLocalAccount } = orchestrateAll(sharedFlows, {});
// XXX sharedLocalAccountP expects a Promise but this is a vow https://github.com/Agoric/agoric-sdk/issues/9822
/** @type {unknown} */
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,
});

Expand Down
23 changes: 12 additions & 11 deletions packages/orchestration/src/examples/send-anywhere.flows.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -18,15 +19,15 @@ const { entries } = Object;
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @param {object} ctx
* @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState
* @param {Promise<GuestInterface<LocalOrchestrationAccountKit['holder']>>} ctx.sharedLocalAccountP
* @param {GuestInterface<ZoeTools>} ctx.zoeTools
* @param {GuestOf<(msg: string) => Vow<void>>} ctx.log
* @param {ZCFSeat} seat
* @param {{ chainName: string; destAddr: string }} offerArgs
*/
export const sendIt = async (
orch,
{ contractState, log, zoeTools: { localTransfer, withdrawToSeat } },
{ sharedLocalAccountP, log, zoeTools: { localTransfer, withdrawToSeat } },
seat,
offerArgs,
) => {
Expand All @@ -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',
Expand All @@ -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);
Expand Down
17 changes: 17 additions & 0 deletions packages/orchestration/src/examples/shared.flows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @import {Orchestrator, OrchestrationFlow, LocalAccountMethods} from '../types.js';
*/

// in guest file (the orchestration functions)
// the second argument is all the endowments provided

/**
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @returns {Promise<LocalAccountMethods>}
*/
export const makeLocalAccount = async orch => {
const agoricChain = await orch.getChain('agoric');
return agoricChain.makeAccount();
};
harden(makeLocalAccount);
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
* 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';
import { CosmosOrchestrationInvitationMakersI } from '../exos/cosmos-orchestration-account.js';
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';

/**
Expand Down Expand Up @@ -46,16 +46,6 @@ const contract = async (
zone,
{ orchestrateAll, zoeTools, chainHub },
) => {
const contractState = makeSharedStateRecord(
/**
* @type {{
* account: (OrchestrationAccount<any> & LocalAccountMethods) | undefined;
* }}
*/ {
localAccount: undefined,
},
);

const StakingCombinationsInvitationMakersI = M.interface(
'StakingCombinationsInvitationMakersI',
{
Expand Down Expand Up @@ -128,8 +118,15 @@ const contract = async (
StakingCombinationsInvitationMakersI,
);

const { makeLocalAccount } = orchestrateAll(sharedFlows, {});
// XXX sharedLocalAccountP expects a Promise but this is a vow https://github.com/Agoric/agoric-sdk/issues/9822
/** @type {any} */
const sharedLocalAccountP = zone.makeOnce('localAccount', () =>
makeLocalAccount(),
);

const orchFns = orchestrateAll(flows, {
contractState,
sharedLocalAccountP,
makeCombineInvitationMakers,
makeExtraInvitationMaker,
flows,
Expand Down
21 changes: 12 additions & 9 deletions packages/orchestration/src/examples/staking-combinations.flows.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -47,7 +48,7 @@ harden(makeAccount);
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @param {object} ctx
* @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState
* @param {Promise<GuestInterface<LocalOrchestrationAccountKit['holder']>>} ctx.sharedLocalAccountP
* @param {GuestInterface<ZoeTools>} ctx.zoeTools
* @param {GuestInterface<CosmosOrchestrationAccount>} account
* @param {ZCFSeat} seat
Expand All @@ -56,26 +57,28 @@ harden(makeAccount);
*/
export const depositAndDelegate = async (
orch,
{ contractState, zoeTools },
{ sharedLocalAccountP, zoeTools },
account,
seat,
validator,
) => {
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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: {
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand Down
Binary file not shown.
17 changes: 9 additions & 8 deletions packages/orchestration/test/fixtures/zoe-tools.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -49,16 +49,17 @@ const contract = async (
zone,
{ chainHub, orchestrateAll, zoeTools },
) => {
const contractState = makeSharedStateRecord(
/** @type {{ account: OrchestrationAccount<any> | undefined }} */ {
localAccount: undefined,
},
);

const creatorFacet = prepareChainHubAdmin(zone, chainHub);

const { makeLocalAccount } = orchestrateAll(sharedFlows, {});
// XXX sharedLocalAccountP expects a Promise but this is a vow https://github.com/Agoric/agoric-sdk/issues/9822
/** @type {unknown} */
const sharedLocalAccountP = zone.makeOnce('localAccount', () =>
makeLocalAccount(),
);

const orchFns = orchestrateAll(flows, {
contractState,
sharedLocalAccountP,
zoeTools,
});

Expand Down
Loading

0 comments on commit 195c1f5

Please sign in to comment.