Skip to content

Commit

Permalink
feat: getVBankAssetInfo() on orch.getChain('agoric') (#9798)
Browse files Browse the repository at this point in the history
refs: #9541, #9322, #9519

## Description

add `getVBankAssetInfo()` method on agoric chain object.

DRAFT until

 - [x] how to add chain-specific methods to return type of `getChain()`?
 - [x] refactor uses of `makeResumableAgoricNamesHack` to use this

### Documentation Considerations

change is visible via `orchestration-api.d.ts`
cc @dtribble 

### Security Considerations

none?

### Scaling Considerations

returns O(n) data from O(1) args

### Testing Considerations

perhaps not independently tested

### Upgrade Considerations

not yet deployed
  • Loading branch information
mergify[bot] authored Aug 2, 2024
2 parents d12673b + a06ffde commit 5cd99ea
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 209 deletions.
20 changes: 1 addition & 19 deletions packages/orchestration/src/examples/sendAnywhere.contract.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { makeStateRecord } from '@agoric/async-flow';
import { AmountShape } from '@agoric/ertp';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { Fail } from '@endo/errors';
import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { withOrchestration } from '../utils/start-helper.js';
import * as flows from './sendAnywhere.flows.js';
Expand Down Expand Up @@ -50,7 +48,7 @@ const contract = async (
zcf,
privateArgs,
zone,
{ chainHub, orchestrateAll, vowTools, zoeTools },
{ chainHub, orchestrateAll, zoeTools },
) => {
const contractState = makeStateRecord(
/** @type {{ account: OrchestrationAccount<any> | undefined }} */ {
Expand All @@ -60,27 +58,11 @@ const contract = async (

const creatorFacet = prepareChainHubAdmin(zone, chainHub);

// TODO should be a provided helper
/** @type {(brand: Brand) => Vow<VBankAssetDetail>} */
const findBrandInVBank = vowTools.retriable(
zone,
'findBrandInVBank',
/** @param {Brand} brand */
async brand => {
const { agoricNames } = privateArgs;
const assets = await E(E(agoricNames).lookup('vbankAsset')).values();
const it = assets.find(a => a.brand === brand);
it || Fail`brand ${brand} not in agoricNames.vbankAsset`;
return it;
},
);

// orchestrate uses the names on orchestrationFns to do a "prepare" of the associated behavior
const orchFns = orchestrateAll(flows, {
zcf,
contractState,
localTransfer: zoeTools.localTransfer,
findBrandInVBank,
});

const publicFacet = zone.exo(
Expand Down
12 changes: 8 additions & 4 deletions packages/orchestration/src/examples/sendAnywhere.flows.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { NonNullish } from '@agoric/internal';
import { M, mustMatch } from '@endo/patterns';

/**
* @import {GuestOf} from '@agoric/async-flow';
* @import {VBankAssetDetail} from '@agoric/vats/tools/board-utils.js';
* @import {ZoeTools} from '../utils/zoe-tools.js';
* @import {Orchestrator, LocalAccountMethods, OrchestrationAccountI, OrchestrationFlow} from '../types.js';
*/
Expand All @@ -18,13 +18,12 @@ const { entries } = Object;
* @param {object} ctx
* @param {{ localAccount?: OrchestrationAccountI & LocalAccountMethods }} ctx.contractState
* @param {GuestOf<ZoeTools['localTransfer']>} ctx.localTransfer
* @param {(brand: Brand) => Promise<VBankAssetDetail>} ctx.findBrandInVBank
* @param {ZCFSeat} seat
* @param {{ chainName: string; destAddr: string }} offerArgs
*/
export async function sendIt(
orch,
{ contractState, localTransfer, findBrandInVBank },
{ contractState, localTransfer },
seat,
offerArgs,
) {
Expand All @@ -33,7 +32,12 @@ export async function sendIt(
// NOTE the proposal shape ensures that the `give` is a single asset
const { give } = seat.getProposal();
const [[_kw, amt]] = entries(give);
const { denom } = await findBrandInVBank(amt.brand);
const agoric = await orch.getChain('agoric');
const assets = await agoric.getVBankAssetInfo();
const { denom } = NonNullish(
assets.find(a => a.brand === amt.brand),
`${amt.brand} not registered in vbank`,
);
const chain = await orch.getChain(chainName);

if (!contractState.localAccount) {
Expand Down
109 changes: 0 additions & 109 deletions packages/orchestration/src/exos/agoric-names-tools.js

This file was deleted.

57 changes: 53 additions & 4 deletions packages/orchestration/src/exos/local-chain-facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,36 @@ import { M } from '@endo/patterns';
import { pickFacet } from '@agoric/vat-data';
import { VowShape } from '@agoric/vow';

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

/**
* @import {HostOf} from '@agoric/async-flow';
* @import {Zone} from '@agoric/base-zone';
* @import {TimerService} from '@agoric/time';
* @import {Remote} from '@agoric/internal';
* @import {LocalChain, LocalChainAccount} from '@agoric/vats/src/localchain.js';
* @import {AssetInfo} from '@agoric/vats/src/vat-bank.js';
* @import {NameHub} from '@agoric/vats';
* @import {Vow, VowTools} from '@agoric/vow';
* @import {CosmosInterchainService} from './cosmos-interchain-service.js';
* @import {LocalOrchestrationAccountKit, MakeLocalOrchestrationAccountKit} from './local-orchestration-account.js';
* @import {ChainAddress, ChainInfo, CosmosChainInfo, IBCConnectionInfo, OrchestrationAccount} from '../types.js';
*/

/**
* @typedef {object} AgoricChainMethods
* @property {() => Promise<AssetInfo[]>} getVBankAssetInfo Get asset info from
* agoricNames.vbankAsset.
*
* Caches the query to agoricNames in the first call.
*/

/**
* @typedef {{
* makeLocalOrchestrationAccountKit: MakeLocalOrchestrationAccountKit;
* orchestration: Remote<CosmosInterchainService>;
* storageNode: Remote<StorageNode>;
* agoricNames: Remote<NameHub>;
* timer: Remote<TimerService>;
* localchain: Remote<LocalChain>;
* vowTools: VowTools;
Expand All @@ -38,17 +50,26 @@ const prepareLocalChainFacadeKit = (
zone,
{
makeLocalOrchestrationAccountKit,
agoricNames,
localchain,
// TODO vstorage design https://github.com/Agoric/agoric-sdk/issues/9066
// consider making an `accounts` childNode
storageNode,
vowTools: { allVows, watch },
vowTools: { allVows, watch, asVow },
},
) =>
zone.exoClassKit(
'LocalChainFacade',
{
public: ChainFacadeI,
public: M.interface('LocalChainFacade', {
...chainFacadeMethods,
getVBankAssetInfo: M.call().optional(M.boolean()).returns(VowShape),
}),
vbankAssetValuesWatcher: M.interface('vbankAssetValuesWatcher', {
onFulfilled: M.call(M.arrayOf(M.record()))
.optional(M.arrayOf(M.undefined())) // empty context
.returns(VowShape),
}),
makeAccountWatcher: M.interface('makeAccountWatcher', {
onFulfilled: M.call([M.remotable('LCA Account'), M.string()])
.optional(M.arrayOf(M.undefined())) // empty context
Expand All @@ -64,7 +85,10 @@ const prepareLocalChainFacadeKit = (
* @param {CosmosChainInfo} localChainInfo
*/
localChainInfo => {
return { localChainInfo };
return {
localChainInfo,
vbankAssets: /** @type {AssetInfo[] | undefined} */ (undefined),
};
},
{
public: {
Expand All @@ -83,6 +107,31 @@ const prepareLocalChainFacadeKit = (
this.facets.makeAccountWatcher,
);
},
/** @type {HostOf<AgoricChainMethods['getVBankAssetInfo']>} */
getVBankAssetInfo() {
return asVow(() => {
const { vbankAssets } = this.state;
if (vbankAssets) {
return vbankAssets;
}
const vbankAssetNameHubP = E(agoricNames).lookup('vbankAsset');
const vbankAssetValuesP = E(vbankAssetNameHubP).values();
const { vbankAssetValuesWatcher } = this.facets;
return watch(vbankAssetValuesP, vbankAssetValuesWatcher);
});
},
},
vbankAssetValuesWatcher: {
/**
* @param {AssetInfo[]} assets
*/
onFulfilled(assets) {
const { state } = this;
return asVow(() => {
state.vbankAssets = assets;
return assets;
});
},
},
makeAccountWatcher: {
/**
Expand Down
6 changes: 5 additions & 1 deletion packages/orchestration/src/orchestration-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { LocalChainAccount } from '@agoric/vats/src/localchain.js';
import type { ResolvedPublicTopic } from '@agoric/zoe/src/contractSupport/topics.js';
import type { Passable } from '@endo/marshal';
import type {
AgoricChainMethods,
ChainInfo,
CosmosChainAccountMethods,
CosmosChainInfo,
Expand Down Expand Up @@ -96,7 +97,10 @@ export interface Chain<CI extends ChainInfo> {
export interface Orchestrator {
getChain: <C extends string>(
chainName: C,
) => Promise<Chain<C extends keyof KnownChains ? KnownChains[C] : any>>;
) => Promise<
Chain<C extends keyof KnownChains ? KnownChains[C] : any> &
(C extends 'agoric' ? AgoricChainMethods : {})
>;

makeLocalAccount: () => Promise<LocalChainAccount>;
/**
Expand Down
6 changes: 4 additions & 2 deletions packages/orchestration/src/typeGuards.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@ export const DenomAmountShape = { denom: DenomShape, value: M.bigint() };

export const AmountArgShape = M.or(AmountShape, DenomAmountShape);

/** @see {Chain} */
export const ChainFacadeI = M.interface('ChainFacade', {
export const chainFacadeMethods = harden({
getChainInfo: M.call().returns(VowShape),
makeAccount: M.call().returns(VowShape),
});

/** @see {Chain} */
export const ChainFacadeI = M.interface('ChainFacade', chainFacadeMethods);

/**
* for google/protobuf/timestamp.proto, not to be confused with TimestampShape
* from `@agoric/time`
Expand Down
1 change: 1 addition & 0 deletions packages/orchestration/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type * from './chain-info.js';
export type * from './cosmos-api.js';
export type * from './ethereum-api.js';
export type * from './exos/ica-account-kit.js';
export type * from './exos/local-chain-facade.js';
export type * from './exos/icq-connection-kit.js';
export type * from './orchestration-api.js';
export type * from './exos/cosmos-interchain-service.js';
Expand Down
1 change: 1 addition & 0 deletions packages/orchestration/src/utils/start-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const provideOrchestration = (
localchain: remotePowers.localchain,
// FIXME what path?
storageNode: remotePowers.storageNode,
agoricNames,
orchestration: remotePowers.orchestrationService,
timer: remotePowers.timerService,
vowTools,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ Generated by [AVA](https://avajs.dev).
0: {
contractState_kindHandle: 'Alleged: kind',
contractState_singleton: 'Alleged: contractState',
findBrandInVBank_kindHandle: 'Alleged: kind',
findBrandInVBank_singleton: 'Alleged: findBrandInVBank',
localTransfer_kindHandle: 'Alleged: kind',
localTransfer_singleton: 'Alleged: localTransfer',
},
Expand Down
Binary file not shown.
Loading

0 comments on commit 5cd99ea

Please sign in to comment.