-
Notifications
You must be signed in to change notification settings - Fork 207
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
96 changes: 96 additions & 0 deletions
96
packages/orchestration/src/examples/continuing-invitation.contract.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/** | ||
* @file This contract demonstrates the continuing invitation pattern with async | ||
* flows. | ||
* | ||
* The primary offer result is a power for invitation makers that can perform | ||
* actions with an ICA account. | ||
*/ | ||
import { VowShape } from '@agoric/vow'; | ||
import { M } from '@endo/patterns'; | ||
import { prepareCombineInvitationMakers } from '../exos/combine-invitation-makers.js'; | ||
import { withOrchestration } from '../utils/start-helper.js'; | ||
import * as flows from './continuing-invitation.flows.js'; | ||
|
||
/** | ||
* @import {Delegation} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/staking.js'; | ||
* @import {TimerService} from '@agoric/time'; | ||
* @import {LocalChain} from '@agoric/vats/src/localchain.js'; | ||
* @import {NameHub} from '@agoric/vats'; | ||
* @import {Remote} from '@agoric/internal'; | ||
* @import {Zone} from '@agoric/zone'; | ||
* @import {CosmosInterchainService} from '../exos/cosmos-interchain-service.js'; | ||
* @import {OrchestrationTools} from '../utils/start-helper.js'; | ||
* @import {CosmosOrchestrationAccount} from '../exos/cosmos-orchestration-account.js'; | ||
*/ | ||
|
||
/** | ||
* Orchestration contract to be wrapped by withOrchestration for Zoe. | ||
* | ||
* @param {ZCF} zcf | ||
* @param {{ | ||
* agoricNames: Remote<NameHub>; | ||
* localchain: Remote<LocalChain>; | ||
* orchestrationService: Remote<CosmosInterchainService>; | ||
* storageNode: Remote<StorageNode>; | ||
* marshaller: Marshaller; | ||
* timerService: Remote<TimerService>; | ||
* }} privateArgs | ||
* @param {Zone} zone | ||
* @param {OrchestrationTools} tools | ||
*/ | ||
const contract = async (zcf, privateArgs, zone, { orchestrateAll }) => { | ||
const guards = { | ||
UndelegateAndTransfer: M.call(M.array()).returns(VowShape), | ||
}; | ||
const makeExtraInvitationMaker = zone.exoClass( | ||
'ContinuingInvitationExampleInvitationMakers', | ||
M.interface('', guards), | ||
/** @param {CosmosOrchestrationAccount} account */ | ||
account => { | ||
return { account }; | ||
}, | ||
{ | ||
/** | ||
* @param {Omit<Delegation, 'delegatorAddress'>[]} delegations | ||
*/ | ||
UndelegateAndTransfer(delegations) { | ||
const { account } = this.state; | ||
// eslint-disable-next-line no-use-before-define -- defined by orchestrateAll, necessarily after this | ||
return orchFns.undelegateAndTransfer(account, delegations); | ||
}, | ||
}, | ||
); | ||
|
||
const makeCombineInvitationMakers = prepareCombineInvitationMakers( | ||
zone, | ||
guards, | ||
); | ||
|
||
const orchFns = orchestrateAll(flows, { | ||
makeCombineInvitationMakers, | ||
makeExtraInvitationMaker, | ||
flows, | ||
zcf, | ||
}); | ||
|
||
const publicFacet = zone.exo('publicFacet', undefined, { | ||
makeAccount() { | ||
return zcf.makeInvitation( | ||
orchFns.makeAccount, | ||
'Make an ICA account', | ||
undefined, | ||
harden({ | ||
// Nothing to give; the funds are deposited offline | ||
give: {}, | ||
want: {}, // UNTIL https://github.com/Agoric/agoric-sdk/issues/2230 | ||
exit: M.any(), | ||
}), | ||
); | ||
}, | ||
}); | ||
|
||
return harden({ publicFacet }); | ||
}; | ||
|
||
export const start = withOrchestration(contract); | ||
harden(start); |
61 changes: 61 additions & 0 deletions
61
packages/orchestration/src/examples/continuing-invitation.flows.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* @import {Orchestrator, OrchestrationFlow, OrchestrationAccount, OrchestrationAccountI, StakingAccountActions} from '../types.js' | ||
* @import {ContinuingOfferResult, InvitationMakers} from '@agoric/smart-wallet/src/types.js'; | ||
* @import {MakeCombineInvitationMakers} from '../exos/combine-invitation-makers.js'; | ||
* @import {Delegation} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/staking.js'; | ||
*/ | ||
|
||
/** | ||
* @satisfies {OrchestrationFlow} | ||
* @param {Orchestrator} orch | ||
* @param {{ | ||
* flows: { undelegateAndTransfer: Function }; | ||
* makeCombineInvitationMakers: MakeCombineInvitationMakers; | ||
* makeExtraInvitationMaker: any; | ||
* zcf: ZCF; | ||
* }} ctx | ||
* @param {ZCFSeat} _seat | ||
* @param {{ chainName: string }} offerArgs | ||
* @returns {Promise<ContinuingOfferResult>} | ||
*/ | ||
export const makeAccount = async (orch, ctx, _seat, { chainName }) => { | ||
const chain = await orch.getChain(chainName); | ||
const account = await chain.makeAccount(); | ||
|
||
const extraMakers = ctx.makeExtraInvitationMaker(account); | ||
|
||
/** @type {ContinuingOfferResult} */ | ||
const result = await account.asContinuingOffer(); | ||
|
||
return { | ||
...result, | ||
// @ts-expect-error makeCombineInvitationMakers returns Farable | ||
invitationMakers: ctx.makeCombineInvitationMakers( | ||
extraMakers, | ||
result.invitationMakers, | ||
), | ||
}; | ||
}; | ||
harden(makeAccount); | ||
|
||
// FIXME 'account' not Passable? | ||
/** | ||
* @satisfies {OrchestrationFlow} | ||
* @param {Orchestrator} orch | ||
* @param {object} ctx | ||
* @param {OrchestrationAccountI & StakingAccountActions} account | ||
* @param {Omit<Delegation, 'delegatorAddress'>[]} delegations | ||
* @returns {Promise<string>} | ||
*/ | ||
export const undelegateAndTransfer = async ( | ||
orch, | ||
ctx, | ||
account, | ||
delegations, | ||
) => { | ||
// FIXME undelegate something | ||
await account.undelegate(delegations); | ||
// FIXME then transfer something | ||
return 'guest undelegateAndTransfer complete'; | ||
}; | ||
harden(undelegateAndTransfer); |
92 changes: 92 additions & 0 deletions
92
packages/orchestration/test/examples/continuing-invitation.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; | ||
|
||
import { inspectMapStore } from '@agoric/internal/src/testing-utils.js'; | ||
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js'; | ||
import { E } from '@endo/far'; | ||
import path from 'path'; | ||
import { protoMsgMocks, UNBOND_PERIOD_SECONDS } from '../ibc-mocks.js'; | ||
import { commonSetup } from '../supports.js'; | ||
|
||
const dirname = path.dirname(new URL(import.meta.url).pathname); | ||
|
||
const contractFile = `${dirname}/../../src/examples/continuing-invitation.contract.js`; | ||
type StartFn = | ||
typeof import('@agoric/orchestration/src/examples/continuing-invitation.contract.js').start; | ||
|
||
test('start', async t => { | ||
const { | ||
bootstrap: { timer, vowTools: vt }, | ||
brands: { ist }, | ||
mocks: { ibcBridge }, | ||
commonPrivateArgs, | ||
} = await commonSetup(t); | ||
|
||
let contractBaggage; | ||
const { zoe, bundleAndInstall } = await setUpZoeForTest({ | ||
setJig: ({ baggage }) => { | ||
contractBaggage = baggage; | ||
}, | ||
}); | ||
const installation: Installation<StartFn> = | ||
await bundleAndInstall(contractFile); | ||
|
||
const { publicFacet } = await E(zoe).startInstance( | ||
installation, | ||
{ Stable: ist.issuer }, | ||
{}, | ||
commonPrivateArgs, | ||
); | ||
|
||
const inv = E(publicFacet).makeAccount(); | ||
|
||
t.is( | ||
(await E(zoe).getInvitationDetails(inv)).description, | ||
'Make an ICA account', | ||
); | ||
|
||
const userSeat = await E(zoe).offer( | ||
inv, | ||
{}, | ||
{}, | ||
{ | ||
chainName: 'osmosis', | ||
}, | ||
); | ||
|
||
const result = await vt.when(E(userSeat).getOfferResult()); | ||
t.like(result, { | ||
publicSubscribers: { | ||
account: { | ||
description: 'Staking Account holder status', | ||
storagePath: 'mockChainStorageRoot.cosmos1test', | ||
}, | ||
}, | ||
}); | ||
|
||
// Here the account would get funded through Cosmos native operations. | ||
|
||
// Delegate the funds | ||
await E(result.invitationMakers).Delegate( | ||
{ value: '10', encoding: 'bech32', chainId: 'osmosis' }, | ||
{ | ||
denom: 'osmo', | ||
value: 10n, | ||
}, | ||
); | ||
|
||
// Undelegate the funds using the guest flow | ||
ibcBridge.addMockAck( | ||
// observed in console | ||
'eyJ0eXBlIjoxLCJkYXRhIjoiQ2xnS0pTOWpiM050YjNNdWMzUmhhMmx1Wnk1Mk1XSmxkR0V4TGsxeloxVnVaR1ZzWldkaGRHVVNMd29MWTI5emJXOXpNWFJsYzNRU0VtTnZjMjF2YzNaaGJHOXdaWEl4ZEdWemRCb01DZ1YxYjNOdGJ4SURNVEF3IiwibWVtbyI6IiJ9', | ||
protoMsgMocks.undelegate.ack, | ||
); | ||
const undelegateVow = await E(result.invitationMakers).UndelegateAndTransfer([ | ||
{ validatorAddress: 'cosmosvaloper1test', shares: '100' }, | ||
]); | ||
timer.advanceBy(UNBOND_PERIOD_SECONDS * 1000n); | ||
t.is(await vt.when(undelegateVow), 'guest undelegateAndTransfer complete'); | ||
|
||
// snapshot the resulting contract baggage | ||
const tree = inspectMapStore(contractBaggage); | ||
t.snapshot(tree, 'contract baggage after start'); | ||
}); |
85 changes: 85 additions & 0 deletions
85
packages/orchestration/test/examples/snapshots/continuing-invitation.test.ts.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Snapshot report for `test/examples/continuing-invitation.test.ts` | ||
|
||
The actual snapshot is saved in `continuing-invitation.test.ts.snap`. | ||
|
||
Generated by [AVA](https://avajs.dev). | ||
|
||
## start | ||
|
||
> contract baggage after start | ||
{ | ||
'Durable Publish Kit_kindHandle': 'Alleged: kind', | ||
Recorder_kindHandle: 'Alleged: kind', | ||
asyncFlow: { | ||
AdminAsyncFlow_kindHandle: 'Alleged: kind', | ||
AdminAsyncFlow_singleton: 'Alleged: AdminAsyncFlow', | ||
Bijection_kindHandle: 'Alleged: kind', | ||
FunctionUnwrapper_kindHandle: 'Alleged: kind', | ||
FunctionUnwrapper_singleton: 'Alleged: FunctionUnwrapper', | ||
LogStore_kindHandle: 'Alleged: kind', | ||
StateUnwrapper_kindHandle: 'Alleged: kind', | ||
asyncFuncEagerWakers: [], | ||
asyncFuncFailures: {}, | ||
flowForOutcomeVow: {}, | ||
unwrapMap: 'Alleged: weakMapStore', | ||
}, | ||
contract: { | ||
CombinedInvitationMakers_kindHandle: 'Alleged: kind', | ||
ContinuingInvitationExampleInvitationMakers_kindHandle: 'Alleged: kind', | ||
orchestration: { | ||
makeAccount: { | ||
asyncFlow_kindHandle: 'Alleged: kind', | ||
endowments: { | ||
0: { | ||
flows_kindHandle: 'Alleged: kind', | ||
flows_singleton: 'Alleged: flows', | ||
makeCombineInvitationMakers_kindHandle: 'Alleged: kind', | ||
makeCombineInvitationMakers_singleton: 'Alleged: makeCombineInvitationMakers', | ||
makeExtraInvitationMaker_kindHandle: 'Alleged: kind', | ||
makeExtraInvitationMaker_singleton: 'Alleged: makeExtraInvitationMaker', | ||
}, | ||
}, | ||
}, | ||
undelegateAndTransfer: { | ||
asyncFlow_kindHandle: 'Alleged: kind', | ||
endowments: { | ||
0: { | ||
flows_kindHandle: 'Alleged: kind', | ||
flows_singleton: 'Alleged: flows', | ||
makeCombineInvitationMakers_kindHandle: 'Alleged: kind', | ||
makeCombineInvitationMakers_singleton: 'Alleged: makeCombineInvitationMakers', | ||
makeExtraInvitationMaker_kindHandle: 'Alleged: kind', | ||
makeExtraInvitationMaker_singleton: 'Alleged: makeExtraInvitationMaker', | ||
}, | ||
}, | ||
}, | ||
}, | ||
publicFacet_kindHandle: 'Alleged: kind', | ||
publicFacet_singleton: 'Alleged: publicFacet', | ||
}, | ||
orchestration: { | ||
'Cosmos Orchestration Account Holder_kindHandle': 'Alleged: kind', | ||
'Local Orchestration Account Kit_kindHandle': 'Alleged: kind', | ||
LocalChainFacade_kindHandle: 'Alleged: kind', | ||
Orchestrator_kindHandle: 'Alleged: kind', | ||
RemoteChainFacade_kindHandle: 'Alleged: kind', | ||
chainName: { | ||
osmosis: 'Alleged: RemoteChainFacade public', | ||
}, | ||
ibcTools: { | ||
IBCTransferSenderKit_kindHandle: 'Alleged: kind', | ||
ibcResultWatcher_kindHandle: 'Alleged: kind', | ||
ibcResultWatcher_singleton: 'Alleged: ibcResultWatcher', | ||
}, | ||
packetTools: { | ||
PacketToolsKit_kindHandle: 'Alleged: kind', | ||
}, | ||
}, | ||
vows: { | ||
PromiseWatcher_kindHandle: 'Alleged: kind', | ||
VowInternalsKit_kindHandle: 'Alleged: kind', | ||
WatchUtils_kindHandle: 'Alleged: kind', | ||
}, | ||
zoe: {}, | ||
} |
Binary file added
BIN
+1.21 KB
packages/orchestration/test/examples/snapshots/continuing-invitation.test.ts.snap
Binary file not shown.