diff --git a/.gitbook/SUMMARY.md b/.gitbook/SUMMARY.md index 6ff3b1c85..f9bf95bdc 100644 --- a/.gitbook/SUMMARY.md +++ b/.gitbook/SUMMARY.md @@ -61,6 +61,7 @@ * [Core Modules](core-modules/README.md) * [Auction](core-modules/auction.md) * [AuthZ](core-modules/authz.md) + - [Feegrant](core-modules/feegrant.md) * [Bank](core-modules/bank.md) * [Distribution](core-modules/distribution.md) * [Exchange](core-modules/exchange.md) diff --git a/.gitbook/core-modules/README.md b/.gitbook/core-modules/README.md index 65f95d10a..f7968321b 100644 --- a/.gitbook/core-modules/README.md +++ b/.gitbook/core-modules/README.md @@ -10,6 +10,7 @@ Within this section, we are going to explore the core modules of the Injective c | ------------------------------- | ------------------------------------------------ | | [Auction](auction.md) | Use for the buy-back-and-burn on chain mechanism | | [AuthZ](authz.md) | Used for granting account priveledges | +| [Feegrant](feegrant.md) | Used for granting fee allowance priveledges | | [Bank](bank.md) | Used for managing users assets (funds) | | [Exchange](exchange.md) | Used for the exchange primitives | | [Distribution](distribution.md) | Used for on-chain distribution/minting | diff --git a/.gitbook/core-modules/feegrant.md b/.gitbook/core-modules/feegrant.md new file mode 100644 index 000000000..c052621d6 --- /dev/null +++ b/.gitbook/core-modules/feegrant.md @@ -0,0 +1,75 @@ +# Fee Grant + +The `feegrant` module allows accounts (granters) to grant fee allowances to other accounts (grantees). This allows the grantee to use the granter's funds to pay for transaction fees. + +## Messages + +### MsgGrantAllowance + +A fee allowance grant is created using the `MsgGrantAllowance` message. If there is already a grant for the (granter, grantee) pair, then the new grant will overwrite the previous one. + +```ts +import { MsgGrantAllowance, MsgBroadcasterWithPk } from '@injectivelabs/sdk-ts' +import { Network } from '@injectivelabs/networks' + + +const privateKeyOfGranter = '0x...' + +const date = new Date('2023-10-02T00:00:00Z') +const expiration = date.getTime() / 1000 +const granter = 'inj...' +const grantee = 'inj...' +const allowance = { + spendLimit: [ + { + denom: 'inj', + amount: '10000', + }, + ], + expiration +} + +const msg = MsgGrantAllowance.fromJSON({ + granter, + grantee, + allowance, +}) + +const txHash = await new MsgBroadcasterWithPk({ +privateKey: privateKeyOfGranter, +network: Network.Testnet, +}).broadcast({ +msgs: msg, +}) + +console.log(txHash) + +``` + +### MsgRevokeAllowance +A grant can be removed using the MsgRevokeAllowance message. The grantee will no longer be able to use the granter's funds to pay for transaction fees. + +```ts +import { MsgRevokeAllowance, MsgBroadcasterWithPk } from '@injectivelabs/sdk-ts' +import { Network } from '@injectivelabs/networks' + +const privateKey= "0x..." +const granteeAddress = 'inj...' +const granterAddress = 'inj...' + +const params = { +grantee: granteeAddress, +granter: granterAddress, +} + +const msg = MsgRevokeAllowance.fromJSON(params); + +const txHash = await new MsgBroadcasterWithPk({ +privateKey, +network: Network.Testnet, +}).broadcast({ +msgs: msg, +}) + +console.log(txHash) +``` diff --git a/packages/sdk-ts/src/core/modules/feegrant/index.ts b/packages/sdk-ts/src/core/modules/feegrant/index.ts new file mode 100644 index 000000000..be0443536 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/index.ts @@ -0,0 +1,4 @@ +import MsgGrantAllowance from './msgs/MsgGrantAllowance' +import MsgRevokeAllowance from './msgs/MsgRevokeAllowance' + +export { MsgGrantAllowance, MsgRevokeAllowance } diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts new file mode 100644 index 000000000..15b6808eb --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.spec.ts @@ -0,0 +1,151 @@ +import MsgGrantAllowance from './MsgGrantAllowance' +import { mockFactory } from '@injectivelabs/test-utils' +import { CosmosFeegrantV1Beta1Feegrant } from '@injectivelabs/core-proto-ts' +import snakecaseKeys from 'snakecase-keys' + +const { injectiveAddress, injectiveAddress2 } = mockFactory + +const params: MsgGrantAllowance['params'] = { + grantee: injectiveAddress, + granter: injectiveAddress2, + allowance: { + spendLimit: [ + { + denom: 'inj', + amount: '1000', + }, + ], + expiration: 1679416772, + }, +} + +const protoType = '/cosmos.feegrant.v1beta1.MsgGrantAllowance' +const protoTypeShort = 'cosmos-sdk/MsgGrantAllowance' +const protoParams = { + grantee: params.grantee, + granter: params.granter, + allowance: { + typeUrl: '/cosmos.feegrant.v1beta1.BasicAllowance', + value: Uint8Array.from( + CosmosFeegrantV1Beta1Feegrant.BasicAllowance.encode({ + spendLimit: params.allowance.spendLimit, + expiration: new Date(params.allowance.expiration! * 1000), + }).finish(), + ), + }, +} + +const protoParamsAmino = snakecaseKeys({ + grantee: params.grantee, + granter: params.granter, + allowance: { + type: 'cosmos-sdk/BasicAllowance', + value: { + spendLimit: params.allowance.spendLimit, + expiration: new Date(params.allowance.expiration! * 1000), + }, + }, +}) + +const protoParamsWeb3 = { + grantee: params.grantee, + granter: params.granter, + allowance: { + '@type': '/cosmos.feegrant.v1beta1.BasicAllowance', + spendLimit: params.allowance.spendLimit, + expiration: new Date(params.allowance.expiration! * 1000), + }, +} +const message = MsgGrantAllowance.fromJSON(params) + +describe('MsgGrantAllowance', () => { + it('generates proper proto', () => { + const message = MsgGrantAllowance.fromJSON(params) + const proto = message.toProto() + + expect(proto).toStrictEqual({ + ...protoParams, + }) + }) + + it('generates proper data', () => { + const data = message.toData() + + expect(data).toStrictEqual({ + '@type': protoType, + ...protoParams, + }) + }) + + it('generates proper amino', () => { + const amino = message.toAmino() + + expect(amino).toStrictEqual({ + type: protoTypeShort, + value: protoParamsAmino, + }) + }) + + it('generates proper Eip712 types', () => { + const eip712Types = message.toEip712Types() + + expect(Object.fromEntries(eip712Types)).toStrictEqual({ + TypeAllowance: [ + { name: 'type', type: 'string' }, + { name: 'value', type: 'TypeAllowanceValue' }, + ], + TypeAllowanceValue: [ + { name: 'spend_limit', type: 'TypeAllowanceValueSpendLimit[]' }, + { name: 'expiration', type: 'string' }, + ], + TypeAllowanceValueSpendLimit: [ + { name: 'denom', type: 'string' }, + { name: 'amount', type: 'string' }, + ], + MsgValue: [ + { name: 'granter', type: 'string' }, + { name: 'grantee', type: 'string' }, + { name: 'allowance', type: 'TypeAllowance' }, + ], + }) + }) + + it('generates proper Eip712 values', () => { + const eip712 = message.toEip712() + + expect(eip712).toStrictEqual({ + type: protoTypeShort, + value: snakecaseKeys({ + ...protoParamsAmino, + allowance: { + ...protoParamsAmino.allowance, + value: { + ...protoParamsAmino.allowance.value, + expiration: + protoParamsAmino.allowance.value.expiration + .toJSON() + .split('.')[0] + 'Z', + }, + }, + }), + }) + }) + + it('generates proper direct sign', () => { + const directSign = message.toDirectSign() + + expect(directSign).toStrictEqual({ + type: protoType, + message: protoParams, + }) + }) + + it('generates proper web3', () => { + const web3 = message.toWeb3() + + expect(web3).toStrictEqual({ + '@type': protoType, + ...protoParamsWeb3, + }) + }) +}) diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts new file mode 100644 index 000000000..8c325b448 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgGrantAllowance.ts @@ -0,0 +1,166 @@ +import snakecaseKeys from 'snakecase-keys' +import { MsgBase } from '../../MsgBase' +import { + CosmosFeegrantV1Beta1Tx, + CosmosFeegrantV1Beta1Feegrant, + GoogleProtobufTimestamp, + GoogleProtobufAny, +} from '@injectivelabs/core-proto-ts' +import { Coin } from '@injectivelabs/ts-types' + +const basicAllowanceType = '/cosmos.feegrant.v1beta1.BasicAllowance' +export declare namespace MsgGrantAllowance { + export interface Params { + granter: string + grantee: string + allowance: { + spendLimit: Coin[] + expiration: number | undefined + } + } + + export type Proto = CosmosFeegrantV1Beta1Tx.MsgGrantAllowance + + export type Object = Omit< + CosmosFeegrantV1Beta1Tx.MsgGrantAllowance, + 'allowance' + > & { + allowance: any + } +} + +/** + * @category Messages + */ +export default class MsgGrantAllowance extends MsgBase< + MsgGrantAllowance.Params, + MsgGrantAllowance.Proto +> { + static fromJSON(params: MsgGrantAllowance.Params): MsgGrantAllowance { + return new MsgGrantAllowance(params) + } + + public toProto() { + const { params } = this + + const timestamp = this.getTimestamp() + const basicAllowance = CosmosFeegrantV1Beta1Feegrant.BasicAllowance.create() + basicAllowance.spendLimit = params.allowance.spendLimit + basicAllowance.expiration = new Date(Number(timestamp.seconds) * 1000) + + const allowance = GoogleProtobufAny.Any.create() + allowance.typeUrl = basicAllowanceType + allowance.value = Buffer.from( + CosmosFeegrantV1Beta1Feegrant.BasicAllowance.encode( + basicAllowance, + ).finish(), + ) + + const message = CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.create() + message.grantee = params.grantee + message.granter = params.granter + message.allowance = allowance + console.log({ + message, + fromJSON: CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.fromJSON(message), + }) + + return CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.fromJSON(message) + } + + public toData() { + const proto = this.toProto() + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgGrantAllowance', + ...proto, + } + } + + public toAmino() { + const { params } = this + + const proto = this.toProto() + const timestamp = this.getTimestamp() + const message = proto + + const messageWithAllowance = snakecaseKeys({ + ...message, + allowance: { + type: 'cosmos-sdk/BasicAllowance', + value: { + spendLimit: params.allowance.spendLimit, + expiration: new Date(Number(timestamp.seconds) * 1000), + }, + }, + }) + + return { + type: 'cosmos-sdk/MsgGrantAllowance', + value: messageWithAllowance as unknown as MsgGrantAllowance.Object, + } + } + + public toDirectSign() { + const proto = this.toProto() + + return { + type: '/cosmos.feegrant.v1beta1.MsgGrantAllowance', + message: proto, + } + } + + public toWeb3() { + const { params } = this + const amino = this.toAmino() + const timestamp = this.getTimestamp() + + const messageWithAllowance = { + granter: amino.value.granter, + grantee: amino.value.grantee, + allowance: { + '@type': basicAllowanceType, + spendLimit: params.allowance.spendLimit, + expiration: new Date(Number(timestamp.seconds) * 1000), + }, + } + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgGrantAllowance', + ...messageWithAllowance, + } + } + + private getTimestamp() { + const { params } = this + + if (params.allowance.expiration) { + const timestamp = GoogleProtobufTimestamp.Timestamp.create() + + timestamp.seconds = params.allowance.expiration.toString() + + return timestamp + } + + const defaultExpiryYears = 5 + const dateNow = new Date() + const expiration = new Date( + dateNow.getFullYear() + defaultExpiryYears, + dateNow.getMonth(), + dateNow.getDate(), + ) + + const timestamp = GoogleProtobufTimestamp.Timestamp.create() + const timestampInSeconds = (expiration.getTime() / 1000).toString() + + timestamp.seconds = timestampInSeconds + + return timestamp + } + + public toBinary(): Uint8Array { + return CosmosFeegrantV1Beta1Tx.MsgGrantAllowance.encode( + this.toProto(), + ).finish() + } +} diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts new file mode 100644 index 000000000..89ee5a3bc --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.spec.ts @@ -0,0 +1,79 @@ +import MsgRevokeAllowance from './MsgRevokeAllowance' +import { mockFactory } from '@injectivelabs/test-utils' +import snakecaseKeys from 'snakecase-keys' + +const { injectiveAddress, injectiveAddress2 } = mockFactory + +const params: MsgRevokeAllowance['params'] = { + grantee: injectiveAddress, + granter: injectiveAddress2, +} + +const protoType = '/cosmos.feegrant.v1beta1.MsgRevokeAllowance' +const protoTypeShort = 'cosmos-sdk/MsgRevokeAllowance' +const protoParams = { + grantee: params.grantee, + granter: params.granter, +} + +const protoParamsAmino = snakecaseKeys(protoParams) +const message = MsgRevokeAllowance.fromJSON(params) + +describe('MsgRevokeAllowance', () => { + it('generates proper proto', () => { + const proto = message.toProto() + + expect(proto).toStrictEqual({ + ...protoParams, + }) + }) + + it('generates proper data', () => { + const data = message.toData() + + expect(data).toStrictEqual({ + '@type': protoType, + ...protoParams, + }) + }) + + it('generates proper amino', () => { + const amino = message.toAmino() + + expect(amino).toStrictEqual({ + type: protoTypeShort, + value: protoParamsAmino, + }) + }) + + it('generates proper Eip712 types', () => { + const eip712Types = message.toEip712Types() + + expect(Object.fromEntries(eip712Types)).toStrictEqual({ + MsgValue: [ + { name: 'granter', type: 'string' }, + { name: 'grantee', type: 'string' }, + ], + }) + }) + + it('generates proper Eip712 values', () => { + const eip712 = message.toEip712() + + expect(eip712).toStrictEqual({ + type: protoTypeShort, + value: snakecaseKeys({ + ...protoParamsAmino, + }), + }) + }) + + it('generates proper web3', () => { + const web3 = message.toWeb3() + + expect(web3).toStrictEqual({ + '@type': protoType, + ...protoParamsAmino, + }) + }) +}) diff --git a/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts new file mode 100644 index 000000000..1dd2599dd --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/msgs/MsgRevokeAllowance.ts @@ -0,0 +1,80 @@ +import { MsgBase } from '../../MsgBase' +import snakecaseKeys, { SnakeCaseKeys } from 'snakecase-keys' +import { CosmosFeegrantV1Beta1Tx } from '@injectivelabs/core-proto-ts' + +export declare namespace MsgRevokeAllowance { + export interface Params { + granter: string + grantee: string + } + + export type Proto = CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance +} + +/** + * @category Messages + */ +export default class MsgRevokeAllowance extends MsgBase< + MsgRevokeAllowance.Params, + MsgRevokeAllowance.Proto +> { + static fromJSON(params: MsgRevokeAllowance.Params): MsgRevokeAllowance { + return new MsgRevokeAllowance(params) + } + + public toProto() { + const { params } = this + + const message = CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance.create() + message.grantee = params.grantee + message.granter = params.granter + + return CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance.fromPartial(message) + } + + public toData() { + const proto = this.toProto() + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgRevokeAllowance', + ...proto, + } + } + + public toAmino() { + const proto = this.toProto() + const message = { + ...snakecaseKeys(proto), + } + + return { + type: 'cosmos-sdk/MsgRevokeAllowance', + value: message as unknown as SnakeCaseKeys, + } + } + + public toWeb3() { + const amino = this.toAmino() + const { value } = amino + + return { + '@type': '/cosmos.feegrant.v1beta1.MsgRevokeAllowance', + ...value, + } + } + + public toDirectSign() { + const proto = this.toProto() + + return { + type: '/cosmos.feegrant.v1beta1.MsgRevokeAllowance', + message: proto, + } + } + + public toBinary(): Uint8Array { + return CosmosFeegrantV1Beta1Tx.MsgRevokeAllowance.encode( + this.toProto(), + ).finish() + } +} diff --git a/packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts b/packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts new file mode 100644 index 000000000..7e50a0e83 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/utils/allowance.ts @@ -0,0 +1,140 @@ +import { + GoogleProtobufAny, + CosmosFeegrantV1Beta1Feegrant, +} from '@injectivelabs/core-proto-ts' +import { GeneralException } from '@injectivelabs/exceptions' + +export type AllowedMsgAllowance = Omit< + CosmosFeegrantV1Beta1Feegrant.AllowedMsgAllowance, + 'allowance' +> & { + allowance: + | CosmosFeegrantV1Beta1Feegrant.BasicAllowance + | CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance +} + +export type Allowance = + | CosmosFeegrantV1Beta1Feegrant.BasicAllowance + | CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance + | AllowedMsgAllowance + | undefined + +export enum AllowanceTypes { + BasicAllowance = 'spendLimit', + PeriodicAllowance = 'periodSpendLimit', + AllowedMsgAllowance = 'allowedMessages', +} + +function isBasicAllowance( + allowance: Allowance, +): allowance is CosmosFeegrantV1Beta1Feegrant.BasicAllowance { + if (!allowance) { + return false + } + + return AllowanceTypes.BasicAllowance in allowance +} + +function isPeriodicAllowance( + allowance: Allowance, +): allowance is CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance { + if (!allowance) { + return false + } + + return AllowanceTypes.PeriodicAllowance in allowance +} + +function isAllowedMsgAllowance( + allowance: Allowance, +): allowance is AllowedMsgAllowance { + if (!allowance) { + return false + } + + return AllowanceTypes.AllowedMsgAllowance in allowance +} + +function encodeBasicAllowance( + allowance: CosmosFeegrantV1Beta1Feegrant.BasicAllowance, +): GoogleProtobufAny.Any { + return { + typeUrl: '/cosmos.feegrant.v1beta1.BasicAllowance', + value: Buffer.from( + CosmosFeegrantV1Beta1Feegrant.BasicAllowance.encode(allowance).finish(), + ), + } +} + +function encodePeriodicAllowance( + allowance: CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance, +): GoogleProtobufAny.Any { + return { + typeUrl: '/cosmos.feegrant.v1beta1.PeriodicAllowance', + value: Buffer.from( + CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance.encode( + allowance, + ).finish(), + ), + } +} + +function encodeAllowedMsgAllowance( + allowance: AllowedMsgAllowance, +): GoogleProtobufAny.Any | undefined { + let internalAllowance: GoogleProtobufAny.Any + + if (isBasicAllowance(allowance.allowance as Allowance)) { + internalAllowance = encodeBasicAllowance( + allowance.allowance as unknown as CosmosFeegrantV1Beta1Feegrant.BasicAllowance, + ) + } else if (isPeriodicAllowance(allowance.allowance as Allowance)) { + internalAllowance = encodePeriodicAllowance( + allowance.allowance as unknown as CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance, + ) + } else { + throw new Error( + `AllowedMsgAllowance: Cannot cast allowance into 'BasicAllowance' or 'PeriodicAllowance': ${JSON.stringify( + allowance.allowance, + )}`, + ) + } + + return { + typeUrl: '/cosmos.feegrant.v1beta1.AllowedMsgAllowance', + value: Buffer.from( + CosmosFeegrantV1Beta1Feegrant.AllowedMsgAllowance.encode({ + allowedMessages: allowance.allowedMessages, + allowance: internalAllowance, + }).finish(), + ), + } +} + +export function encodeAllowance( + allowance: Allowance, +): GoogleProtobufAny.Any | undefined { + if (isBasicAllowance(allowance)) { + return encodeBasicAllowance( + allowance as CosmosFeegrantV1Beta1Feegrant.BasicAllowance, + ) + } + + if (isPeriodicAllowance(allowance)) { + return encodePeriodicAllowance( + allowance as CosmosFeegrantV1Beta1Feegrant.PeriodicAllowance, + ) + } + + if (isAllowedMsgAllowance(allowance)) { + return encodeAllowedMsgAllowance(allowance as AllowedMsgAllowance) + } + + throw new GeneralException( + new Error( + `Cannot cast allowance into 'BasicAllowance', 'PeriodicAllowance' or 'AllowedMsgAllowance': ${JSON.stringify( + allowance, + )}`, + ), + ) +} diff --git a/packages/sdk-ts/src/core/modules/feegrant/utils/index.ts b/packages/sdk-ts/src/core/modules/feegrant/utils/index.ts new file mode 100644 index 000000000..48a402756 --- /dev/null +++ b/packages/sdk-ts/src/core/modules/feegrant/utils/index.ts @@ -0,0 +1 @@ +export * from './allowance' diff --git a/packages/sdk-ts/src/core/modules/index.ts b/packages/sdk-ts/src/core/modules/index.ts index b88650c8e..e108a6fb6 100644 --- a/packages/sdk-ts/src/core/modules/index.ts +++ b/packages/sdk-ts/src/core/modules/index.ts @@ -12,3 +12,4 @@ export * from './tokenfactory' export * from './wasm' export * from './tx' export * from './msgs' +export * from './feegrant' diff --git a/packages/sdk-ts/src/core/modules/msgs.ts b/packages/sdk-ts/src/core/modules/msgs.ts index f61caccde..6928dc4cd 100644 --- a/packages/sdk-ts/src/core/modules/msgs.ts +++ b/packages/sdk-ts/src/core/modules/msgs.ts @@ -4,6 +4,8 @@ import MsgRevoke from './authz/msgs/MsgRevoke' import MsgAuthzExec from './authz/msgs/MsgExec' import MsgSend from './bank/msgs/MsgSend' import MsgMultiSend from './bank/msgs/MsgMultiSend' +import MsgGrantAllowance from './feegrant/msgs/MsgGrantAllowance' +import MsgRevokeAllowance from './feegrant/msgs/MsgRevokeAllowance' import MsgWithdrawDelegatorReward from './distribution/msgs/MsgWithdrawDelegatorReward' import MsgWithdrawValidatorCommission from './distribution/msgs/MsgWithdrawValidatorCommission' import MsgBatchCancelDerivativeOrders from './exchange/msgs/MsgBatchCancelDerivativeOrders' @@ -109,6 +111,8 @@ export type Msgs = | MsgChangeAdmin | MsgCreateDenom | MsgSetDenomMetadata + | MsgGrantAllowance + | MsgRevokeAllowance /** * @category Messages diff --git a/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts b/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts index 65a86b0d7..330f69325 100644 --- a/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts +++ b/packages/sdk-ts/src/core/modules/tx/eip712/maps.ts @@ -629,6 +629,12 @@ export const protoTypeToAminoType = (type: string): string => { case 'ibc.applications.transfer.v1.MsgTransfer': return 'cosmos-sdk/MsgTransfer' + // feegrant + case 'cosmos.feegrant.v1beta1.MsgGrantAllowance': + return 'cosmos-sdk/MsgGrantAllowance' + case 'cosmos.feegrant.v1beta1.MsgRevokeAllowance': + return 'cosmos-sdk/MsgRevokeAllowance' + default: throw new GeneralException(new Error('Unknown message type: ' + type)) } diff --git a/packages/ts-types/src/enums.ts b/packages/ts-types/src/enums.ts index 2e01dac6d..e7a4bc341 100644 --- a/packages/ts-types/src/enums.ts +++ b/packages/ts-types/src/enums.ts @@ -18,9 +18,11 @@ export enum ChainId { export enum MsgType { MsgExec = 'cosmos.authz.v1beta1.MsgExec', MsgGrant = 'cosmos.authz.v1beta1.MsgGrant', + MsgRevoke = 'cosmos.authz.v1beta1.MsgRevoke', MsgSend = 'cosmos.bank.v1beta1.MsgSend', MsgWithdrawDelegatorReward = 'cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward', MsgGrantAllowance = 'cosmos.feegrant.v1beta1.MsgGrantAllowance', + MsgRevokeAllowance = 'cosmos.feegrant.v1beta1.MsgRevokeAllowance', MsgDepositCosmos = 'cosmos.gov.v1beta1.MsgDeposit', MsgSubmitProposal = 'cosmos.gov.v1beta1.MsgSubmitProposal', MsgVote = 'cosmos.gov.v1beta1.MsgVote',