Skip to content

Commit

Permalink
chore: chain facades create child node per account
Browse files Browse the repository at this point in the history
- previously, each orch account was given the contracts storage node. this creates a child node per account
- refs #9066, helping ensure orch account addresses are available for smart-wallet clients. left some suggestions in code comments for further improvements
  • Loading branch information
0xpatrickdev committed Jul 10, 2024
1 parent 8330fba commit 3ba1e59
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 15 deletions.
28 changes: 26 additions & 2 deletions packages/orchestration/src/exos/local-chain-facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { pickFacet } from '@agoric/vat-data';
import { VowShape } from '@agoric/vow';

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

Expand Down Expand Up @@ -36,6 +37,8 @@ const prepareLocalChainFacadeKit = (
{
makeLocalOrchestrationAccountKit,
localchain,
// TODO vstorage design https://github.com/Agoric/agoric-sdk/issues/9066
// consider making an `accounts` childNode
storageNode,
vowTools: { allVows, watch },
},
Expand All @@ -44,9 +47,14 @@ const prepareLocalChainFacadeKit = (
'LocalChainFacade',
{
public: ChainFacadeI,
makeAccountWatcher: M.interface('undelegateWatcher', {
makeAccountWatcher: M.interface('makeAccountWatcher', {
onFulfilled: M.call([M.remotable('LCA Account'), M.string()])
.optional(M.arrayOf(M.undefined())) // empty context
.returns(VowShape),
}),
makeChildNodeWatcher: M.interface('makeChildNodeWatcher', {
onFulfilled: M.call(M.remotable())
.optional({ account: M.remotable(), address: M.string() }) // empty context
.returns(M.remotable()),
}),
},
Expand Down Expand Up @@ -82,6 +90,22 @@ const prepareLocalChainFacadeKit = (
* @param {[LocalChainAccount, ChainAddress['value']]} results
*/
onFulfilled([account, address]) {
return watch(
E(storageNode).makeChildNode(address),
this.facets.makeChildNodeWatcher,
{ account, address },
);
},
},
makeChildNodeWatcher: {
/**
* @param {Remote<StorageNode>} childNode
* @param {{
* account: LocalChainAccount;
* address: ChainAddress['value'];
* }} ctx
*/
onFulfilled(childNode, { account, address }) {
const { localChainInfo } = this.state;
const { holder } = makeLocalOrchestrationAccountKit({
account,
Expand All @@ -91,7 +115,7 @@ const prepareLocalChainFacadeKit = (
chainId: localChainInfo.chainId,
}),
// FIXME storage path https://github.com/Agoric/agoric-sdk/issues/9066
storageNode,
storageNode: childNode,
});
return holder;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ export const prepareLocalOrchestrationAccountKit = (
// must be the fully synchronous maker because the kit is held in durable state
// @ts-expect-error XXX Patterns
const topicKit = makeRecorderKit(storageNode, PUBLIC_TOPICS.account[1]);
// TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066
void E(topicKit.recorder).write('');

return { account, address, topicKit };
},
Expand Down
59 changes: 46 additions & 13 deletions packages/orchestration/src/exos/remote-chain-facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { E } from '@endo/far';
import { M } from '@endo/patterns';
import { pickFacet } from '@agoric/vat-data';
import { VowShape } from '@agoric/vow';
import { ChainFacadeI } from '../typeGuards.js';
import { ChainAddressShape, ChainFacadeI } from '../typeGuards.js';

/**
* @import {Zone} from '@agoric/base-zone';
Expand Down Expand Up @@ -43,6 +43,8 @@ const prepareRemoteChainFacadeKit = (
{
makeCosmosOrchestrationAccount,
orchestration,
// TODO vstorage design https://github.com/Agoric/agoric-sdk/issues/9066
// consider making an `accounts` childNode
storageNode,
timer,
vowTools: { asVow, watch },
Expand All @@ -54,12 +56,20 @@ const prepareRemoteChainFacadeKit = (
public: ChainFacadeI,
makeAccountWatcher: M.interface('makeAccountWatcher', {
onFulfilled: M.call(M.remotable())
.optional(M.string())
.optional(M.arrayOf(M.undefined())) // empty context
.returns(VowShape),
}),
getAddressWatcher: M.interface('makeAccountWatcher', {
getAddressWatcher: M.interface('getAddressWatcher', {
onFulfilled: M.call(M.record())
.optional({ stakingDenom: M.string(), account: M.remotable() })
.optional(M.remotable())
.returns(VowShape),
}),
makeChildNodeWatcher: M.interface('makeChildNodeWatcher', {
onFulfilled: M.call(M.remotable())
.optional({
account: M.remotable(),
chainAddress: ChainAddressShape,
})
.returns(M.remotable()),
}),
},
Expand Down Expand Up @@ -95,32 +105,55 @@ const prepareRemoteChainFacadeKit = (
connectionInfo.counterparty.connection_id,
),
this.facets.makeAccountWatcher,
stakingDenom,
);
});
},
},
makeAccountWatcher: {
/**
* XXX Pipeline vows allVows and E
*
* @param {IcaAccount} account
* @param {Denom} stakingDenom
*/
onFulfilled(account, stakingDenom) {
return watch(E(account).getAddress(), this.facets.getAddressWatcher, {
stakingDenom,
onFulfilled(account) {
return watch(
E(account).getAddress(),
this.facets.getAddressWatcher,
account,
});
);
},
},
getAddressWatcher: {
/**
* @param {ChainAddress} chainAddress
* @param {{ stakingDenom: Denom; account: IcaAccount }} ctx
* @param {IcaAccount} account
*/
onFulfilled(chainAddress, account) {
return watch(
E(storageNode).makeChildNode(chainAddress.value),
this.facets.makeChildNodeWatcher,
{ account, chainAddress },
);
},
},
makeChildNodeWatcher: {
/**
* @param {Remote<StorageNode>} childNode
* @param {{
* account: IcaAccount;
* chainAddress: ChainAddress;
* }} ctx
*/
onFulfilled(chainAddress, { account, stakingDenom }) {
onFulfilled(childNode, { account, chainAddress }) {
const { remoteChainInfo } = this.state;
const stakingDenom = remoteChainInfo.stakingTokens?.[0]?.denom;
if (!stakingDenom) {
throw Fail`chain info lacks staking denom`;
}
return makeCosmosOrchestrationAccount(chainAddress, stakingDenom, {
account,
storageNode,
// FIXME storage path https://github.com/Agoric/agoric-sdk/issues/9066
storageNode: childNode,
// FIXME provide real ICQ connection
// FIXME make Query Connection available via chain, not orchestrationAccount
icqConnection: anyVal,
Expand Down

0 comments on commit 3ba1e59

Please sign in to comment.