-
Notifications
You must be signed in to change notification settings - Fork 44
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
Abstract away Any
in the generated types
#118
Comments
For reference, here's how it looks when generated with ts-proto: /**
* MsgGrantAllowance adds permission for Grantee to spend up to Allowance
* of fees from the account of Granter.
*/
interface MsgGrantAllowance {
granter: string;
grantee: string;
- allowance: BasicAllowance | PeriodicAllowance | AllowedMsgAllowance;
+ allowance?: Any;
}
/**
* BasicAllowance implements Allowance with a one-time grant of tokens
* that optionally expires. The grantee can use up to SpendLimit to cover fees.
*/
interface BasicAllowance {
/**
* spend_limit specifies the maximum amount of tokens that can be spent
* by this allowance and will be updated as tokens are spent. If it is
* empty, there is no spend limit and any amount of coins can be spent.
*/
spendLimit: Coin[];
/** expiration specifies an optional time when this allowance expires */
expiration?: Timestamp;
}
/**
* PeriodicAllowance extends Allowance to allow for both a maximum cap,
* as well as a limit per time period.
*/
interface PeriodicAllowance {
/** basic specifies a struct of `BasicAllowance` */
basic?: BasicAllowance;
/**
* period specifies the time duration in which period_spend_limit coins can
* be spent before that allowance is reset
*/
period?: Duration;
/**
* period_spend_limit specifies the maximum number of coins that can be spent
* in the period
*/
periodSpendLimit: Coin[];
/** period_can_spend is the number of coins left to be spent before the period_reset time */
periodCanSpend: Coin[];
/**
* period_reset is the time at which this period resets and a new one begins,
* it is calculated from the start time of the first transaction after the
* last period ended
*/
periodReset?: Timestamp;
}
/** AllowedMsgAllowance creates allowance only for specified message types. */
export interface AllowedMsgAllowance {
/** allowance can be any of basic and filtered fee allowance. */
- allowance: BasicAllowance | PeriodicAllowance | AllowedMsgAllowance;
+ allowance?: Any;
/** allowed_messages are the messages for which the grantee has the access. */
allowedMessages: string[];
} |
|
So things just became more complicated. Reposting from Discord: Hi all, I have a question about the protobuf definitions of In In practice there are at least 7 proposal types that I manged to find by hand, so my question is how can client library effectively find them?
And two more in ibc-go: Seems to me that they're all manually implementing the Also seems like Would love to get some feedback and more info on this. 🙏 |
@ValarDragon another question I have — would it be a breaking change to add the It seems that there was a convention, but perhaps it didn't get followed. If this would be a non-breaking change, adding this option would allow us to automate all the proposal serialization logic. |
we also need to figure out where in exported
@faddat @nghuyenthevinh2000 do you know if the cosmos-sdk exports these two objects to From what I can tell, these objects aren't included in the export. |
This should be possible and not a breaking change to do, as far as I understand! I'd test it on a node before releasing, but that should be easy to do |
some examples I've found in the wild: export const createSubmitProposalMsg = (
typeUrl,
title,
description,
proposer,
deposit,
denom,
) => {
const msgSubmitProposal = {
content: {
typeUrl: typeUrl,
value: gov_1.TextProposal.encode(gov_1.TextProposal.fromPartial({
title: title,
description: description,
})).finish(),
},
initialDeposit: coins(deposit, denom),
proposer: proposer
}
const msg = {
typeUrl: "/cosmos.gov.v1beta1.MsgSubmitProposal",
value: msgSubmitProposal,
}
return msg
} |
Really glad to see this... this is the kind of annoying stuff we have to do to encode nested proto messages in JS right now: https://github.com/DA0-DA0/dao-dao-ui/blob/940462a5210c507a731289b3dc2cdcc36299c33d/packages/utils/messages.ts#L205 |
due to infinite recursion of the authz messages types — pretty certain we need to re-write how amino types are encoded: this will be more maintainable as well: #49 |
@assafmo @webmaster128 making some progress, these are auto-generated decoders: import { DepositDeploymentAuthorization as DepositDeploymentAuthorization1 } from "../../../akash/deployment/v1beta1/authz";
import { DepositDeploymentAuthorization as DepositDeploymentAuthorization2 } from "../../../akash/deployment/v1beta2/authz";
import { SendAuthorization } from "../../bank/v1beta1/authz";
import { StakeAuthorization } from "../../staking/v1beta1/authz";
...
export const Authorization_InterfaceDecoder = (input: _m0.Reader | Uint8Array): DepositDeploymentAuthorization1 | DepositDeploymentAuthorization2 | GenericAuthorization | SendAuthorization | StakeAuthorization | Any => {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
const data = Any.decode(reader, reader.uint32());
switch (data.typeUrl) {
case "/akash.deployment.v1beta1.DepositDeploymentAuthorization":
return DepositDeploymentAuthorization1.decode(data.value);
case "/akash.deployment.v1beta2.DepositDeploymentAuthorization":
return DepositDeploymentAuthorization2.decode(data.value);
case "/cosmos.authz.v1beta1.GenericAuthorization":
return GenericAuthorization.decode(data.value);
case "/cosmos.bank.v1beta1.SendAuthorization":
return SendAuthorization.decode(data.value);
case "/cosmos.staking.v1beta1.StakeAuthorization":
return StakeAuthorization.decode(data.value);
default:
return data;
}
}; the idea is to replace the type decoders anywhere they are found in decode function: decode(input: _m0.Reader | Uint8Array, length?: number): Grant {
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseGrant();
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
message.authorization = Authorization_InterfaceDecoder(reader);
break;
case 2:
message.expiration = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
break;
default:
reader.skipType(tag & 7);
break;
}
}
return message;
}, related osmosis-labs/osmojs#5 |
Complex Msgs in cosmos-sdk usually have an
Any
field in them. It might be a good Idea to abstract this away from the users by recursively followingimplements_interface
&accepts_interface
.For example:
allowance
isAny
InMsgGrantAllowance
: https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/proto/cosmos/feegrant/v1beta1/tx.proto#L33accepts_interface
and see that it'sFeeAllowanceI
implements_interface
forFeeAllowanceI
and find all of these:BasicAllowance
: https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L14-L27PeriodicAllowance
: https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L29-L54AllowedMsgAllowance
: https://github.com/cosmos/cosmos-sdk/blob/v0.45.4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L56-L66Then the Typescript output should probably look like this:
(BTW I'm still not sure how to handle optional fields, as some of them are definitely not optional)
The text was updated successfully, but these errors were encountered: