Skip to content

Commit

Permalink
10016 StakingAccountQueries (#10069)
Browse files Browse the repository at this point in the history
closes: #10016

## Description

Implements the `StakingAccountQueries`. Except for `getRedelegation` because there is no query that's guaranteed to return one. It's a strict subset of what's returned by `getRedelegations`. If there are ever use cases in which that payload is too large we can optimize then.

This also massages the return types in cosmos-api.ts to more closely match what is returned by the Cosmos query endpoints. (No longer dropping data.)

### Security Considerations
The queries are read-only. Like any query there is a risk of resource exhaustion. These aren't rate limited but since they run in a vat the malicious code would exhaust itself. The risks of exhausting the RPC server are no greater than any off-chain query.

### Scaling Considerations
May benefit from some load testing in production-ish environment to see what the service can handle.

### Documentation Considerations

The interface is already documented. This implements it so nothing changes (other than the return types, as mentioned above)

### Testing Considerations
New tests

### Upgrade Considerations
No vats yet use this code.
  • Loading branch information
mergify[bot] committed Sep 17, 2024
2 parents b5575d3 + c006436 commit f291362
Show file tree
Hide file tree
Showing 13 changed files with 1,091 additions and 58 deletions.
44 changes: 33 additions & 11 deletions packages/orchestration/src/cosmos-api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { AnyJson, TypedJson, JsonSafe } from '@agoric/cosmic-proto';
import type {
Delegation,
DelegationResponse,
Redelegation,
RedelegationResponse,
UnbondingDelegation,
} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/staking.js';
import type { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js';
Expand All @@ -26,6 +28,7 @@ import type {
LocalIbcAddress,
RemoteIbcAddress,
} from '@agoric/vats/tools/ibc-utils.js';
import type { QueryDelegationTotalRewardsResponse } from '@agoric/cosmic-proto/cosmos/distribution/v1beta1/query.js';
import type { AmountArg, ChainAddress, Denom, DenomAmount } from './types.js';

/** An address for a validator on some blockchain, e.g., cosmos, eth, etc. */
Expand Down Expand Up @@ -97,6 +100,24 @@ export type CosmosChainInfo = Readonly<{
stakingTokens?: Readonly<Array<{ denom: string }>>;
}>;

// #region Orchestration views on Cosmos response types
// Naming scheme: Cosmos for the chain system, Rewards b/c getRewards function,
// and Response because it's the return value.

/** @see {QueryDelegationTotalRewardsResponse} */
export interface CosmosRewardsResponse {
rewards: { validator: CosmosValidatorAddress; reward: DenomAmount[] }[];
total: DenomAmount[];
}

/** @see {DelegationResponse} */
export interface CosmosDelegationResponse {
delegator: ChainAddress;
validator: CosmosValidatorAddress;
amount: DenomAmount;
}
// #endregion

/**
* Queries for the staking properties of an account.
*
Expand All @@ -107,13 +128,15 @@ export interface StakingAccountQueries {
/**
* @returns all active delegations from the account to any validator (or [] if none)
*/
getDelegations: () => Promise<Delegation[]>;
getDelegations: () => Promise<CosmosDelegationResponse[]>;

/**
* @returns the active delegation from the account to a specific validator. Return an
* empty Delegation if there is no delegation.
*/
getDelegation: (validator: CosmosValidatorAddress) => Promise<Delegation>;
getDelegation: (
validator: CosmosValidatorAddress,
) => Promise<CosmosDelegationResponse>;

/**
* @returns the unbonding delegations from the account to any validator (or [] if none)
Expand All @@ -127,18 +150,13 @@ export interface StakingAccountQueries {
validator: CosmosValidatorAddress,
) => Promise<UnbondingDelegation>;

getRedelegations: () => Promise<Redelegation[]>;

getRedelegation: (
srcValidator: CosmosValidatorAddress,
dstValidator?: CosmosValidatorAddress,
) => Promise<Redelegation>;
getRedelegations: () => Promise<RedelegationResponse[]>;

/**
* Get the pending rewards for the account.
* @returns the amounts of the account's rewards pending from all validators
*/
getRewards: () => Promise<DenomAmount[]>;
getRewards: () => Promise<CosmosRewardsResponse>;

/**
* Get the rewards pending with a specific validator.
Expand Down Expand Up @@ -187,7 +205,11 @@ export interface StakingAccountActions {
* @param delegations - the delegation to undelegate
*/
undelegate: (
delegations: { amount: AmountArg; validator: CosmosValidatorAddress }[],
delegations: {
amount: AmountArg;
delegator?: ChainAddress;
validator: CosmosValidatorAddress;
}[],
) => Promise<void>;

/**
Expand Down Expand Up @@ -307,7 +329,7 @@ export type CosmosChainAccountMethods<CCI extends CosmosChainInfo> =
CCI extends {
stakingTokens: {};
}
? StakingAccountActions
? StakingAccountActions & StakingAccountQueries
: {};

export type ICQQueryFunction = (
Expand Down
8 changes: 4 additions & 4 deletions packages/orchestration/src/examples/unbond.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ import * as flows from './unbond.flows.js';
* @param {OrchestrationTools} tools
*/
const contract = async (zcf, privateArgs, zone, { orchestrateAll }) => {
const { unbondAndLiquidStake } = orchestrateAll(flows, { zcf });
const { unbondAndTransfer } = orchestrateAll(flows, { zcf });

const publicFacet = zone.exo('publicFacet', undefined, {
makeUnbondAndLiquidStakeInvitation() {
makeUnbondAndTransferInvitation() {
return zcf.makeInvitation(
unbondAndLiquidStake,
'Unbond and liquid stake',
unbondAndTransfer,
'Unbond and transfer',
undefined,
harden({
// Nothing to give; the funds come from undelegating
Expand Down
35 changes: 14 additions & 21 deletions packages/orchestration/src/examples/unbond.flows.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
import { makeTracer } from '@agoric/internal';

const trace = makeTracer('UnbondAndTransfer');

/**
* @import {Orchestrator, OrchestrationFlow} from '../types.js'
* @import {TimerService} from '@agoric/time';
* @import {LocalChain} from '@agoric/vats/src/localchain.js';
* @import {NameHub} from '@agoric/vats';
* @import {Remote} from '@agoric/internal';
* @import {Zone} from '@agoric/zone';
* @import {CosmosInterchainService} from '../exos/exo-interfaces.js';
* @import {OrchestrationTools} from '../utils/start-helper.js';
* @import {Orchestrator, OrchestrationFlow, CosmosDelegationResponse} from '../types.js'
* @import {DelegationResponse} from '@agoric/cosmic-proto/cosmos/staking/v1beta1/staking.js';
*/

/**
* @satisfies {OrchestrationFlow}
* @param {Orchestrator} orch
* @param {object} ctx
* @param {ZCF} ctx.zcf
* @param {ZCFSeat} _seat
* @param {undefined} _offerArgs
*/
export const unbondAndLiquidStake = async (
orch,
{ zcf },
_seat,
_offerArgs,
) => {
export const unbondAndTransfer = async (orch, { zcf }) => {
console.log('zcf within the membrane', zcf);
// Osmosis is one of the few chains with icqEnabled
const osmosis = await orch.getChain('osmosis');
// In a real world scenario, accounts would be re-used across invokations of the handler
const osmoAccount = await osmosis.makeAccount();

// TODO https://github.com/Agoric/agoric-sdk/issues/10016
// const delegations = await celestiaAccount.getDelegations();
// // wait for the undelegations to be complete (may take weeks)
// await celestiaAccount.undelegate(delegations);
/** @type {CosmosDelegationResponse[]} Cosmos */
const delegations = await osmoAccount.getDelegations();
trace('delegations', delegations);
// wait for the undelegations to be complete (may take weeks)
await osmoAccount.undelegate(delegations);

// ??? should this be synchronous? depends on how names are resolved.
const stride = await orch.getChain('stride');
const strideAccount = await stride.makeAccount();
Expand All @@ -44,4 +37,4 @@ export const unbondAndLiquidStake = async (
// await strideAccount.liquidStake(tiaAmt);
console.log(osmoAccount, strideAccount);
};
harden(unbondAndLiquidStake);
harden(unbondAndTransfer);
Loading

0 comments on commit f291362

Please sign in to comment.