From 8aa0aa5383699a1101cd060d88ef50007dace598 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 15 Mar 2021 16:36:25 +0100 Subject: [PATCH] Add support for vesting accounts to accountFromAny --- CHANGELOG.md | 7 + packages/stargate/scripts/define-proto.sh | 1 + .../codec/cosmos/vesting/v1beta1/vesting.ts | 520 ++++++++++++++++++ packages/stargate/src/stargateclient.ts | 35 +- 4 files changed, 561 insertions(+), 2 deletions(-) create mode 100644 packages/stargate/src/codec/cosmos/vesting/v1beta1/vesting.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ca99ac2..f50dc156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to ## [Unreleased] +### Added + +- @cosmjs/stargate: Add support for different account types in `accountFromAny` + and `StargateClient`. Added vesting accounts `BaseVestingAccount`, + `ContinuousVestingAccount`, `DelayedVestingAccount` and + `PeriodicVestingAccount`. + ### Changed - @cosmjs/cosmwasm-stargate: Codec adapted to support wasmd 0.16. Older versions diff --git a/packages/stargate/scripts/define-proto.sh b/packages/stargate/scripts/define-proto.sh index 32bc6338..d5a88522 100755 --- a/packages/stargate/scripts/define-proto.sh +++ b/packages/stargate/scripts/define-proto.sh @@ -33,6 +33,7 @@ protoc \ "$COSMOS_PROTO_DIR/cosmos/staking/v1beta1/tx.proto" \ "$COSMOS_PROTO_DIR/cosmos/tx/signing/v1beta1/signing.proto" \ "$COSMOS_PROTO_DIR/cosmos/tx/v1beta1/tx.proto" \ + "$COSMOS_PROTO_DIR/cosmos/vesting/v1beta1/vesting.proto" \ "$COSMOS_PROTO_DIR/ibc/core/channel/v1/channel.proto" \ "$COSMOS_PROTO_DIR/ibc/core/channel/v1/query.proto" \ "$COSMOS_PROTO_DIR/ibc/core/client/v1/client.proto" \ diff --git a/packages/stargate/src/codec/cosmos/vesting/v1beta1/vesting.ts b/packages/stargate/src/codec/cosmos/vesting/v1beta1/vesting.ts new file mode 100644 index 00000000..f9f2d0ea --- /dev/null +++ b/packages/stargate/src/codec/cosmos/vesting/v1beta1/vesting.ts @@ -0,0 +1,520 @@ +/* eslint-disable */ +import { BaseAccount } from "../../../cosmos/auth/v1beta1/auth"; +import Long from "long"; +import { Coin } from "../../../cosmos/base/v1beta1/coin"; +import _m0 from "protobufjs/minimal"; + +export const protobufPackage = "cosmos.vesting.v1beta1"; + +/** + * BaseVestingAccount implements the VestingAccount interface. It contains all + * the necessary fields needed for any vesting account implementation. + */ +export interface BaseVestingAccount { + baseAccount?: BaseAccount; + originalVesting: Coin[]; + delegatedFree: Coin[]; + delegatedVesting: Coin[]; + endTime: Long; +} + +/** + * ContinuousVestingAccount implements the VestingAccount interface. It + * continuously vests by unlocking coins linearly with respect to time. + */ +export interface ContinuousVestingAccount { + baseVestingAccount?: BaseVestingAccount; + startTime: Long; +} + +/** + * DelayedVestingAccount implements the VestingAccount interface. It vests all + * coins after a specific time, but non prior. In other words, it keeps them + * locked until a specified time. + */ +export interface DelayedVestingAccount { + baseVestingAccount?: BaseVestingAccount; +} + +/** Period defines a length of time and amount of coins that will vest. */ +export interface Period { + length: Long; + amount: Coin[]; +} + +/** + * PeriodicVestingAccount implements the VestingAccount interface. It + * periodically vests by unlocking coins during each specified period. + */ +export interface PeriodicVestingAccount { + baseVestingAccount?: BaseVestingAccount; + startTime: Long; + vestingPeriods: Period[]; +} + +const baseBaseVestingAccount: object = { endTime: Long.ZERO }; + +export const BaseVestingAccount = { + encode(message: BaseVestingAccount, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.baseAccount !== undefined) { + BaseAccount.encode(message.baseAccount, writer.uint32(10).fork()).ldelim(); + } + for (const v of message.originalVesting) { + Coin.encode(v!, writer.uint32(18).fork()).ldelim(); + } + for (const v of message.delegatedFree) { + Coin.encode(v!, writer.uint32(26).fork()).ldelim(); + } + for (const v of message.delegatedVesting) { + Coin.encode(v!, writer.uint32(34).fork()).ldelim(); + } + if (!message.endTime.isZero()) { + writer.uint32(40).int64(message.endTime); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): BaseVestingAccount { + const reader = input instanceof Uint8Array ? new _m0.Reader(input) : input; + let end = length === undefined ? reader.len : reader.pos + length; + const message = { ...baseBaseVestingAccount } as BaseVestingAccount; + message.originalVesting = []; + message.delegatedFree = []; + message.delegatedVesting = []; + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.baseAccount = BaseAccount.decode(reader, reader.uint32()); + break; + case 2: + message.originalVesting.push(Coin.decode(reader, reader.uint32())); + break; + case 3: + message.delegatedFree.push(Coin.decode(reader, reader.uint32())); + break; + case 4: + message.delegatedVesting.push(Coin.decode(reader, reader.uint32())); + break; + case 5: + message.endTime = reader.int64() as Long; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): BaseVestingAccount { + const message = { ...baseBaseVestingAccount } as BaseVestingAccount; + message.originalVesting = []; + message.delegatedFree = []; + message.delegatedVesting = []; + if (object.baseAccount !== undefined && object.baseAccount !== null) { + message.baseAccount = BaseAccount.fromJSON(object.baseAccount); + } else { + message.baseAccount = undefined; + } + if (object.originalVesting !== undefined && object.originalVesting !== null) { + for (const e of object.originalVesting) { + message.originalVesting.push(Coin.fromJSON(e)); + } + } + if (object.delegatedFree !== undefined && object.delegatedFree !== null) { + for (const e of object.delegatedFree) { + message.delegatedFree.push(Coin.fromJSON(e)); + } + } + if (object.delegatedVesting !== undefined && object.delegatedVesting !== null) { + for (const e of object.delegatedVesting) { + message.delegatedVesting.push(Coin.fromJSON(e)); + } + } + if (object.endTime !== undefined && object.endTime !== null) { + message.endTime = Long.fromString(object.endTime); + } else { + message.endTime = Long.ZERO; + } + return message; + }, + + toJSON(message: BaseVestingAccount): unknown { + const obj: any = {}; + message.baseAccount !== undefined && + (obj.baseAccount = message.baseAccount ? BaseAccount.toJSON(message.baseAccount) : undefined); + if (message.originalVesting) { + obj.originalVesting = message.originalVesting.map((e) => (e ? Coin.toJSON(e) : undefined)); + } else { + obj.originalVesting = []; + } + if (message.delegatedFree) { + obj.delegatedFree = message.delegatedFree.map((e) => (e ? Coin.toJSON(e) : undefined)); + } else { + obj.delegatedFree = []; + } + if (message.delegatedVesting) { + obj.delegatedVesting = message.delegatedVesting.map((e) => (e ? Coin.toJSON(e) : undefined)); + } else { + obj.delegatedVesting = []; + } + message.endTime !== undefined && (obj.endTime = (message.endTime || Long.ZERO).toString()); + return obj; + }, + + fromPartial(object: DeepPartial): BaseVestingAccount { + const message = { ...baseBaseVestingAccount } as BaseVestingAccount; + message.originalVesting = []; + message.delegatedFree = []; + message.delegatedVesting = []; + if (object.baseAccount !== undefined && object.baseAccount !== null) { + message.baseAccount = BaseAccount.fromPartial(object.baseAccount); + } else { + message.baseAccount = undefined; + } + if (object.originalVesting !== undefined && object.originalVesting !== null) { + for (const e of object.originalVesting) { + message.originalVesting.push(Coin.fromPartial(e)); + } + } + if (object.delegatedFree !== undefined && object.delegatedFree !== null) { + for (const e of object.delegatedFree) { + message.delegatedFree.push(Coin.fromPartial(e)); + } + } + if (object.delegatedVesting !== undefined && object.delegatedVesting !== null) { + for (const e of object.delegatedVesting) { + message.delegatedVesting.push(Coin.fromPartial(e)); + } + } + if (object.endTime !== undefined && object.endTime !== null) { + message.endTime = object.endTime as Long; + } else { + message.endTime = Long.ZERO; + } + return message; + }, +}; + +const baseContinuousVestingAccount: object = { startTime: Long.ZERO }; + +export const ContinuousVestingAccount = { + encode(message: ContinuousVestingAccount, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.baseVestingAccount !== undefined) { + BaseVestingAccount.encode(message.baseVestingAccount, writer.uint32(10).fork()).ldelim(); + } + if (!message.startTime.isZero()) { + writer.uint32(16).int64(message.startTime); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ContinuousVestingAccount { + const reader = input instanceof Uint8Array ? new _m0.Reader(input) : input; + let end = length === undefined ? reader.len : reader.pos + length; + const message = { ...baseContinuousVestingAccount } as ContinuousVestingAccount; + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.baseVestingAccount = BaseVestingAccount.decode(reader, reader.uint32()); + break; + case 2: + message.startTime = reader.int64() as Long; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ContinuousVestingAccount { + const message = { ...baseContinuousVestingAccount } as ContinuousVestingAccount; + if (object.baseVestingAccount !== undefined && object.baseVestingAccount !== null) { + message.baseVestingAccount = BaseVestingAccount.fromJSON(object.baseVestingAccount); + } else { + message.baseVestingAccount = undefined; + } + if (object.startTime !== undefined && object.startTime !== null) { + message.startTime = Long.fromString(object.startTime); + } else { + message.startTime = Long.ZERO; + } + return message; + }, + + toJSON(message: ContinuousVestingAccount): unknown { + const obj: any = {}; + message.baseVestingAccount !== undefined && + (obj.baseVestingAccount = message.baseVestingAccount + ? BaseVestingAccount.toJSON(message.baseVestingAccount) + : undefined); + message.startTime !== undefined && (obj.startTime = (message.startTime || Long.ZERO).toString()); + return obj; + }, + + fromPartial(object: DeepPartial): ContinuousVestingAccount { + const message = { ...baseContinuousVestingAccount } as ContinuousVestingAccount; + if (object.baseVestingAccount !== undefined && object.baseVestingAccount !== null) { + message.baseVestingAccount = BaseVestingAccount.fromPartial(object.baseVestingAccount); + } else { + message.baseVestingAccount = undefined; + } + if (object.startTime !== undefined && object.startTime !== null) { + message.startTime = object.startTime as Long; + } else { + message.startTime = Long.ZERO; + } + return message; + }, +}; + +const baseDelayedVestingAccount: object = {}; + +export const DelayedVestingAccount = { + encode(message: DelayedVestingAccount, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.baseVestingAccount !== undefined) { + BaseVestingAccount.encode(message.baseVestingAccount, writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): DelayedVestingAccount { + const reader = input instanceof Uint8Array ? new _m0.Reader(input) : input; + let end = length === undefined ? reader.len : reader.pos + length; + const message = { ...baseDelayedVestingAccount } as DelayedVestingAccount; + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.baseVestingAccount = BaseVestingAccount.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): DelayedVestingAccount { + const message = { ...baseDelayedVestingAccount } as DelayedVestingAccount; + if (object.baseVestingAccount !== undefined && object.baseVestingAccount !== null) { + message.baseVestingAccount = BaseVestingAccount.fromJSON(object.baseVestingAccount); + } else { + message.baseVestingAccount = undefined; + } + return message; + }, + + toJSON(message: DelayedVestingAccount): unknown { + const obj: any = {}; + message.baseVestingAccount !== undefined && + (obj.baseVestingAccount = message.baseVestingAccount + ? BaseVestingAccount.toJSON(message.baseVestingAccount) + : undefined); + return obj; + }, + + fromPartial(object: DeepPartial): DelayedVestingAccount { + const message = { ...baseDelayedVestingAccount } as DelayedVestingAccount; + if (object.baseVestingAccount !== undefined && object.baseVestingAccount !== null) { + message.baseVestingAccount = BaseVestingAccount.fromPartial(object.baseVestingAccount); + } else { + message.baseVestingAccount = undefined; + } + return message; + }, +}; + +const basePeriod: object = { length: Long.ZERO }; + +export const Period = { + encode(message: Period, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (!message.length.isZero()) { + writer.uint32(8).int64(message.length); + } + for (const v of message.amount) { + Coin.encode(v!, writer.uint32(18).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Period { + const reader = input instanceof Uint8Array ? new _m0.Reader(input) : input; + let end = length === undefined ? reader.len : reader.pos + length; + const message = { ...basePeriod } as Period; + message.amount = []; + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.length = reader.int64() as Long; + break; + case 2: + message.amount.push(Coin.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): Period { + const message = { ...basePeriod } as Period; + message.amount = []; + if (object.length !== undefined && object.length !== null) { + message.length = Long.fromString(object.length); + } else { + message.length = Long.ZERO; + } + if (object.amount !== undefined && object.amount !== null) { + for (const e of object.amount) { + message.amount.push(Coin.fromJSON(e)); + } + } + return message; + }, + + toJSON(message: Period): unknown { + const obj: any = {}; + message.length !== undefined && (obj.length = (message.length || Long.ZERO).toString()); + if (message.amount) { + obj.amount = message.amount.map((e) => (e ? Coin.toJSON(e) : undefined)); + } else { + obj.amount = []; + } + return obj; + }, + + fromPartial(object: DeepPartial): Period { + const message = { ...basePeriod } as Period; + message.amount = []; + if (object.length !== undefined && object.length !== null) { + message.length = object.length as Long; + } else { + message.length = Long.ZERO; + } + if (object.amount !== undefined && object.amount !== null) { + for (const e of object.amount) { + message.amount.push(Coin.fromPartial(e)); + } + } + return message; + }, +}; + +const basePeriodicVestingAccount: object = { startTime: Long.ZERO }; + +export const PeriodicVestingAccount = { + encode(message: PeriodicVestingAccount, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.baseVestingAccount !== undefined) { + BaseVestingAccount.encode(message.baseVestingAccount, writer.uint32(10).fork()).ldelim(); + } + if (!message.startTime.isZero()) { + writer.uint32(16).int64(message.startTime); + } + for (const v of message.vestingPeriods) { + Period.encode(v!, writer.uint32(26).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PeriodicVestingAccount { + const reader = input instanceof Uint8Array ? new _m0.Reader(input) : input; + let end = length === undefined ? reader.len : reader.pos + length; + const message = { ...basePeriodicVestingAccount } as PeriodicVestingAccount; + message.vestingPeriods = []; + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.baseVestingAccount = BaseVestingAccount.decode(reader, reader.uint32()); + break; + case 2: + message.startTime = reader.int64() as Long; + break; + case 3: + message.vestingPeriods.push(Period.decode(reader, reader.uint32())); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): PeriodicVestingAccount { + const message = { ...basePeriodicVestingAccount } as PeriodicVestingAccount; + message.vestingPeriods = []; + if (object.baseVestingAccount !== undefined && object.baseVestingAccount !== null) { + message.baseVestingAccount = BaseVestingAccount.fromJSON(object.baseVestingAccount); + } else { + message.baseVestingAccount = undefined; + } + if (object.startTime !== undefined && object.startTime !== null) { + message.startTime = Long.fromString(object.startTime); + } else { + message.startTime = Long.ZERO; + } + if (object.vestingPeriods !== undefined && object.vestingPeriods !== null) { + for (const e of object.vestingPeriods) { + message.vestingPeriods.push(Period.fromJSON(e)); + } + } + return message; + }, + + toJSON(message: PeriodicVestingAccount): unknown { + const obj: any = {}; + message.baseVestingAccount !== undefined && + (obj.baseVestingAccount = message.baseVestingAccount + ? BaseVestingAccount.toJSON(message.baseVestingAccount) + : undefined); + message.startTime !== undefined && (obj.startTime = (message.startTime || Long.ZERO).toString()); + if (message.vestingPeriods) { + obj.vestingPeriods = message.vestingPeriods.map((e) => (e ? Period.toJSON(e) : undefined)); + } else { + obj.vestingPeriods = []; + } + return obj; + }, + + fromPartial(object: DeepPartial): PeriodicVestingAccount { + const message = { ...basePeriodicVestingAccount } as PeriodicVestingAccount; + message.vestingPeriods = []; + if (object.baseVestingAccount !== undefined && object.baseVestingAccount !== null) { + message.baseVestingAccount = BaseVestingAccount.fromPartial(object.baseVestingAccount); + } else { + message.baseVestingAccount = undefined; + } + if (object.startTime !== undefined && object.startTime !== null) { + message.startTime = object.startTime as Long; + } else { + message.startTime = Long.ZERO; + } + if (object.vestingPeriods !== undefined && object.vestingPeriods !== null) { + for (const e of object.vestingPeriods) { + message.vestingPeriods.push(Period.fromPartial(e)); + } + } + return message; + }, +}; + +type Builtin = Date | Function | Uint8Array | string | number | undefined | Long; +export type DeepPartial = T extends Builtin + ? T + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 12df5479..f4a1aef1 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -16,12 +16,18 @@ import { Tendermint34Client, toRfc3339WithNanoseconds, } from "@cosmjs/tendermint-rpc"; -import { assertDefinedAndNotNull } from "@cosmjs/utils"; +import { assert, assertDefinedAndNotNull } from "@cosmjs/utils"; import Long from "long"; import { BaseAccount } from "./codec/cosmos/auth/v1beta1/auth"; import { MsgData, TxMsgData } from "./codec/cosmos/base/abci/v1beta1/abci"; import { Coin } from "./codec/cosmos/base/v1beta1/coin"; +import { + BaseVestingAccount, + ContinuousVestingAccount, + DelayedVestingAccount, + PeriodicVestingAccount, +} from "./codec/cosmos/vesting/v1beta1/vesting"; import { Any } from "./codec/google/protobuf/any"; import { AuthExtension, BankExtension, QueryClient, setupAuthExtension, setupBankExtension } from "./queries"; @@ -113,9 +119,34 @@ export function accountFromAny(input: Any): Account { const { typeUrl, value } = input; switch (typeUrl) { - case "/cosmos.auth.v1beta1.BaseAccount": { + // auth + + case "/cosmos.auth.v1beta1.BaseAccount": return accountFromBaseAccount(BaseAccount.decode(value)); + + // vesting + + case "/cosmos.vesting.v1beta1.BaseVestingAccount": { + const baseAccount = BaseVestingAccount.decode(value)?.baseAccount; + assert(baseAccount); + return accountFromBaseAccount(baseAccount); } + case "/cosmos.vesting.v1beta1.ContinuousVestingAccount": { + const baseAccount = ContinuousVestingAccount.decode(value)?.baseVestingAccount?.baseAccount; + assert(baseAccount); + return accountFromBaseAccount(baseAccount); + } + case "/cosmos.vesting.v1beta1.DelayedVestingAccount": { + const baseAccount = DelayedVestingAccount.decode(value)?.baseVestingAccount?.baseAccount; + assert(baseAccount); + return accountFromBaseAccount(baseAccount); + } + case "/cosmos.vesting.v1beta1.PeriodicVestingAccount": { + const baseAccount = PeriodicVestingAccount.decode(value)?.baseVestingAccount?.baseAccount; + assert(baseAccount); + return accountFromBaseAccount(baseAccount); + } + default: throw new Error(`Unsupported type: '${typeUrl}'`); }