Skip to content

Commit

Permalink
feat: implement OrchestrationAccountI .send() and .sendAll() methods (
Browse files Browse the repository at this point in the history
#9870)

refs: #9193

## Description

Implements `.send()` and `.sendAll()` methods on CosmosOrchestrationAccount and LocalOrchestrationAccount

### Security Considerations
n/a

### Scaling Considerations
n/a

### Documentation Considerations
n/a

### Testing Considerations
Includes unit tests

### Upgrade Considerations
n/a, yet to be released
  • Loading branch information
mergify[bot] authored Aug 9, 2024
2 parents d3223ae + 8131c72 commit 644c210
Show file tree
Hide file tree
Showing 18 changed files with 585 additions and 116 deletions.
76 changes: 74 additions & 2 deletions packages/boot/test/bootstrapTests/lca.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { TestFn } from 'ava';
import { Fail } from '@endo/errors';
import type { start as stakeBldStart } from '@agoric/orchestration/src/examples/stakeBld.contract.js';
import type { Instance } from '@agoric/zoe/src/zoeService/utils.js';
import { SIMULATED_ERRORS } from '@agoric/vats/tools/fake-bridge.js';
import {
makeWalletFactoryContext,
type WalletFactoryTestContext,
Expand Down Expand Up @@ -100,17 +101,88 @@ test.serial('stakeBld', async t => {
source: 'continuing',
previousOffer: 'request-stake',
invitationMakerName: 'Delegate',
invitationArgs: ['agoric1validator1', { brand: BLD, value: 504n }],
invitationArgs: [
'agoric1validator1',
{ brand: BLD, value: SIMULATED_ERRORS.TIMEOUT },
],
},
proposal: {
give: {
// @ts-expect-error XXX BoardRemote
In: { brand: BLD, value: 504n },
In: { brand: BLD, value: SIMULATED_ERRORS.TIMEOUT },
},
},
}),
// TODO propagate error message through bridge
// FIXME should receive "simulated packet timeout" error
// { message: 'simulated packet timeout' },
);

await wd.executeOffer({
id: 'bank-send',
invitationSpec: {
source: 'continuing',
previousOffer: 'request-stake',
invitationMakerName: 'Send',
},
proposal: {},
offerArgs: {
toAccount: {
value: 'agoric1EOAAccAddress',
chainId: 'agoriclocal',
encoding: 'bech32',
},
amount: { denom: 'ibc/1234', value: 10n },
},
});
t.like(wd.getLatestUpdateRecord(), {
status: { id: 'bank-send', numWantsSatisfied: 1 },
});

await wd.executeOffer({
id: 'bank-sendAll',
invitationSpec: {
source: 'continuing',
previousOffer: 'request-stake',
invitationMakerName: 'SendAll',
},
proposal: {},
offerArgs: {
toAccount: {
value: 'agoric1EOAAccAddress',
chainId: 'agoriclocal',
encoding: 'bech32',
},
amounts: [
{ denom: 'uatom', value: 10n },
{ denom: 'ibc/1234', value: 10n },
],
},
});
t.like(wd.getLatestUpdateRecord(), {
status: { id: 'bank-sendAll', numWantsSatisfied: 1 },
});

await t.throwsAsync(
wd.executeOffer({
id: 'bank-send-fail',
invitationSpec: {
source: 'continuing',
previousOffer: 'request-stake',
invitationMakerName: 'Send',
},
proposal: {},
offerArgs: {
toAccount: {
value: 'agoric1EOAAccAddress',
chainId: 'agoriclocal',
encoding: 'bech32',
},
amount: {
denom: 'ibc/1234',
value: SIMULATED_ERRORS.BAD_REQUEST,
},
},
}),
);
});
49 changes: 39 additions & 10 deletions packages/boot/test/bootstrapTests/orchestration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { CosmosValidatorAddress } from '@agoric/orchestration';
import type { start as startStakeIca } from '@agoric/orchestration/src/examples/stakeIca.contract.js';
import type { Instance } from '@agoric/zoe/src/zoeService/utils.js';
import type { TestFn } from 'ava';
import { SIMULATED_ERRORS } from '@agoric/vats/tools/fake-bridge.js';
import {
makeWalletFactoryContext,
type WalletFactoryTestContext,
Expand All @@ -19,6 +20,8 @@ const validatorAddress: CosmosValidatorAddress = {
encoding: 'bech32',
};

const ATOM_DENOM = 'uatom';

test.before(async t => {
t.context = await makeWalletFactoryContext(
t,
Expand All @@ -43,7 +46,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 +123,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 +187,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 +209,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 +221,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 +417,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 +429,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 +467,10 @@ test.serial('basic-flows - portfolio holder', async t => {
invitationArgs: [
'cosmoshub',
'Delegate',
[validatorAddress, { brand: ATOM, value: 504n }],
[
validatorAddress,
{ denom: ATOM_DENOM, value: SIMULATED_ERRORS.TIMEOUT },
],
],
},
proposal: {},
Expand All @@ -461,7 +487,10 @@ test.serial('basic-flows - portfolio holder', async t => {
invitationArgs: [
'agoric',
'Delegate',
['agoric1validator1', { brand: BLD, value: 504n }],
[
'agoric1validator1',
{ brand: BLD, value: SIMULATED_ERRORS.TIMEOUT },
],
],
},
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
29 changes: 10 additions & 19 deletions packages/boot/tools/supports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { loadSwingsetConfigFile } from '@agoric/swingset-vat';
import { makeSlogSender } from '@agoric/telemetry';
import { TimeMath, Timestamp } from '@agoric/time';
import { Fail } from '@endo/errors';
import { fakeLocalChainBridgeTxMsgHandler } from '@agoric/vats/tools/fake-bridge.js';

import {
makeRunUtils,
Expand Down Expand Up @@ -321,7 +322,9 @@ export const makeSwingsetTestKit = async (
return data;
};

let lastNonce = 0n;
let lastBankNonce = 0n;
let ibcSequenceNonce = 0;
let lcaSequenceNonce = 0;

const outboundMessages = new Map();

Expand All @@ -332,7 +335,6 @@ export const makeSwingsetTestKit = async (
// eslint-disable-next-line no-use-before-define
bridgeInbound!(...args);
};
let ibcSequenceNonce = 0;

/**
* Adds the sequence so the bridge knows what response to connect it to.
Expand Down Expand Up @@ -431,11 +433,11 @@ export const makeSwingsetTestKit = async (

case `${BridgeId.BANK}:VBANK_GRAB`:
case `${BridgeId.BANK}:VBANK_GIVE`: {
lastNonce += 1n;
lastBankNonce += 1n;
// Also empty balances.
return harden({
type: 'VBANK_BALANCE_UPDATE',
nonce: `${lastNonce}`,
nonce: `${lastBankNonce}`,
updated: [],
});
}
Expand Down Expand Up @@ -491,21 +493,10 @@ export const makeSwingsetTestKit = async (
return 'agoric1mockVlocalchainAddress';
}
case `${BridgeId.VLOCALCHAIN}:VLOCALCHAIN_EXECUTE_TX`: {
return obj.messages.map(message => {
switch (message['@type']) {
case '/cosmos.staking.v1beta1.MsgDelegate': {
if (message.amount.amount === '504') {
// FIXME - how can we propagate the error?
// this results in `syscall.callNow failed: device.invoke failed, see logs for details`
throw Error('simulated packet timeout');
}
return {} as JsonSafe<MsgDelegateResponse>;
}
// returns one empty object per message unless specified
default:
return {};
}
});
lcaSequenceNonce += 1;
return obj.messages.map(message =>
fakeLocalChainBridgeTxMsgHandler(message, lcaSequenceNonce),
);
}
default: {
throw Error(`FIXME missing support for ${bridgeId}: ${obj.type}`);
Expand Down
4 changes: 4 additions & 0 deletions packages/cosmic-proto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
"types": "./dist/codegen/cosmos/bank/v1beta1/query.d.ts",
"default": "./dist/codegen/cosmos/bank/v1beta1/query.js"
},
"./cosmos/bank/v1beta1/tx.js": {
"types": "./dist/codegen/cosmos/bank/v1beta1/tx.d.ts",
"default": "./dist/codegen/cosmos/bank/v1beta1/tx.js"
},
"./cosmos/distribution/v1beta1/tx.js": {
"types": "./dist/codegen/cosmos/distribution/v1beta1/tx.d.ts",
"default": "./dist/codegen/cosmos/distribution/v1beta1/tx.js"
Expand Down
3 changes: 3 additions & 0 deletions packages/orchestration/src/exos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ classDiagram
getPublicTopics()
monitorTransfers()
send()
sendAll()
transfer()
undelegate()
withdraw()
Expand All @@ -117,6 +118,8 @@ classDiagram
getBalance()
getPublicTopics()
redelegate()
send()
sendAll()
undelegate()
withdrawReward()
}
Expand Down
Loading

0 comments on commit 644c210

Please sign in to comment.