Skip to content

Commit

Permalink
feat(orchestration): add queryBalance to stakeAtom
Browse files Browse the repository at this point in the history
- refs: Agoric#9042
  • Loading branch information
0xpatrickdev committed May 2, 2024
1 parent ce0f0fd commit 2a12810
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 64 deletions.
11 changes: 11 additions & 0 deletions packages/boot/test/bootstrapTests/test-orchestration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ test.serial('stakeAtom - repl-style', async t => {

const res = await EV(account).delegate('cosmosvaloper1test', atomAmount);
t.is(res, 'Success', 'delegate returns Success');

const queryRes = await EV(account).queryBalance();
t.deepEqual(queryRes, { amount: '0', denom: 'uatom' });

const queryUnknownDenom =
await EV(account).queryBalance('some-invalid-denom');
t.deepEqual(
queryUnknownDenom,
{ amount: '0', denom: 'some-invalid-denom' },
'queryBalance for unknown denom returns amount: 0',
);
});

test.serial('stakeAtom - smart wallet', async t => {
Expand Down
45 changes: 37 additions & 8 deletions packages/boot/test/bootstrapTests/test-vat-orchestration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
MsgDelegateResponse,
} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx.js';
import { RequestQuery } from '@agoric/cosmic-proto/tendermint/abci/types.js';
import type { OrchestrationService } from '@agoric/orchestration';
import type {
OrchestrationService,
ICQConnection,
} from '@agoric/orchestration';
import { decodeBase64 } from '@endo/base64';
import { M, matches } from '@endo/patterns';
import { makeWalletFactoryContext } from './walletFactory.ts';
Expand Down Expand Up @@ -198,12 +201,12 @@ test('Query connection can be created', async t => {
type Powers = { orchestration: OrchestrationService };
const contract = async ({ orchestration }: Powers) => {
const connection =
await EV(orchestration).createQueryConnection('connection-0');
await EV(orchestration).provideICQConnection('connection-0');
t.log('Query Connection', connection);
t.truthy(connection, 'createQueryConnection returns a connection');
t.truthy(connection, 'provideICQConnection returns a connection');
t.truthy(
matches(connection, M.remotable('QueryConnection')),
'QueryConnection is a remotable',
matches(connection, M.remotable('ICQConnection')),
'ICQConnection is a remotable',
);
};

Expand All @@ -221,9 +224,9 @@ test('Query connection can send a query', async t => {
} = t.context;

type Powers = { orchestration: OrchestrationService };
const contract = async ({ orchestration }: { Powers }) => {
const queryConnection: QueryConnection =
await EV(orchestration).createQueryConnection('connection-0');
const contract = async ({ orchestration }: Powers) => {
const queryConnection: ICQConnection =
await EV(orchestration).provideICQConnection('connection-0');

const [result] = await EV(queryConnection).query([balanceQuery]);
t.is(result.code, 0);
Expand Down Expand Up @@ -267,3 +270,29 @@ test('Query connection can send a query', async t => {
await contract({ orchestration });
}
});

test('provideICQConnection is idempotent', async t => {
const {
runUtils: { EV },
} = t.context;
const orchestration: OrchestrationService =
await EV.vat('bootstrap').consumeItem('orchestration');

const queryConn0 =
await EV(orchestration).provideICQConnection('connection-0');
const queryConn1 =
await EV(orchestration).provideICQConnection('connection-1');
const queryConn02 =
await EV(orchestration).provideICQConnection('connection-0');

const [addr0, addr1, addr02] = await Promise.all([
EV(queryConn0).getRemoteAddress(),
EV(queryConn1).getRemoteAddress(),
EV(queryConn02).getRemoteAddress(),
]);
t.is(addr0, addr02);
t.not(addr0, addr1);

const [result] = await EV(queryConn02).query([balanceQuery]);
t.is(result.code, 0, 'ICQConnectionKit from MapStore state can send queries');
});
2 changes: 2 additions & 0 deletions packages/builders/scripts/orchestration/init-stakeAtom.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultProposalBuilder = async (
const {
hostConnectionId = 'connection-1',
controllerConnectionId = 'connection-0',
bondDenom = 'uatom',
} = options;
return harden({
sourceSpec: '@agoric/orchestration/src/proposals/start-stakeAtom.js',
Expand All @@ -21,6 +22,7 @@ export const defaultProposalBuilder = async (
},
hostConnectionId,
controllerConnectionId,
bondDenom,
},
],
});
Expand Down
18 changes: 12 additions & 6 deletions packages/orchestration/src/examples/stakeAtom.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import { prepareStakingAccountKit } from '../exos/stakingAccountKit.js';

const trace = makeTracer('StakeAtom');
/**
* @import { OrchestrationService } from '../service.js'
* @import { Baggage } from '@agoric/vat-data';
* @import { IBCConnectionID } from '@agoric/vats';
* @import { ICQConnection, OrchestrationService } from '../types.js';
*/

/**
* @typedef {{
* hostConnectionId: IBCConnectionID;
* controllerConnectionId: IBCConnectionID;
* bondDenom: string;
* }} StakeAtomTerms
*/

Expand All @@ -30,12 +31,15 @@ const trace = makeTracer('StakeAtom');
* orchestration: OrchestrationService;
* storageNode: StorageNode;
* marshaller: Marshaller;
* icqConnection: ICQConnection
* }} privateArgs
* @param {Baggage} baggage
*/
export const start = async (zcf, privateArgs, baggage) => {
const { hostConnectionId, controllerConnectionId } = zcf.getTerms();
const { orchestration, marshaller, storageNode } = privateArgs;
// TODO #9063 this roughly matches what we'll get from Chain<C>.getChainInfo()
const { hostConnectionId, controllerConnectionId, bondDenom } =
zcf.getTerms();
const { orchestration, marshaller, storageNode, icqConnection } = privateArgs;

const zone = makeDurableZone(baggage);

Expand All @@ -52,12 +56,14 @@ export const start = async (zcf, privateArgs, baggage) => {
hostConnectionId,
controllerConnectionId,
);
const address = await E(account).getAddress();
trace('chain address', address);
const accountAddress = await E(account).getAddress();
trace('account address', accountAddress);
const { holder, invitationMakers } = makeStakingAccountKit(
account,
storageNode,
address,
accountAddress,
icqConnection,
bondDenom,
);
return {
publicSubscribers: holder.getPublicTopics(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @ts-check
/** @file QueryConnection Exo */
/** @file ICQConnection Exo */
import { NonNullish } from '@agoric/assert';
import { makeTracer } from '@agoric/internal';
import { V as E } from '@agoric/vat-data/vow.js';
Expand All @@ -17,24 +17,24 @@ import { ConnectionHandlerI } from '../typeGuards.js';
*/

const { Fail } = assert;
const trace = makeTracer('Orchestration:QueryConnection');
const trace = makeTracer('Orchestration:ICQConnection');

export const QueryMsgShape = M.splitRecord(
export const ICQMsgShape = M.splitRecord(
{ path: M.string(), data: M.string() },
{ height: M.string(), prove: M.boolean() },
);

export const QueryConnectionI = M.interface('QueryConnection', {
export const ICQConnectionI = M.interface('ICQConnection', {
getLocalAddress: M.call().returns(M.string()),
getRemoteAddress: M.call().returns(M.string()),
query: M.call(M.arrayOf(QueryMsgShape)).returns(M.promise()),
query: M.call(M.arrayOf(ICQMsgShape)).returns(M.promise()),
});

/** @param {Zone} zone */
export const prepareQueryConnectionKit = zone =>
export const prepareICQConnectionKit = zone =>
zone.exoClassKit(
'QueryConnectionKit',
{ connection: QueryConnectionI, connectionHandler: ConnectionHandlerI },
'ICQConnectionKit',
{ connection: ICQConnectionI, connectionHandler: ConnectionHandlerI },
/**
* @param {Port} port
*/
Expand Down Expand Up @@ -106,5 +106,5 @@ export const prepareQueryConnectionKit = zone =>
},
);

/** @typedef {ReturnType<ReturnType<typeof prepareQueryConnectionKit>>} QueryConnectionKit */
/** @typedef {QueryConnectionKit['connection']} QueryConnection */
/** @typedef {ReturnType<ReturnType<typeof prepareICQConnectionKit>>} ICQConnectionKit */
/** @typedef {ICQConnectionKit['connection']} ICQConnection */
Loading

0 comments on commit 2a12810

Please sign in to comment.