Skip to content

Commit

Permalink
9449 chain facades return vows (#9547)
Browse files Browse the repository at this point in the history
refs: #9449

## Description
More exos returning vows. Note these are _heap_ vows due to https://github.com/Agoric/agoric-sdk/blob/944adea10660e68a65c10a2b32b6899919315e31/packages/vow/vat.js#L29-L31

### Security Considerations
none

### Scaling Considerations
none

### Documentation Considerations
none

### Testing Considerations
CI

### Upgrade Considerations
none
  • Loading branch information
mergify[bot] authored Jun 21, 2024
2 parents c5c52ec + f9b6857 commit 788647d
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 46 deletions.
4 changes: 2 additions & 2 deletions packages/orchestration/src/chain-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const knownChains = /** @satisfies {Record<string, ChainInfo>} */ (
* @param {ERef<import('@agoric/vats').NameHubKit['nameAdmin']>} agoricNamesAdmin
* @param {string} name
* @param {CosmosChainInfo} chainInfo
* @param {(...messages: string[]) => void} log
* @param {(...messages: string[]) => void} [log]
*/
export const registerChain = async (
agoricNamesAdmin,
Expand Down Expand Up @@ -105,7 +105,7 @@ export const registerChain = async (

/**
* @param {ERef<import('@agoric/vats').NameHubKit['nameAdmin']>} agoricNamesAdmin
* @param {(...messages: string[]) => void} log
* @param {(...messages: string[]) => void} [log]
*/
export const registerChainNamespace = async (agoricNamesAdmin, log) => {
for await (const [name, info] of Object.entries(knownChains)) {
Expand Down
9 changes: 7 additions & 2 deletions packages/orchestration/src/examples/sendAnywhere.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,16 @@ export const start = async (zcf, privateArgs, baggage) => {
// FIXME ok to use a heap var crossing the membrane scope this way?
if (!contractAccount) {
const agoricChain = await orch.getChain('agoric');
contractAccount = await agoricChain.makeAccount();
// XXX when() until membrane
contractAccount = await V.when(agoricChain.makeAccount());
console.log('contractAccount', contractAccount);
}

const info = await chain.getChainInfo();
// XXX when() until membrane
const info = await V.when(chain.getChainInfo());
console.log('info', info);
const { chainId } = info;
assert(typeof chainId === 'string', 'bad chainId');
const { [kw]: pmtP } = await withdrawFromSeat(zcf, seat, give);
await E.when(pmtP, pmt => contractAccount.deposit(pmt));
await contractAccount.transfer(
Expand Down
7 changes: 5 additions & 2 deletions packages/orchestration/src/examples/swapExample.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js'
import { Far } from '@endo/far';
import { deeplyFulfilled } from '@endo/marshal';
import { M, objectMap } from '@endo/patterns';
import { when } from '@agoric/vow/vat.js';
import { orcUtils } from '../utils/orc.js';
import { provideOrchestration } from '../utils/start-helper.js';

Expand Down Expand Up @@ -95,8 +96,10 @@ export const start = async (zcf, privateArgs, baggage) => {
const agoric = await orch.getChain('agoric');

const [omniAccount, localAccount] = await Promise.all([
omni.makeAccount(),
agoric.makeAccount(),
// XXX when() until membrane
when(omni.makeAccount()),
// XXX when() until membrane
when(agoric.makeAccount()),
]);

const omniAddress = omniAccount.getAddress();
Expand Down
46 changes: 28 additions & 18 deletions packages/orchestration/src/exos/local-chain-facade.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @file ChainAccount exo */
import { V } from '@agoric/vow/vat.js';
import { V, watch } from '@agoric/vow/vat.js';

import { ChainFacadeI } from '../typeGuards.js';

Expand All @@ -8,6 +8,7 @@ import { ChainFacadeI } from '../typeGuards.js';
* @import {TimerService} from '@agoric/time';
* @import {Remote} from '@agoric/internal';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {Vow, VowTools} from '@agoric/vow';
* @import {OrchestrationService} from '../service.js';
* @import {MakeLocalOrchestrationAccountKit} from './local-orchestration-account.js';
* @import {ChainInfo, CosmosChainInfo, IBCConnectionInfo, OrchestrationAccount} from '../types.js';
Expand All @@ -21,11 +22,17 @@ import { ChainFacadeI } from '../typeGuards.js';
* storageNode: Remote<StorageNode>;
* timer: Remote<TimerService>;
* localchain: Remote<LocalChain>;
* vowTools: VowTools;
* }} powers
*/
export const prepareLocalChainFacade = (
zone,
{ makeLocalOrchestrationAccountKit, localchain, storageNode },
{
makeLocalOrchestrationAccountKit,
localchain,
storageNode,
vowTools: { allVows },
},
) =>
zone.exoClass(
'LocalChainFacade',
Expand All @@ -37,29 +44,32 @@ export const prepareLocalChainFacade = (
return { localChainInfo };
},
{
async getChainInfo() {
return this.state.localChainInfo;
getChainInfo() {
return watch(this.state.localChainInfo);
},

// FIXME parameterize on the remoteChainInfo to make()
// That used to work but got lost in the migration to Exo
/** @returns {Promise<OrchestrationAccount<ChainInfo>>} */
async makeAccount() {
/** @returns {Vow<OrchestrationAccount<ChainInfo>>} */
makeAccount() {
const { localChainInfo } = this.state;
const lcaP = V(localchain).makeAccount();
const [lca, address] = await Promise.all([lcaP, V(lcaP).getAddress()]);
const { holder: account } = makeLocalOrchestrationAccountKit({
account: lca,
address: harden({
address,
chainId: localChainInfo.chainId,
addressEncoding: 'bech32',
}),
// FIXME storage path https://github.com/Agoric/agoric-sdk/issues/9066
storageNode,
// FIXME use watch() from vowTools
return watch(allVows([lcaP, V(lcaP).getAddress()]), {
onFulfilled: ([lca, address]) => {
const { holder: account } = makeLocalOrchestrationAccountKit({
account: lca,
address: harden({
address,
addressEncoding: 'bech32',
chainId: localChainInfo.chainId,
}),
// FIXME storage path https://github.com/Agoric/agoric-sdk/issues/9066
storageNode,
});
return account;
},
});

return account;
},
},
);
Expand Down
49 changes: 31 additions & 18 deletions packages/orchestration/src/exos/remote-chain-facade.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/** @file ChainAccount exo */
import { makeTracer } from '@agoric/internal';
import { V } from '@agoric/vow/vat.js';
import { V, watch } from '@agoric/vow/vat.js';

import { ChainFacadeI } from '../typeGuards.js';

/**
* @import {Zone} from '@agoric/base-zone';
* @import {TimerService} from '@agoric/time';
* @import {Remote} from '@agoric/internal';
* @import {Vow, VowTools} from '@agoric/vow';
* @import {OrchestrationService} from '../service.js';
* @import {prepareCosmosOrchestrationAccount} from './cosmos-orchestration-account.js';
* @import {ChainInfo, CosmosChainInfo, IBCConnectionInfo, OrchestrationAccount} from '../types.js';
Expand All @@ -28,11 +29,18 @@ const anyVal = null;
* orchestration: Remote<OrchestrationService>;
* storageNode: Remote<StorageNode>;
* timer: Remote<TimerService>;
* vowTools: VowTools;
* }} powers
*/
export const prepareRemoteChainFacade = (
zone,
{ makeCosmosOrchestrationAccount, orchestration, storageNode, timer },
{
makeCosmosOrchestrationAccount,
orchestration,
storageNode,
timer,
vowTools: { allVows },
},
) =>
zone.exoClass(
'RemoteChainFacade',
Expand All @@ -46,33 +54,38 @@ export const prepareRemoteChainFacade = (
return { remoteChainInfo, connectionInfo };
},
{
async getChainInfo() {
return this.state.remoteChainInfo;
getChainInfo() {
return watch(this.state.remoteChainInfo);
},

// FIXME parameterize on the remoteChainInfo to make()
// That used to work but got lost in the migration to Exo
/** @returns {Promise<OrchestrationAccount<ChainInfo>>} */
async makeAccount() {
/** @returns {Vow<OrchestrationAccount<ChainInfo>>} */
makeAccount() {
const { remoteChainInfo, connectionInfo } = this.state;
const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom;
if (!stakingDenom) {
// FIXME methods that return vows must not throw synchronously
throw Fail`chain info lacks staking denom`;
}

const icaAccount = await V(orchestration).makeAccount(
const icaP = V(orchestration).makeAccount(
remoteChainInfo.chainId,
connectionInfo.id,
connectionInfo.counterparty.connection_id,
);

const address = await V(icaAccount).getAddress();

const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom;
if (!stakingDenom) {
throw Fail`chain info lacks staking denom`;
}
return makeCosmosOrchestrationAccount(address, stakingDenom, {
account: icaAccount,
storageNode,
icqConnection: anyVal,
timer,
// FIXME use watch() from vowTools
return watch(allVows([icaP, V(icaP).getAddress()]), {
onFulfilled: ([account, address]) => {
return makeCosmosOrchestrationAccount(address, stakingDenom, {
account,
storageNode,
// FIXME provide real ICQ connection
icqConnection: anyVal,
timer,
});
},
});
},
},
Expand Down
5 changes: 3 additions & 2 deletions packages/orchestration/src/typeGuards.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AmountShape } from '@agoric/ertp';
import { VowShape } from '@agoric/vow';
import { M } from '@endo/patterns';

export const ConnectionHandlerI = M.interface('ConnectionHandler', {
Expand Down Expand Up @@ -89,6 +90,6 @@ export const DenomAmountShape = { denom: DenomShape, value: M.bigint() };

/** @see {Chain} */
export const ChainFacadeI = M.interface('ChainFacade', {
getChainInfo: M.callWhen().returns(ChainInfoShape),
makeAccount: M.callWhen().returns(M.remotable('OrchestrationAccount')),
getChainInfo: M.call().returns(VowShape),
makeAccount: M.call().returns(VowShape),
});
2 changes: 2 additions & 0 deletions packages/orchestration/src/utils/start-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const provideOrchestration = (
orchestration: remotePowers.orchestrationService,
storageNode: remotePowers.storageNode,
timer: remotePowers.timerService,
vowTools,
});

const makeLocalChainFacade = prepareLocalChainFacade(zone, {
Expand All @@ -86,6 +87,7 @@ export const provideOrchestration = (
storageNode: remotePowers.storageNode,
orchestration: remotePowers.orchestrationService,
timer: remotePowers.timerService,
vowTools,
});

const facade = makeOrchestrationFacade({
Expand Down
2 changes: 1 addition & 1 deletion packages/orchestration/test/chain-info.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ test('chain-info', async t => {
const { nameHub: agoricNames, nameAdmin: agoricNamesAdmin } =
makeNameHubKit();

await registerChainNamespace(agoricNamesAdmin, t.log);
await registerChainNamespace(agoricNamesAdmin);
const chainNames = await agoricNames.lookup('chain');
t.like(await chainNames.lookup('cosmoshub'), {
chainId: 'cosmoshub-4',
Expand Down
3 changes: 2 additions & 1 deletion packages/orchestration/test/facade.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { V } from '@agoric/vow/vat.js';
import { setupZCFTest } from '@agoric/zoe/test/unitTests/zcf/setupZcfTest.js';
import type { CosmosChainInfo, IBCConnectionInfo } from '../src/cosmos-api.js';
import type { Chain } from '../src/orchestration-api.js';
Expand Down Expand Up @@ -73,7 +74,7 @@ test('chain info', async t => {
});

const result = (await handle()) as Chain<any>;
t.deepEqual(await result.getChainInfo(), mockChainInfo);
t.deepEqual(await V.when(result.getChainInfo()), mockChainInfo);
});

test.todo('contract upgrade');

0 comments on commit 788647d

Please sign in to comment.