Skip to content

Commit

Permalink
feat: amountToCoin accepts any denom
Browse files Browse the repository at this point in the history
- still does not support brand lookups (see #9211)
- throws error if a brand is provided instead of warning in the console
- moves bondDenom check to delegate method to preserve functionality
- also includes this helper on LocalOrchestrationAccount
  • Loading branch information
0xpatrickdev committed Aug 9, 2024
1 parent 49fc4c7 commit 99b1704
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 20 deletions.
40 changes: 31 additions & 9 deletions packages/boot/test/bootstrapTests/orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const validatorAddress: CosmosValidatorAddress = {
encoding: 'bech32',
};

const ATOM_DENOM = 'uatom';

test.before(async t => {
t.context = await makeWalletFactoryContext(
t,
Expand All @@ -43,7 +45,7 @@ test.serial('config', async t => {
const cosmosChainInfo = await EV(agoricNames).lookup('chain', 'cosmoshub');
t.like(cosmosChainInfo, {
chainId: 'cosmoshub-4',
stakingTokens: [{ denom: 'uatom' }],
stakingTokens: [{ denom: ATOM_DENOM }],
});
t.deepEqual(
readLatest(`published.agoricNames.chain.cosmoshub`),
Expand Down Expand Up @@ -120,8 +122,8 @@ test.skip('stakeOsmo - queries', async t => {
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 queryRes = await EV(account).getBalance(ATOM_DENOM);
t.deepEqual(queryRes, { value: 0n, denom: ATOM_DENOM });

const queryUnknownDenom = await EV(account).getBalance('some-invalid-denom');
t.deepEqual(
Expand Down Expand Up @@ -184,7 +186,7 @@ test.serial('stakeAtom - smart wallet', async t => {
source: 'continuing',
previousOffer: 'request-account',
invitationMakerName: 'Delegate',
invitationArgs: [validatorAddress, { brand: ATOM, value: 10n }],
invitationArgs: [validatorAddress, { denom: ATOM_DENOM, value: 10n }],
},
proposal: {},
});
Expand All @@ -206,7 +208,10 @@ test.serial('stakeAtom - smart wallet', async t => {
source: 'continuing',
previousOffer: 'request-account',
invitationMakerName: 'Delegate',
invitationArgs: [validatorAddressFail, { brand: ATOM, value: 10n }],
invitationArgs: [
validatorAddressFail,
{ denom: ATOM_DENOM, value: 10n },
],
},
proposal: {},
}),
Expand All @@ -215,6 +220,24 @@ test.serial('stakeAtom - smart wallet', async t => {
},
'delegate fails with invalid validator',
);

// This will trigger the immediate ack of the mock bridge
await t.throwsAsync(
wd.executeOffer({
id: 'request-delegate-brand',
invitationSpec: {
source: 'continuing',
previousOffer: 'request-account',
invitationMakerName: 'Delegate',
invitationArgs: [validatorAddress, { brand: ATOM, value: 10n }],
},
proposal: {},
}),
{
message: 'Brands not currently supported.',
},
'brands not currently supported',
);
});

test.todo('undelegate wallet offer');
Expand Down Expand Up @@ -393,8 +416,7 @@ test.serial('basic-flows - portfolio holder', async t => {
// XXX this overrides a previous account, since mocks only provide one address
t.is(readLatest('published.basicFlows.agoric1mockVlocalchainAddress'), '');

const { ATOM, BLD } = agoricNamesRemotes.brand;
ATOM || Fail`ATOM missing from agoricNames`;
const { BLD } = agoricNamesRemotes.brand;
BLD || Fail`BLD missing from agoricNames`;

await wd.sendOffer({
Expand All @@ -406,7 +428,7 @@ test.serial('basic-flows - portfolio holder', async t => {
invitationArgs: [
'cosmoshub',
'Delegate',
[validatorAddress, { brand: ATOM, value: 10n }],
[validatorAddress, { denom: ATOM_DENOM, value: 10n }],
],
},
proposal: {},
Expand Down Expand Up @@ -444,7 +466,7 @@ test.serial('basic-flows - portfolio holder', async t => {
invitationArgs: [
'cosmoshub',
'Delegate',
[validatorAddress, { brand: ATOM, value: 504n }],
[validatorAddress, { denom: ATOM_DENOM, value: 504n }],
],
},
proposal: {},
Expand Down
3 changes: 2 additions & 1 deletion packages/boot/test/orchestration/restart-contracts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ const validatorAddress: CosmosValidatorAddress = {
chainId: 'gaiatest',
encoding: 'bech32',
};
const ATOM_DENOM = 'uatom';

// check for key because the value will be 'undefined' when the result is provided
// TODO should it be something truthy?
Expand Down Expand Up @@ -152,7 +153,7 @@ test.serial('stakeAtom', async t => {
source: 'continuing',
previousOffer: 'request-account',
invitationMakerName: 'Delegate',
invitationArgs: [validatorAddress, { brand: ATOM, value: 10n }],
invitationArgs: [validatorAddress, { denom: ATOM_DENOM, value: 10n }],
},
proposal: {},
});
Expand Down
19 changes: 10 additions & 9 deletions packages/orchestration/src/exos/cosmos-orchestration-account.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,13 @@ export const prepareCosmosOrchestrationAccountKit = (
* @returns {Coin}
*/
amountToCoin(amount) {
const { bondDenom } = this.state;
if ('denom' in amount) {
assert.equal(amount.denom, bondDenom);
} else {
trace('TODO: handle brand', amount);
// FIXME(#9211) brand handling
if (!('denom' in amount)) {
// FIXME(#9211) look up values from brands
trace('TODO #9211: handle brand', amount);
throw Fail`Brands not currently supported.`;
}
return harden({
denom: bondDenom,
denom: amount.denom,
amount: String(amount.value),
});
},
Expand Down Expand Up @@ -358,14 +356,17 @@ export const prepareCosmosOrchestrationAccountKit = (
return asVow(() => {
trace('delegate', validator, amount);
const { helper } = this.facets;
const { chainAddress } = this.state;
const { chainAddress, bondDenom } = this.state;

const amountAsCoin = helper.amountToCoin(amount);
assert.equal(amountAsCoin.denom, bondDenom);

const results = E(helper.owned()).executeEncodedTx([
Any.toJSON(
MsgDelegate.toProtoMsg({
delegatorAddress: chainAddress.value,
validatorAddress: validator.value,
amount: helper.amountToCoin(amount),
amount: amountAsCoin,
}),
),
]);
Expand Down
22 changes: 22 additions & 0 deletions packages/orchestration/src/exos/local-orchestration-account.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { VowShape } from '@agoric/vow';
import { E } from '@endo/far';

import {
AmountArgShape,
ChainAddressShape,
DenomAmountShape,
DenomShape,
Expand All @@ -32,6 +33,7 @@ import { prepareIBCTools } from './ibc-packet.js';
* @import {TimerService, TimestampRecord} from '@agoric/time';
* @import {PromiseVow, EVow, Vow, VowTools} from '@agoric/vow';
* @import {TypedJson, JsonSafe, ResponseTo} from '@agoric/cosmic-proto';
* @import {Coin} from '@agoric/cosmic-proto/cosmos/base/v1beta1/coin.js';
* @import {Matcher, Pattern} from '@endo/patterns';
* @import {ChainHub} from './chain-hub.js';
* @import {PacketTools} from './packet-tools.js';
Expand Down Expand Up @@ -108,6 +110,9 @@ export const prepareLocalOrchestrationAccountKit = (
const makeLocalOrchestrationAccountKit = zone.exoClassKit(
'Local Orchestration Account Kit',
{
helper: M.interface('helper', {
amountToCoin: M.call(AmountArgShape).returns(M.record()),
}),
holder: HolderI,
undelegateWatcher: M.interface('undelegateWatcher', {
onFulfilled: M.call([
Expand Down Expand Up @@ -166,6 +171,23 @@ export const prepareLocalOrchestrationAccountKit = (
return { account, address, topicKit, packetTools };
},
{
helper: {
/**
* @param {AmountArg} amount
* @returns {Coin}
*/
amountToCoin(amount) {
if (!('denom' in amount)) {
// FIXME(#9211) look up values from brands
trace('TODO #9211: handle brand', amount);
throw Fail`Brands not currently supported.`;
}
return harden({
denom: amount.denom,
amount: String(amount.value),
});
},
},
invitationMakers: {
/**
* @param {string} validatorAddress
Expand Down
2 changes: 1 addition & 1 deletion packages/orchestration/test/staking-ops.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ test(`delegate; redelegate using invitationMakers`, async t => {
{
const { validator: dst } = configRedelegate;
const value = BigInt(Object.values(configRedelegate.delegations)[0].amount);
const anAmount = { brand: aBrand, value };
const anAmount = { denom: 'uatom', value };
const toRedelegate = await E(invitationMakers).Redelegate(
validator,
dst,
Expand Down

0 comments on commit 99b1704

Please sign in to comment.