Skip to content

Commit

Permalink
feat(orchestration): add init-stakeOsmo.js to support .query tests
Browse files Browse the repository at this point in the history
- a better approach seems to be refactoring start-stakeAtom.js to start-stakeIca.js with parameters. buildProposal doesn't seem to accept options so punted for now
- TODO: register OSMO in bank
  • Loading branch information
0xpatrickdev committed Jun 17, 2024
1 parent b83745f commit b6df6c2
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 80 deletions.
52 changes: 40 additions & 12 deletions packages/boot/test/bootstrapTests/orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,42 @@ test.serial('config', async t => {
}
});

test.serial('stakeOsmo - queries', async t => {
const {
buildProposal,
evalProposal,
runUtils: { EV },
} = t.context;
await evalProposal(
buildProposal('@agoric/builders/scripts/orchestration/init-stakeOsmo.js'),
);

const agoricNames = await EV.vat('bootstrap').consumeItem('agoricNames');
const instance: Instance<typeof startStakeIca> = await EV(agoricNames).lookup(
'instance',
'stakeOsmo',
);
t.truthy(instance, 'stakeOsmo instance is available');

const zoe: ZoeService = await EV.vat('bootstrap').consumeItem('zoe');
const publicFacet = await EV(zoe).getPublicFacet(instance);
t.truthy(publicFacet, 'stakeOsmo publicFacet is available');

const account = await EV(publicFacet).makeAccount();
t.log('account', account);
t.truthy(account, 'makeAccount returns an account on OSMO connection');

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

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

test.serial('stakeAtom - repl-style', async t => {
const {
buildProposal,
Expand Down Expand Up @@ -111,15 +147,9 @@ test.serial('stakeAtom - repl-style', async t => {
};
await t.notThrowsAsync(EV(account).delegate(validatorAddress, atomAmount));

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

const queryUnknownDenom = await EV(account).getBalance('some-invalid-denom');
t.deepEqual(
queryUnknownDenom,
{ value: 0n, denom: 'some-invalid-denom' },
'getBalance for unknown denom returns value: 0n',
);
await t.throwsAsync(EV(account).getBalance('uatom'), {
message: 'Queries not available for chain "cosmoshub-4"',
});
});

test.serial('stakeAtom - smart wallet', async t => {
Expand Down Expand Up @@ -151,9 +181,7 @@ test.serial('stakeAtom - smart wallet', async t => {
t.like(wd.getLatestUpdateRecord(), {
status: { id: 'request-account', numWantsSatisfied: 1 },
});
t.like(readLatest('published.stakeAtom.accounts.cosmos1test'), {
sequence: 0n,
});
t.is(readLatest('published.stakeAtom.accounts.cosmos1test'), '');

const { ATOM } = agoricNamesRemotes.brand;
ATOM || Fail`ATOM missing from agoricNames`;
Expand Down
15 changes: 1 addition & 14 deletions packages/builders/scripts/orchestration/init-stakeAtom.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
export const defaultProposalBuilder = async (
{ publishRef, install },
options = {},
) => {
const {
hostConnectionId = 'connection-1',
controllerConnectionId = 'connection-0',
bondDenom = 'uatom',
icqEnabled = true,
} = options;
export const defaultProposalBuilder = async ({ publishRef, install }) => {
return harden({
sourceSpec: '@agoric/orchestration/src/proposals/start-stakeAtom.js',
getManifestCall: [
Expand All @@ -21,10 +12,6 @@ export const defaultProposalBuilder = async (
install('@agoric/orchestration/src/examples/stakeIca.contract.js'),
),
},
hostConnectionId,
controllerConnectionId,
bondDenom,
icqEnabled,
},
],
});
Expand Down
23 changes: 23 additions & 0 deletions packages/builders/scripts/orchestration/init-stakeOsmo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) => {
return harden({
sourceSpec: '@agoric/orchestration/src/proposals/start-stakeOsmo.js',
getManifestCall: [
'getManifestForStakeOsmo',
{
installKeys: {
stakeIca: publishRef(
install('@agoric/orchestration/src/examples/stakeIca.contract.js'),
),
},
},
],
});
};

export default async (homeP, endowments) => {
const { writeCoreEval } = await makeHelpers(homeP, endowments);
await writeCoreEval('start-stakeOsmo', defaultProposalBuilder);
};
2 changes: 1 addition & 1 deletion packages/orchestration/src/examples/stakeIca.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,4 @@ export const start = async (zcf, privateArgs, baggage) => {
return { publicFacet };
};

/** @typedef {typeof start} StakeAtomSF */
/** @typedef {typeof start} StakeIcaSF */
2 changes: 2 additions & 0 deletions packages/orchestration/src/exos/chainAccountKit.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ export const prepareChainAccountKit = zone =>
this.state.remoteAddress = remoteAddr;
this.state.localAddress = localAddr;
this.state.chainAddress = harden({
// FIXME need a fallback value like icacontroller-1-connection-1 if this fails
// https://github.com/Agoric/agoric-sdk/issues/9066
address: findAddressField(remoteAddr) || UNPARSABLE_CHAIN_ADDRESS,
chainId: this.state.chainId,
addressEncoding: 'bech32',
Expand Down
9 changes: 5 additions & 4 deletions packages/orchestration/src/exos/cosmosOrchestrationAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,8 @@ 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 }));
// TODO determine what goes in vstorage https://github.com/Agoric/agoric-sdk/issues/9066
void E(topicKit.recorder).write('');

return { chainAddress, bondDenom, topicKit, ...rest };
},
Expand Down Expand Up @@ -366,7 +365,9 @@ export const prepareCosmosOrchestrationAccountKit = (
*/
async getBalance(denom) {
const { chainAddress, icqConnection } = this.state;
if (!icqConnection) throw Error('Queries not enabled.');
if (!icqConnection) {
throw Fail`Queries not available for chain ${chainAddress.chainId}`;
}
// TODO #9211 lookup denom from brand
assert.typeof(denom, 'string');

Expand Down
7 changes: 2 additions & 5 deletions packages/orchestration/src/proposals/start-stakeAtom.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { makeChainHub } from '../utils/chainHub.js';

/**
* @import {IBCConnectionID} from '@agoric/vats';
* @import {StakeAtomSF, StakeIcaTerms} from '../examples/stakeIca.contract';
* @import {StakeIcaSF, StakeIcaTerms} from '../examples/stakeIca.contract';
*/

const trace = makeTracer('StartStakeAtom', true);
Expand Down Expand Up @@ -43,8 +43,6 @@ export const startStakeAtom = async ({

const storageNode = await makeStorageNodeChild(chainStorage, VSTORAGE_PATH);
const marshaller = await E(board).getPublishingMarshaller();
const atomIssuer = await E(agoricNames).lookup('issuer', 'ATOM');
trace('ATOM Issuer', atomIssuer);

const chainHub = makeChainHub(await agoricNames);

Expand All @@ -55,11 +53,10 @@ export const startStakeAtom = async ({
cosmoshub.chainId,
);

/** @type {StartUpgradableOpts<StakeAtomSF>} */
/** @type {StartUpgradableOpts<StakeIcaSF>} */
const startOpts = {
label: 'stakeAtom',
installation: stakeIca,
issuerKeywordRecord: harden({ ATOM: atomIssuer }),
terms: {
chainId: cosmoshub.chainId,
hostConnectionId: connectionInfo.id,
Expand Down
109 changes: 109 additions & 0 deletions packages/orchestration/src/proposals/start-stakeOsmo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { makeTracer } from '@agoric/internal';
import { makeStorageNodeChild } from '@agoric/internal/src/lib-chainStorage.js';
import { E } from '@endo/far';
import { makeChainHub } from '../utils/chainHub.js';

/**
* @import {IBCConnectionID} from '@agoric/vats';
* @import {StakeIcaSF} from '../examples/stakeIca.contract';
*/

const trace = makeTracer('StartStakeOsmo', true);

/**
* @param {BootstrapPowers & {
* installation: {
* consume: {
* stakeIca: Installation<
* import('../examples/stakeIca.contract.js').start
* >;
* };
* };
* }} powers
*/
export const startStakeOsmo = async ({
consume: {
agoricNames,
board,
chainStorage,
chainTimerService,
orchestration,
startUpgradable,
},
installation: {
consume: { stakeIca },
},
instance: {
// @ts-expect-error stakeOsmo not typed
produce: { stakeOsmo: produceInstance },
},
}) => {
const VSTORAGE_PATH = 'stakeOsmo';
trace('startStakeOsmo');
await null;

const storageNode = await makeStorageNodeChild(chainStorage, VSTORAGE_PATH);
const marshaller = await E(board).getPublishingMarshaller();

const chainHub = makeChainHub(await agoricNames);

const agoric = await chainHub.getChainInfo('agoric');
const osmosis = await chainHub.getChainInfo('osmosis');
const connectionInfo = await chainHub.getConnectionInfo(
agoric.chainId,
osmosis.chainId,
);

/** @type {StartUpgradableOpts<StakeIcaSF>} */
const startOpts = {
label: 'stakeOsmo',
installation: stakeIca,
terms: {
chainId: osmosis.chainId,
hostConnectionId: connectionInfo.id,
controllerConnectionId: connectionInfo.counterparty.connection_id,
bondDenom: osmosis.stakingTokens[0].denom,
icqEnabled: osmosis.icqEnabled,
},
privateArgs: {
orchestration: await orchestration,
storageNode,
marshaller,
timer: await chainTimerService,
},
};

const { instance } = await E(startUpgradable)(startOpts);
produceInstance.resolve(instance);
};
harden(startStakeOsmo);

export const getManifestForStakeOsmo = (
{ restoreRef },
{ installKeys, ...options },
) => {
return {
manifest: {
[startStakeOsmo.name]: {
consume: {
agoricNames: true,
board: true,
chainStorage: true,
chainTimerService: true,
orchestration: true,
startUpgradable: true,
},
installation: {
consume: { stakeIca: true },
},
instance: {
produce: { stakeOsmo: true },
},
},
},
installations: {
stakeIca: restoreRef(installKeys.stakeIca),
},
options,
};
};
35 changes: 10 additions & 25 deletions packages/orchestration/test/examples/stake-atom.contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const startContract = async ({
timer,
marshaller,
storage,
issuerKeywordRecord,
issuerKeywordRecord = undefined,
terms = {
chainId: 'cosmoshub-4',
hostConnectionId: 'connection-1',
Expand Down Expand Up @@ -52,15 +52,13 @@ test('makeAccount, getAddress, getBalances, getBalance', async t => {
brands: { ist },
utils,
} = await commonSetup(t);
const { publicFacet } = await startContract({
...bootstrap,
issuerKeywordRecord: { In: ist.issuer },
});
const { publicFacet } = await startContract(bootstrap);

t.log('make an ICA account');
const account = await E(publicFacet).makeAccount();
t.truthy(account, 'account is returned');
const chainAddress = await E(account).getAddress();
// FIXME mock remoteAddress in ibc bridge. Currently UNPARSABLE_CHAIN_ADDRESS
// t.regex(address.address, /cosmos1/);
t.like(chainAddress, { chainId: 'cosmoshub-4', addressEncoding: 'bech32' });

Expand All @@ -72,25 +70,17 @@ test('makeAccount, getAddress, getBalances, getBalance', async t => {
});

await t.throwsAsync(E(account).getBalance('uatom'), {
message: 'Queries not enabled.',
message: 'Queries not available for chain "cosmoshub-4"',
});
});

test('makeAccountInvitationMaker', async t => {
const {
bootstrap,
brands: { ist },
} = await commonSetup(t);
const { publicFacet, zoe } = await startContract({
...bootstrap,
issuerKeywordRecord: { In: ist.issuer },
});
const { bootstrap } = await commonSetup(t);
const { publicFacet, zoe } = await startContract(bootstrap);
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, {
Expand All @@ -107,19 +97,14 @@ test('makeAccountInvitationMaker', async t => {
const storageUpdate = await E(accountNotifier).getUpdateSince();
t.deepEqual(storageUpdate, {
updateCount: 1n,
value: {
sequence: 0n,
},
value: '',
});

// 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/);
}
t.truthy(vstorageEntry, 'vstorage account entry created');
t.log(storagePath, vstorageEntry);
t.is(bootstrap.marshaller.fromCapData(JSON.parse(vstorageEntry!)), '');
});
Loading

0 comments on commit b6df6c2

Please sign in to comment.