Skip to content

Commit

Permalink
feat(orchestrate): membrane friendly wrapper for agoricNames
Browse files Browse the repository at this point in the history
 * Perform remote calls to agoricNames in membrane-friendly way. This is an
 * interim approach until #9541,
 * #9322, or
 * #9519
  • Loading branch information
0xpatrickdev committed Jun 21, 2024
1 parent 944adea commit 6631048
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 15 deletions.
14 changes: 2 additions & 12 deletions packages/orchestration/src/examples/sendAnywhere.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { CosmosChainInfoShape } from '../typeGuards.js';
import { provideOrchestration } from '../utils/start-helper.js';

const { entries } = Object;
const { Fail } = assert;

/**
* @import {Baggage} from '@agoric/vat-data';
Expand Down Expand Up @@ -45,7 +44,7 @@ export const SingleAmountRecord = M.and(
* @param {Baggage} baggage
*/
export const start = async (zcf, privateArgs, baggage) => {
const { chainHub, orchestrate, zone } = provideOrchestration(
const { agNamesTools, chainHub, orchestrate, zone } = provideOrchestration(
zcf,
baggage,
privateArgs,
Expand All @@ -55,15 +54,6 @@ export const start = async (zcf, privateArgs, baggage) => {
/** @type {import('../orchestration-api.js').OrchestrationAccount<any>} */
let contractAccount;

const findBrandInVBank = async brand => {
const assets = await E(
E(privateArgs.agoricNames).lookup('vbankAsset'),
).values();
const it = assets.find(a => a.brand === brand);
it || Fail`brand ${brand} not in agoricNames.vbankAsset`;
return it;
};

/** @type {OfferHandler} */
const sendIt = orchestrate(
'sendIt',
Expand All @@ -77,7 +67,7 @@ export const start = async (zcf, privateArgs, baggage) => {
const { chainName, destAddr } = offerArgs;
const { give } = seat.getProposal();
const [[kw, amt]] = entries(give);
const { denom } = await findBrandInVBank(amt.brand);
const { denom } = await V.when(agNamesTools.findBrandInVBank(amt.brand));
const chain = await orch.getChain(chainName);

// FIXME ok to use a heap var crossing the membrane scope this way?
Expand Down
66 changes: 66 additions & 0 deletions packages/orchestration/src/exos/agoric-names-tools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { VowShape } from '@agoric/vow';
import { E, Far } from '@endo/far';
import { M } from '@endo/patterns';
import { BrandShape } from '@agoric/ertp';

const { Fail } = assert;

/**
* @import {NameHub} from '@agoric/vats';
* @import {AssetInfo} from '@agoric/vats/src/vat-bank';
* @import {Remote} from '@agoric/internal';
* @import {Vow, VowTools} from '@agoric/vow';
* @import {Zone} from '@agoric/zone';
*/

/**
* Perform remote calls to agoricNames in membrane-friendly way. This is an
* interim approach until https://github.com/Agoric/agoric-sdk/issues/9541,
* https://github.com/Agoric/agoric-sdk/pull/9322, or
* https://github.com/Agoric/agoric-sdk/pull/9519
*
* XXX consider exposing `has`, `entries`, `keys`, `values` from `NameHub`
*
* @param {Zone} zone
* @param {{ agoricNames: Remote<NameHub>; vowTools: VowTools }} powers
*/
export const makeAgNamesTools = (
zone,
{ agoricNames, vowTools: { watch } },
) => {
const agNamesTools = zone.exo(
'AgoricNamesTools',
M.interface('AgoricNamesToolsI', {
lookup: M.call().rest(M.arrayOf(M.string())).returns(VowShape),
findBrandInVBank: M.call(BrandShape).returns(VowShape),
}),
{
/** @param {...string} args */
lookup(...args) {
return watch(E(agoricNames).lookup(...args));
},
/**
* @param {Brand<'nat'>} brand
* @returns {Vow<AssetInfo>}
*/
findBrandInVBank(brand) {
// XXX consider caching and refetching 1x if brand is not found,
// if this is planned to be local / long-lived
const vbankAssetNameHubP = E(agoricNames).lookup('vbankAsset');
return watch(
E(vbankAssetNameHubP).values(),
Far('BrandsWatcher', {
/** @param {AssetInfo[]} assets */
onFulfilled(assets) {
const it = assets.find(a => a.brand === brand);
it || Fail`brand ${brand} not in agoricNames.vbankAsset`;
return it;
},
}),
);
},
},
);
return agNamesTools;
};
/** @typedef {ReturnType<typeof makeAgNamesTools>} AgNamesTools */
10 changes: 7 additions & 3 deletions packages/orchestration/src/utils/start-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { makeChainHub } from '../exos/chain-hub.js';
import { prepareRemoteChainFacade } from '../exos/remote-chain-facade.js';
import { prepareCosmosOrchestrationAccount } from '../exos/cosmos-orchestration-account.js';
import { prepareLocalChainFacade } from '../exos/local-chain-facade.js';
import { makeAgNamesTools } from '../exos/agoric-names-tools.js';

/**
* @import {PromiseKit} from '@endo/promise-kit'
Expand Down Expand Up @@ -45,8 +46,9 @@ export const provideOrchestration = (
marshaller,
) => {
const zone = makeDurableZone(baggage);
const { agoricNames, timerService } = remotePowers;

const chainHub = makeChainHub(remotePowers.agoricNames);
const chainHub = makeChainHub(agoricNames);

const vowTools = prepareVowTools(zone.subZone('vows'));

Expand All @@ -55,7 +57,7 @@ export const provideOrchestration = (
zone,
makeRecorderKit,
zcf,
remotePowers.timerService,
timerService,
vowTools,
chainHub,
);
Expand All @@ -64,6 +66,8 @@ export const provideOrchestration = (
vowTools,
});

const agNamesTools = makeAgNamesTools(zone, { agoricNames, vowTools });

const makeCosmosOrchestrationAccount = prepareCosmosOrchestrationAccount(
// FIXME what zone?
zone,
Expand Down Expand Up @@ -101,6 +105,6 @@ export const provideOrchestration = (
vowTools,
...remotePowers,
});
return { ...facade, chainHub, zone };
return { ...facade, chainHub, agNamesTools, zone };
};
harden(provideOrchestration);
25 changes: 25 additions & 0 deletions packages/orchestration/test/exos/agoric-names-tools.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { V } from '@agoric/vow/vat.js';
import { makeHeapZone } from '@agoric/zone';
import { makeAgNamesTools } from '../../src/exos/agoric-names-tools.js';
import { commonSetup } from '../supports.js';

test('agoric names tools', async t => {
const {
bootstrap: { agoricNames, vowTools },
brands: { ist },
} = await commonSetup(t);

const zone = makeHeapZone();
const agNamesTools = makeAgNamesTools(zone, {
agoricNames,
vowTools,
});

const chainEntry = await V.when(agNamesTools.lookup('chain', 'celestia'));
t.like(chainEntry, { chainId: 'celestia' });

const istDenom = await V.when(agNamesTools.findBrandInVBank(ist.brand));
t.like(istDenom, { denom: 'uist' });
});

0 comments on commit 6631048

Please sign in to comment.