Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proto msg response types #9351

Merged
merged 2 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/cosmic-proto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
"@cosmology/telescope": "^1.5.3",
"ava": "^5.3.1",
"rimraf": "^5.0.0",
"tsd": "^0.30.7",
"tsimp": "^2.0.11",
"typescript": "^5.5.0-beta"
},
Expand Down
42 changes: 32 additions & 10 deletions packages/cosmic-proto/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import type { QueryAllBalancesRequest } from './codegen/cosmos/bank/v1beta1/query.js';
import type { MsgSend } from './codegen/cosmos/bank/v1beta1/tx.js';
import type { MsgDelegate } from './codegen/cosmos/staking/v1beta1/tx.js';
import type {
QueryAllBalancesRequest,
QueryAllBalancesResponse,
} from './codegen/cosmos/bank/v1beta1/query.js';
import type {
MsgSend,
MsgSendResponse,
} from './codegen/cosmos/bank/v1beta1/tx.js';
import type {
MsgDelegate,
MsgDelegateResponse,
} from './codegen/cosmos/staking/v1beta1/tx.js';
import { RequestQuery } from './codegen/tendermint/abci/types.js';
import type { Any } from './codegen/google/protobuf/any.js';

Expand All @@ -14,8 +23,18 @@ export type AnyJson = { typeUrl: string; value: string };
// TODO codegen this by modifying Telescope
export type Proto3Shape = {
'/cosmos.bank.v1beta1.MsgSend': MsgSend;
'/cosmos.bank.v1beta1.MsgSendResponse': MsgSendResponse;
'/cosmos.bank.v1beta1.QueryAllBalancesRequest': QueryAllBalancesRequest;
'/cosmos.bank.v1beta1.QueryAllBalancesResponse': QueryAllBalancesResponse;
'/cosmos.staking.v1beta1.MsgDelegate': MsgDelegate;
'/cosmos.staking.v1beta1.MsgDelegateResponse': MsgDelegateResponse;
};

// Often s/Request$/Response/ but not always
type ResponseMap = {
'/cosmos.bank.v1beta1.MsgSend': '/cosmos.bank.v1beta1.MsgSendResponse';
'/cosmos.bank.v1beta1.QueryAllBalancesRequest': '/cosmos.bank.v1beta1.QueryAllBalancesResponse';
'/cosmos.staking.v1beta1.MsgDelegate': '/cosmos.staking.v1beta1.MsgDelegateResponse';
};

/**
Expand All @@ -26,13 +45,16 @@ export type Proto3Shape = {
* type with a string.
*/
export type TypedJson<T extends unknown | keyof Proto3Shape = unknown> =
T extends unknown
? { '@type': string }
: T extends keyof Proto3Shape
? Proto3Shape[T] & {
'@type': T;
}
: never;
T extends keyof Proto3Shape
? Proto3Shape[T] & {
'@type': T;
}
: { '@type': string };

export type ResponseTo<T extends TypedJson> =
T['@type'] extends keyof ResponseMap
? TypedJson<ResponseMap[T['@type']]>
: TypedJson;

export const typedJson = <T extends keyof Proto3Shape>(
typeStr: T,
Expand Down
32 changes: 32 additions & 0 deletions packages/cosmic-proto/test/helpers.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expectType } from 'tsd';
import { typedJson } from '../src/helpers.js';
import type { ResponseTo } from '../src/helpers.ts';

// MsgSend
{
const request = typedJson('/cosmos.bank.v1beta1.MsgSend', {
fromAddress: 'agoric1from',
toAddress: 'agoric1to',
amount: [{ denom: 'ucosm', amount: '1' }],
});
const response: ResponseTo<typeof request> = null as any;
expectType<'/cosmos.bank.v1beta1.MsgSendResponse'>(response['@type']);
response['@type'] = '/cosmos.bank.v1beta1.MsgSendResponse';
// @ts-expect-error invalid value for response
response['@type'] = '/cosmos.bank.v1beta1.MsgSend';
}

// QueryAllBalances
{
const request = typedJson('/cosmos.bank.v1beta1.QueryAllBalancesRequest', {
address: 'agoric1from',
});
const response: ResponseTo<typeof request> = null as any;
expectType<'/cosmos.bank.v1beta1.QueryAllBalancesResponse'>(
response['@type'],
);
response['@type'] = '/cosmos.bank.v1beta1.QueryAllBalancesResponse';
// @ts-expect-error invalid value for response
response['@type'] = '/cosmos.bank.v1beta1.QueryAllBalancesRequest';
response.balances = [{ denom: 'ucosm', amount: '1' }];
}
24 changes: 24 additions & 0 deletions packages/orchestration/test/types.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
* @file pure types types, no runtime, ignored by Ava
*/
import { expectNotType, expectType } from 'tsd';
import { typedJson } from '@agoric/cosmic-proto';
import type { MsgDelegateResponse } from '@agoric/cosmic-proto/cosmos/staking/v1beta1/tx.js';
import type { QueryAllBalancesResponse } from '@agoric/cosmic-proto/cosmos/bank/v1beta1/query.js';
import type { ChainAddress, CosmosValidatorAddress } from '../src/types.js';
import type { LocalchainAccountKit } from '../src/exos/localchainAccountKit.js';

const validatorAddr = {
chainId: 'agoric3',
Expand All @@ -24,3 +28,23 @@ expectNotType<CosmosValidatorAddress>(chainAddr);
// @ts-expect-error
const notVa: CosmosValidatorAddress = chainAddr;
}

{
const lcak: LocalchainAccountKit = null as any;
const lca = lcak.helper.owned();
const results = await lca.executeTx([
typedJson('/cosmos.staking.v1beta1.MsgDelegate', {
amount: {
amount: '1',
denom: 'ubld',
},
validatorAddress: 'agoric1valoperhello',
delegatorAddress: 'agoric1pleab',
}),
typedJson('/cosmos.bank.v1beta1.QueryAllBalancesRequest', {
address: 'agoric1pleab',
}),
] as const);
expectType<MsgDelegateResponse>(results[0]);
expectType<QueryAllBalancesResponse>(results[1]);
}
11 changes: 9 additions & 2 deletions packages/vats/src/localchain.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { AmountShape } from '@agoric/ertp';

const { Fail, bare } = assert;

/** @import {TypedJson, ResponseTo} from '@agoric/cosmic-proto'; */

/**
* @typedef {{
* system: import('./types.js').ScopedBridgeManager;
Expand Down Expand Up @@ -68,8 +70,13 @@ const prepareLocalChainAccount = zone =>
return E(allegedPurse).deposit(payment);
},
/**
* @param {import('@agoric/cosmic-proto').TypedJson<unknown>[]} messages
* @returns {Promise<import('@agoric/cosmic-proto').TypedJson[]>}
* Execute a batch of transactions and return the responses. Use
* `typedJson()` on the arguments to get typed return values.
*
* @template {TypedJson[]} MT messages tuple (use const with multiple
* elements or it will be a mixed array)
* @param {MT} messages
* @returns {Promise<{ [K in keyof MT]: ResponseTo<MT[K]> }>}
*/
async executeTx(messages) {
const { address, powers } = this.state;
Expand Down
Loading