Skip to content

Commit

Permalink
feat(stakeAtom): publish address to vstorage
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpatrickdev committed Jun 17, 2024
1 parent a74b6a2 commit c2021ba
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 26 deletions.
12 changes: 10 additions & 2 deletions packages/boot/test/bootstrapTests/orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ test.serial('stakeAtom - repl-style', async t => {
});

test.serial('stakeAtom - smart wallet', async t => {
const { agoricNamesRemotes } = t.context;
const { agoricNamesRemotes, readLatest } = t.context;

const wd = await t.context.walletFactoryDriver.provideSmartWallet(
'agoric1testStakAtom',
Expand All @@ -140,12 +140,20 @@ test.serial('stakeAtom - smart wallet', async t => {
});
t.like(wd.getCurrentWalletRecord(), {
offerToPublicSubscriberPaths: [
['request-account', { account: 'published.stakeAtom' }],
[
'request-account',
{
account: 'published.stakeAtom.accounts.cosmos1test',
},
],
],
});
t.like(wd.getLatestUpdateRecord(), {
status: { id: 'request-account', numWantsSatisfied: 1 },
});
t.like(readLatest('published.stakeAtom.accounts.cosmos1test'), {
sequence: 0n,
});

const { ATOM } = agoricNamesRemotes.brand;
ATOM || Fail`ATOM missing from agoricNames`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const start = async (zcf, privateArgs, baggage) => {
zone,
chainHub,
makeLocalChainAccountKit,
makeRecorderKit,
...orchPowers,
});

Expand Down
14 changes: 12 additions & 2 deletions packages/orchestration/src/examples/stakeIca.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import { makeTracer, StorageNodeShape } from '@agoric/internal';
import { TimerServiceShape } from '@agoric/time';
import { V as E } from '@agoric/vow/vat.js';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport';
import {
prepareRecorderKitMakers,
provideAll,
} from '@agoric/zoe/src/contractSupport';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { M } from '@endo/patterns';
Expand Down Expand Up @@ -67,6 +70,10 @@ export const start = async (zcf, privateArgs, baggage) => {

const zone = makeDurableZone(baggage);

const { accountsStorageNode } = await provideAll(baggage, {
accountsStorageNode: () => E(storageNode).makeChildNode('accounts'),
});

const { makeRecorderKit } = prepareRecorderKitMakers(baggage, marshaller);

const makeCosmosOrchestrationAccount = prepareCosmosOrchestrationAccount(
Expand All @@ -88,9 +95,12 @@ export const start = async (zcf, privateArgs, baggage) => {

const accountAddress = await E(account).getAddress();
trace('account address', accountAddress);
const accountNode = await E(accountsStorageNode).makeChildNode(
accountAddress.address,
);
const holder = makeCosmosOrchestrationAccount(accountAddress, bondDenom, {
account,
storageNode,
storageNode: accountNode,
icqConnection,
timer,
});
Expand Down
9 changes: 7 additions & 2 deletions packages/orchestration/src/examples/swapExample.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { StorageNodeShape } from '@agoric/internal';
import { TimerServiceShape } from '@agoric/time';
import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { Far } from '@endo/far';
import { E, Far } from '@endo/far';
import { deeplyFulfilled } from '@endo/marshal';
import { M, objectMap } from '@endo/patterns';
import { provideAll } from '@agoric/zoe/src/contractSupport';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import { makeOrchestrationFacade } from '../facade.js';
import { orcUtils } from '../utils/orc.js';
Expand Down Expand Up @@ -79,16 +80,20 @@ export const start = async (zcf, privateArgs, baggage) => {
timerService,
chainHub,
);
const { accountsStorageNode } = await provideAll(baggage, {
accountsStorageNode: () => E(storageNode).makeChildNode('accounts'),
});

const { orchestrate } = makeOrchestrationFacade({
localchain,
orchestrationService,
storageNode,
storageNode: accountsStorageNode,
timerService,
zcf,
zone,
chainHub,
makeLocalChainAccountKit,
makeRecorderKit,
});

/** deprecated historical example */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const start = async (zcf, privateArgs, baggage) => {
zone,
chainHub: makeChainHub(agoricNames),
makeLocalChainAccountKit,
makeRecorderKit,
});

/** @type {OfferHandler} */
Expand Down
3 changes: 3 additions & 0 deletions packages/orchestration/src/exos/cosmosOrchestrationAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ export const prepareCosmosOrchestrationAccountKit = (
// 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 https://github.com/Agoric/agoric-sdk/issues/9066
// update sequence after successful executeEncodedTx, _if we want sequence in `vstorage`_
void E(topicKit.recorder).write(harden({ sequence: 0n }));

return { chainAddress, bondDenom, topicKit, ...rest };
},
Expand Down
12 changes: 9 additions & 3 deletions packages/orchestration/src/facade.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { prepareCosmosOrchestrationAccount } from './exos/cosmosOrchestrationAcc
* @import {TimerService} from '@agoric/time';
* @import {IBCConnectionID} from '@agoric/vats';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {RecorderKit, MakeRecorderKit} from '@agoric/zoe/src/contractSupport/recorder.js'.
* @import {Remote} from '@agoric/internal';
* @import {OrchestrationService} from './service.js';
* @import {Chain, ChainInfo, CosmosChainInfo, IBCConnectionInfo, OrchestrationAccount, Orchestrator} from './types.js';
Expand Down Expand Up @@ -95,6 +96,8 @@ const makeLocalChainFacade = (
* @param {IBCConnectionInfo} connectionInfo
* @param {object} io
* @param {Remote<OrchestrationService>} io.orchestration
* @param {MakeRecorderKit} io.makeRecorderKit
* @param {Remote<StorageNode>} io.storageNode
* @param {Remote<TimerService>} io.timer
* @param {ZCF} io.zcf
* @param {Zone} io.zone
Expand All @@ -103,9 +106,8 @@ const makeLocalChainFacade = (
const makeRemoteChainFacade = (
chainInfo,
connectionInfo,
{ orchestration, timer, zcf, zone },
{ orchestration, makeRecorderKit, storageNode, timer, zcf, zone },
) => {
const makeRecorderKit = () => anyVal;
const makeCosmosOrchestrationAccount = prepareCosmosOrchestrationAccount(
zone.subZone(chainInfo.chainId),
makeRecorderKit,
Expand Down Expand Up @@ -133,7 +135,7 @@ const makeRemoteChainFacade = (
// @ts-expect-error XXX dynamic method availability
return makeCosmosOrchestrationAccount(address, bondDenom, {
account: icaAccount,
storageNode: anyVal,
storageNode,
icqConnection: anyVal,
timer,
});
Expand All @@ -153,6 +155,7 @@ const makeRemoteChainFacade = (
* makeLocalChainAccountKit: ReturnType<
* typeof import('./exos/local-chain-account-kit.js').prepareLocalChainAccountKit
* >;
* makeRecorderKit: MakeRecorderKit;
* }} powers
*/
export const makeOrchestrationFacade = ({
Expand All @@ -164,6 +167,7 @@ export const makeOrchestrationFacade = ({
localchain,
chainHub,
makeLocalChainAccountKit,
makeRecorderKit,
}) => {
console.log('makeOrchestrationFacade got', {
zone,
Expand Down Expand Up @@ -205,6 +209,8 @@ export const makeOrchestrationFacade = ({

return makeRemoteChainFacade(remoteChainInfo, connectionInfo, {
orchestration: orchestrationService,
makeRecorderKit,
storageNode,
timer: timerService,
zcf,
zone,
Expand Down
65 changes: 55 additions & 10 deletions packages/orchestration/test/examples/stake-atom.contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js';
import { E } from '@endo/far';
import path from 'path';
import { makeNotifierFromSubscriber } from '@agoric/notifier';
import type { Installation } from '@agoric/zoe/src/zoeService/utils.js';
import { commonSetup } from '../supports.js';
import { type StakeAtomTerms } from '../../src/examples/stakeAtom.contract.js';
import { type StakeIcaTerms } from '../../src/examples/stakeIca.contract.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);

Expand All @@ -20,29 +21,25 @@ const startContract = async ({
storage,
issuerKeywordRecord,
terms = {
chainId: 'cosmoshub-4',
hostConnectionId: 'connection-1',
controllerConnectionId: 'connection-2',
bondDenom: 'uatom',
icqEnabled: false,
} as StakeAtomTerms,
} as StakeIcaTerms,
}) => {
const { zoe, bundleAndInstall } = await setUpZoeForTest();
const installation: Installation<StartFn> =
await bundleAndInstall(contractFile);

const { publicFacet } = await E(zoe).startInstance(
installation,
{ In: bld.issuer },
{
chainId: 'cosmoshub-4',
hostConnectionId: 'connection-1',
controllerConnectionId: 'connection-2',
bondDenom: 'uatom',
},
issuerKeywordRecord,
terms,
{
marshaller,
orchestration,
storageNode: storage.rootNode,
storageNode: storage.rootNode.makeChildNode('stakeAtom'),
timer,
},
);
Expand Down Expand Up @@ -78,3 +75,51 @@ test('makeAccount, getAddress, getBalances, getBalance', async t => {
message: 'Queries not enabled.',
});
});

test('makeAccountInvitationMaker', async t => {
const {
bootstrap,
brands: { ist },
} = await commonSetup(t);
const { publicFacet, zoe } = await startContract({
...bootstrap,
issuerKeywordRecord: { In: ist.issuer },
});
const inv = await E(publicFacet).makeAccountInvitationMaker();
t.log('make an offer for ICA account');
t.log('inv', inv);

const seat = await E(zoe).offer(inv);
t.log('seat', seat);
const offerResult = await E(seat).getOfferResult();

t.like(offerResult, {
publicSubscribers: {
account: {
description: 'Staking Account holder status',
},
},
});

const accountNotifier = makeNotifierFromSubscriber(
offerResult.publicSubscribers.account.subscriber,
);
const storageUpdate = await E(accountNotifier).getUpdateSince();
t.deepEqual(storageUpdate, {
updateCount: 1n,
value: {
sequence: 0n,
},
});

// FIXME mock remoteAddress in ibc bridge
const storagePath =
'mockChainStorageRoot.stakeAtom.accounts.UNPARSABLE_CHAIN_ADDRESS';
const vstorageEntry = bootstrap.storage.data.get(storagePath);
if (typeof vstorageEntry !== 'string') {
t.fail('vstorageEntry not found');
} else {
t.log(storagePath, vstorageEntry);
t.regex(vstorageEntry, /sequence/);
}
});
6 changes: 6 additions & 0 deletions packages/orchestration/test/facade.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js';

import { setupZCFTest } from '@agoric/zoe/test/unitTests/zcf/setupZcfTest.js';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import type { CosmosChainInfo, IBCConnectionInfo } from '../src/cosmos-api.js';
import { makeOrchestrationFacade } from '../src/facade.js';
import type { Chain } from '../src/orchestration-api.js';
Expand Down Expand Up @@ -48,6 +49,10 @@ test('chain info', async t => {

const { zcf } = await setupZCFTest();
const chainHub = makeChainHub(facadeServices.agoricNames);
const { makeRecorderKit } = prepareRecorderKitMakers(
zone.mapStore('recorder'),
bootstrap.marshaller,
);

const { orchestrate } = makeOrchestrationFacade({
...facadeServices,
Expand All @@ -56,6 +61,7 @@ test('chain info', async t => {
zone,
chainHub,
makeLocalChainAccountKit,
makeRecorderKit,
});

chainHub.registerChain('mock', mockChainInfo);
Expand Down
43 changes: 36 additions & 7 deletions packages/orchestration/test/staking-ops.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
MsgUndelegateResponse,
} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx.js';
import { makeScalarBigMapStore, type Baggage } from '@agoric/vat-data';
import { makeFakeBoard } from '@agoric/vats/tools/board-utils.js';
import { decodeBase64 } from '@endo/base64';
import { E, Far } from '@endo/far';
import { buildZoeManualTimer } from '@agoric/zoe/tools/manualTimer.js';
Expand All @@ -16,6 +17,9 @@ import type { Coin } from '@agoric/cosmic-proto/cosmos/base/v1beta1/coin.js';
import type { TimestampRecord, TimestampValue } from '@agoric/time';
import type { AnyJson } from '@agoric/cosmic-proto';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { makeFakeStorageKit } from '@agoric/internal/src/storage-test-utils.js';
import { makeNotifierFromSubscriber } from '@agoric/notifier';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import {
prepareCosmosOrchestrationAccountKit,
trivialDelegateResponse,
Expand Down Expand Up @@ -174,17 +178,16 @@ const makeScenario = () => {
return { zcf, zoe };
};

const makeRecorderKit = () => harden({}) as any;

const baggage = makeScalarBigMapStore('b1') as Baggage;
const zone = makeDurableZone(baggage);
const marshaller = makeFakeBoard().getReadonlyMarshaller();
const { makeRecorderKit } = prepareRecorderKitMakers(baggage, marshaller);

const { delegations, startTime } = configStaking;

// TODO: when we write to chainStorage, test it.
// const { rootNode } = makeFakeStorageKit('mockChainStorageRoot');

const storageNode = Far('StorageNode', {}) as unknown as StorageNode;
const { rootNode } = makeFakeStorageKit('mockChainStorageRoot', {
sequence: false,
});

const icqConnection = Far('ICQConnection', {}) as ICQConnection;

Expand All @@ -197,13 +200,39 @@ const makeScenario = () => {
zone,
makeRecorderKit,
...mockAccount(undefined, delegations),
storageNode,
storageNode: rootNode,
timer,
icqConnection,
...mockZCF(),
};
};

test('makeAccount() writes to storage', async t => {
const s = makeScenario();
const { account, calls, timer } = s;
const { makeRecorderKit, storageNode, zcf, icqConnection, zone } = s;
const make = prepareCosmosOrchestrationAccountKit(zone, makeRecorderKit, zcf);

// Higher fidelity tests below use invitationMakers.
const { holder } = make(account.getAddress(), 'uatom', {
account,
storageNode,
icqConnection,
timer,
});
const { publicSubscribers } = holder.asContinuingOffer();
const accountNotifier = makeNotifierFromSubscriber(
publicSubscribers.account.subscriber,
);
const storageUpdate = await E(accountNotifier).getUpdateSince();
t.deepEqual(storageUpdate, {
updateCount: 1n,
value: {
sequence: 0n,
},
});
});

test('withdrawRewards() on StakingAccountHolder formats message correctly', async t => {
const s = makeScenario();
const { account, calls, timer } = s;
Expand Down

0 comments on commit c2021ba

Please sign in to comment.