-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: kitchen sink fixture for async-flow continuing offers
- Loading branch information
1 parent
ca61a90
commit f1f07bb
Showing
6 changed files
with
364 additions
and
1 deletion.
There are no files selected for viewing
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
25 changes: 25 additions & 0 deletions
25
packages/builders/scripts/orchestration/init-kitchen-sink.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,25 @@ | ||
import { makeHelpers } from '@agoric/deploy-script-support'; | ||
|
||
/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */ | ||
export const defaultProposalBuilder = async ({ publishRef, install }) => { | ||
return harden({ | ||
sourceSpec: '@agoric/orchestration/src/proposals/start-kitchen-sink.js', | ||
getManifestCall: [ | ||
'getManifestForContract', | ||
{ | ||
installKeys: { | ||
kitchenSink: publishRef( | ||
install( | ||
'@agoric/orchestration/src/examples/kitchen-sink.contract.js', | ||
), | ||
), | ||
}, | ||
}, | ||
], | ||
}); | ||
}; | ||
|
||
export default async (homeP, endowments) => { | ||
const { writeCoreEval } = await makeHelpers(homeP, endowments); | ||
await writeCoreEval('start-kitchen-sink', defaultProposalBuilder); | ||
}; |
103 changes: 103 additions & 0 deletions
103
packages/orchestration/src/examples/kitchen-sink.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,103 @@ | ||
/** | ||
* @file Primarily a testing fixture, but also serves as an example of how to | ||
* leverage basic functionality of the Orchestration API with async-flow. | ||
*/ | ||
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js'; | ||
import { M, mustMatch } from '@endo/patterns'; | ||
import { provideOrchestration } from '../utils/start-helper.js'; | ||
|
||
/** | ||
* @import {Baggage} from '@agoric/vat-data'; | ||
* @import {Orchestrator} from '@agoric/orchestration'; | ||
* @import {OrchestrationPowers} from '../utils/start-helper.js'; | ||
*/ | ||
|
||
/** | ||
* Create an account on the local chain and return a continuing offer with | ||
* invitations for Delegate, WithdrawRewards, Transfer, etc. | ||
* | ||
* @param {Orchestrator} orch | ||
* @param {undefined} _ctx | ||
* @param {ZCFSeat} seat | ||
*/ | ||
const makeLocalOrchAcctHandler = async (orch, _ctx, seat) => { | ||
seat.exit(); // no funds exchanged | ||
const agoric = await orch.getChain('agoric'); | ||
const localAccount = await agoric.makeAccount(); | ||
// @ts-expect-error asContinuingOffer does not exist on OrchestrationAccountI | ||
return localAccount.asContinuingOffer(); | ||
}; | ||
|
||
/** | ||
* Create an account on a Cosmos chain and return a continuing offer with | ||
* invitations makers for Delegate, WithdrawRewards, Transfer, etc. | ||
* | ||
* @param {Orchestrator} orch | ||
* @param {undefined} _ctx | ||
* @param {ZCFSeat} seat | ||
* @param {{ chainName: string }} offerArgs | ||
*/ | ||
const makeCosmosOrchAcctHandler = async (orch, _ctx, seat, { chainName }) => { | ||
seat.exit(); // no funds exchanged | ||
mustMatch(chainName, M.string()); | ||
const remoteChain = await orch.getChain(chainName); | ||
const cosmosAccount = await remoteChain.makeAccount(); | ||
// @ts-expect-error asContinuingOffer does not exist on OrchestrationAccountI | ||
return cosmosAccount.asContinuingOffer(); | ||
}; | ||
|
||
/** | ||
* @param {ZCF} zcf | ||
* @param {OrchestrationPowers & { | ||
* marshaller: Marshaller; | ||
* }} privateArgs | ||
* @param {Baggage} baggage | ||
*/ | ||
export const start = async (zcf, privateArgs, baggage) => { | ||
const { orchestrate, zone } = provideOrchestration( | ||
zcf, | ||
baggage, | ||
privateArgs, | ||
privateArgs.marshaller, | ||
); | ||
|
||
/** @type {OfferHandler} */ | ||
const makeLocalOrchAccount = orchestrate( | ||
'makeLocalAccount', | ||
undefined, | ||
makeLocalOrchAcctHandler, | ||
); | ||
|
||
/** @type {OfferHandler} */ | ||
const makeCosmosOrchAccount = orchestrate( | ||
'makeCosmosICAAccount', | ||
undefined, | ||
makeCosmosOrchAcctHandler, | ||
); | ||
|
||
const publicFacet = zone.exo( | ||
'Kitchen Sink Public Facet', | ||
M.interface('Kitchen Sink PF', { | ||
makeLocalOrchAcctInvitation: M.callWhen().returns(InvitationShape), | ||
makeCosmosOrchAcctInvitation: M.callWhen().returns(InvitationShape), | ||
}), | ||
{ | ||
makeLocalOrchAcctInvitation() { | ||
return zcf.makeInvitation( | ||
makeLocalOrchAccount, | ||
'Make Local Orchestration Account', | ||
); | ||
}, | ||
makeCosmosOrchAcctInvitation() { | ||
return zcf.makeInvitation( | ||
makeCosmosOrchAccount, | ||
'Make Cosmos Orchestration Account', | ||
); | ||
}, | ||
}, | ||
); | ||
|
||
return { publicFacet }; | ||
}; | ||
|
||
/** @typedef {typeof start} KitchenSinkSF */ |
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
97 changes: 97 additions & 0 deletions
97
packages/orchestration/src/proposals/start-kitchen-sink.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,97 @@ | ||
/** | ||
* @file A proposal to start the kitchen sink contract. | ||
*/ | ||
import { makeTracer } from '@agoric/internal'; | ||
import { makeStorageNodeChild } from '@agoric/internal/src/lib-chainStorage.js'; | ||
import { E } from '@endo/far'; | ||
|
||
/** | ||
* @import {KitchenSinkSF} from '../examples/kitchen-sink.contract.js'; | ||
*/ | ||
|
||
const trace = makeTracer('StartKitchenSink', true); | ||
const contractName = 'kitchenSink'; | ||
|
||
/** | ||
* See `@agoric/builders/builders/scripts/orchestration/init-kitchen-sink.js` | ||
* for the accompanying proposal builder. Run `agoric run | ||
* packages/builders/scripts/orchestration/init-kitchen-sink.js` to build the | ||
* contract and proposal files. | ||
* | ||
* @param {BootstrapPowers} powers | ||
*/ | ||
export const startKitchenSink = async ({ | ||
consume: { | ||
agoricNames, | ||
board, | ||
chainStorage, | ||
chainTimerService, | ||
cosmosInterchainService, | ||
localchain, | ||
startUpgradable, | ||
}, | ||
installation: { | ||
// @ts-expect-error not a WellKnownName | ||
consume: { [contractName]: installation }, | ||
}, | ||
instance: { | ||
// @ts-expect-error not a WellKnownName | ||
produce: { [contractName]: produceInstance }, | ||
}, | ||
}) => { | ||
trace(`start ${contractName}`); | ||
await null; | ||
|
||
const storageNode = await makeStorageNodeChild(chainStorage, contractName); | ||
const marshaller = await E(board).getPublishingMarshaller(); | ||
|
||
/** @type {StartUpgradableOpts<KitchenSinkSF>} */ | ||
const startOpts = { | ||
label: 'kitchenSink', | ||
installation, | ||
terms: undefined, | ||
privateArgs: { | ||
agoricNames: await agoricNames, | ||
orchestrationService: await cosmosInterchainService, | ||
localchain: await localchain, | ||
storageNode, | ||
marshaller, | ||
timerService: await chainTimerService, | ||
}, | ||
}; | ||
|
||
const { instance } = await E(startUpgradable)(startOpts); | ||
produceInstance.resolve(instance); | ||
}; | ||
harden(startKitchenSink); | ||
|
||
export const getManifestForContract = ( | ||
{ restoreRef }, | ||
{ installKeys, ...options }, | ||
) => { | ||
return { | ||
manifest: { | ||
[startKitchenSink.name]: { | ||
consume: { | ||
agoricNames: true, | ||
board: true, | ||
chainStorage: true, | ||
chainTimerService: true, | ||
cosmosInterchainService: true, | ||
localchain: true, | ||
startUpgradable: true, | ||
}, | ||
installation: { | ||
consume: { [contractName]: true }, | ||
}, | ||
instance: { | ||
produce: { [contractName]: true }, | ||
}, | ||
}, | ||
}, | ||
installations: { | ||
[contractName]: restoreRef(installKeys[contractName]), | ||
}, | ||
options, | ||
}; | ||
}; |
94 changes: 94 additions & 0 deletions
94
packages/orchestration/test/examples/kitchen-sink.contract.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,94 @@ | ||
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; | ||
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js'; | ||
import { E, getInterfaceOf } from '@endo/far'; | ||
import path from 'path'; | ||
import { commonSetup } from '../supports.js'; | ||
|
||
const dirname = path.dirname(new URL(import.meta.url).pathname); | ||
|
||
const contractName = 'kitchen-sink'; | ||
const contractFile = `${dirname}/../../src/examples/${contractName}.contract.js`; | ||
type StartFn = | ||
typeof import('../../src/examples/kitchen-sink.contract.js').start; | ||
|
||
test('orchestrate - LocalOrchAccount returns a ContinuingOfferResult', async t => { | ||
t.log('bootstrap, orchestration core-eval'); | ||
const { | ||
bootstrap: { storage }, | ||
commonPrivateArgs, | ||
} = await commonSetup(t); | ||
|
||
const { zoe, bundleAndInstall } = await setUpZoeForTest(); | ||
|
||
t.log('contract coreEval', contractName); | ||
|
||
const installation: Installation<StartFn> = | ||
await bundleAndInstall(contractFile); | ||
|
||
const storageNode = await E(storage.rootNode).makeChildNode(contractName); | ||
const kitchenSinkKit = await E(zoe).startInstance( | ||
installation, | ||
undefined, | ||
{}, | ||
{ ...commonPrivateArgs, storageNode }, | ||
); | ||
|
||
const publicFacet = await E(zoe).getPublicFacet(kitchenSinkKit.instance); | ||
const inv = E(publicFacet).makeLocalOrchAcctInvitation(); | ||
const userSeat = E(zoe).offer(inv, {}); | ||
// @ts-expect-error TODO: type expected offer result | ||
const { holder, invitationMakers, publicSubscribers } = | ||
await E(userSeat).getOfferResult(); | ||
|
||
t.regex(getInterfaceOf(holder)!, /Local Orchestration (.*) holder/); | ||
t.regex( | ||
getInterfaceOf(invitationMakers)!, | ||
/Local Orchestration (.*) invitationMakers/, | ||
); | ||
const { description, storagePath, subscriber } = publicSubscribers.account; | ||
t.regex(description, /Account holder/); | ||
// FIXME in this PR, currently a vow | ||
t.is(getInterfaceOf(storagePath), undefined); | ||
t.regex(getInterfaceOf(subscriber)!, /Durable Publish Kit subscriber/); | ||
}); | ||
|
||
test('orchestrate - CosmosOrchAccount returns a ContinuingOfferResult', async t => { | ||
t.log('bootstrap, orchestration core-eval'); | ||
const { | ||
bootstrap: { storage }, | ||
commonPrivateArgs, | ||
} = await commonSetup(t); | ||
|
||
const { zoe, bundleAndInstall } = await setUpZoeForTest(); | ||
|
||
t.log('contract coreEval', contractName); | ||
|
||
const installation: Installation<StartFn> = | ||
await bundleAndInstall(contractFile); | ||
|
||
const storageNode = await E(storage.rootNode).makeChildNode(contractName); | ||
const kitchenSinkKit = await E(zoe).startInstance( | ||
installation, | ||
undefined, | ||
{}, | ||
{ ...commonPrivateArgs, storageNode }, | ||
); | ||
|
||
const publicFacet = await E(zoe).getPublicFacet(kitchenSinkKit.instance); | ||
const inv = E(publicFacet).makeCosmosOrchAcctInvitation(); | ||
const userSeat = E(zoe).offer(inv, {}, undefined, { chainName: 'cosmoshub' }); | ||
// @ts-expect-error TODO: type expected offer result | ||
const { holder, invitationMakers, publicSubscribers } = | ||
await E(userSeat).getOfferResult(); | ||
|
||
t.regex(getInterfaceOf(holder)!, /Staking Account (.*) holder/); | ||
t.regex( | ||
getInterfaceOf(invitationMakers)!, | ||
/Staking Account (.*) invitationMakers/, | ||
); | ||
const { description, storagePath, subscriber } = publicSubscribers.account; | ||
t.regex(description, /Account holder/); | ||
// FIXME in this PR, currently a vow | ||
t.is(getInterfaceOf(storagePath), undefined); | ||
t.regex(getInterfaceOf(subscriber)!, /Durable Publish Kit subscriber/); | ||
}); |