diff --git a/package-lock.json b/package-lock.json index b9e598831..b56a7331d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@terra-money/legacy.proto": "npm:@terra-money/terra.proto@^0.1.7", - "@terra-money/terra.proto": "~2.0.0", + "@terra-money/terra.proto": "^2.1.0", "axios": "^0.26.1", "bech32": "^2.0.0", "bip32": "^2.0.6", @@ -1188,9 +1188,9 @@ } }, "node_modules/@terra-money/terra.proto": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.0.0.tgz", - "integrity": "sha512-ZjyFOFUzrGn8IwzGIgr1OJFcPSsQoz/XAfoSKThJx+OjJA7CLhdcz51+5h7ehNfb+qB9wr7aNME0h24wu9D4SQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.1.0.tgz", + "integrity": "sha512-rhaMslv3Rkr+QsTQEZs64FKA4QlfO0DfQHaR6yct/EovenMkibDEQ63dEL6yJA6LCaEQGYhyVB9JO9pTUA8ybw==", "dependencies": { "@improbable-eng/grpc-web": "^0.14.1", "google-protobuf": "^3.17.3", @@ -8418,9 +8418,9 @@ } }, "@terra-money/terra.proto": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.0.0.tgz", - "integrity": "sha512-ZjyFOFUzrGn8IwzGIgr1OJFcPSsQoz/XAfoSKThJx+OjJA7CLhdcz51+5h7ehNfb+qB9wr7aNME0h24wu9D4SQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.1.0.tgz", + "integrity": "sha512-rhaMslv3Rkr+QsTQEZs64FKA4QlfO0DfQHaR6yct/EovenMkibDEQ63dEL6yJA6LCaEQGYhyVB9JO9pTUA8ybw==", "requires": { "@improbable-eng/grpc-web": "^0.14.1", "google-protobuf": "^3.17.3", diff --git a/package.json b/package.json index 7798ca20e..9f0012366 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ }, "dependencies": { "@terra-money/legacy.proto": "npm:@terra-money/terra.proto@^0.1.7", - "@terra-money/terra.proto": "~2.0.0", + "@terra-money/terra.proto": "^2.1.0", "axios": "^0.26.1", "bech32": "^2.0.0", "bip32": "^2.0.6", diff --git a/src/client/lcd/api/FeeGrantAPI.spec.ts b/src/client/lcd/api/FeeGrantAPI.spec.ts index 163f1b79e..a793a34c6 100644 --- a/src/client/lcd/api/FeeGrantAPI.spec.ts +++ b/src/client/lcd/api/FeeGrantAPI.spec.ts @@ -44,4 +44,17 @@ describe('FeeGrantAPI', () => { ).rejects.toThrow(); }); }); + + it('allowancesByGranter', async () => { + const res = await feeGrant.allowancesByGranter( + 'terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v' + ); + expect(res.allowances[0]).toMatchObject({ + granter: expect.any(String), + grantee: expect.any(String), + }); + const allowanceData = res.allowances[0].allowance.toData(); + expect(allowanceData['@type']).toMatch(/cosmos.feegrant.v1beta1/g); + expect(res.pagination).not.toBeUndefined(); + }); }); diff --git a/src/client/lcd/api/FeeGrantAPI.ts b/src/client/lcd/api/FeeGrantAPI.ts index 62a2c5289..a4d8a6947 100644 --- a/src/client/lcd/api/FeeGrantAPI.ts +++ b/src/client/lcd/api/FeeGrantAPI.ts @@ -5,7 +5,6 @@ import { Pagination, PaginationOptions } from '../APIRequester'; import { LCDClient } from '../LCDClient'; export class FeeGrantAPI extends BaseAPI { - constructor(public lcd: LCDClient) { super(lcd.apiRequester); } @@ -54,4 +53,37 @@ export class FeeGrantAPI extends BaseAPI { }>(`/cosmos/feegrant/v1beta1/allowance/${granter}/${grantee}`) .then(d => Allowance.fromData(d.allowance.allowance)); } + + public async allowancesByGranter( + granter: AccAddress, + params: Partial = {} + ): Promise<{ + allowances: { + granter: AccAddress; + grantee: AccAddress; + allowance: Allowance; + }[]; + pagination: Pagination; + }> { + if (this.lcd.config.isClassic) { + throw new Error('Not supported for the network'); + } + return this.c + .get<{ + allowances: { + granter: AccAddress; + grantee: AccAddress; + allowance: Allowance.Data; + }[]; + pagination: Pagination; + }>(`/cosmos/feegrant/v1beta1/issued/${granter}`, params) + .then(d => ({ + allowances: d.allowances.map(allowance => ({ + granter: allowance.granter, + grantee: allowance.grantee, + allowance: Allowance.fromData(allowance.allowance), + })), + pagination: d.pagination, + })); + } } diff --git a/src/core/Msg.ts b/src/core/Msg.ts index 20a10ca22..bc57a6015 100644 --- a/src/core/Msg.ts +++ b/src/core/Msg.ts @@ -40,6 +40,12 @@ import { MsgUndelegate, StakingMsg, } from './staking/msgs'; +import { + MsgCreatePeriodicVestingAccount, + MsgCreateVestingAccount, + MsgDonateAllVestingTokens, + VestingMsg, +} from './vesting/msgs'; import { MsgStoreCode, MsgMigrateCode, @@ -91,6 +97,7 @@ export type Msg = | OracleMsg | SlashingMsg | StakingMsg + | VestingMsg | WasmMsg | IbcTransferMsg | IbcClientMsg @@ -109,6 +116,7 @@ export namespace Msg { | OracleMsg.Amino | SlashingMsg.Amino | StakingMsg.Amino + | VestingMsg.Amino | WasmMsg.Amino | IbcTransferMsg.Amino | CrisisMsg.Amino; @@ -123,6 +131,7 @@ export namespace Msg { | OracleMsg.Data | SlashingMsg.Data | StakingMsg.Data + | VestingMsg.Data | WasmMsg.Data | IbcTransferMsg.Data | IbcClientMsg.Data @@ -140,6 +149,7 @@ export namespace Msg { | OracleMsg.Proto | SlashingMsg.Proto | StakingMsg.Proto + | VestingMsg.Proto | WasmMsg.Proto | IbcTransferMsg.Proto | IbcClientMsg.Proto @@ -238,6 +248,14 @@ export namespace Msg { case 'cosmos-sdk/MsgEditValidator': return MsgEditValidator.fromAmino(data, isClassic); + // vesting + case 'cosmos-sdk/MsgCreatePeriodicVestingAccount': + return MsgCreatePeriodicVestingAccount.fromAmino(data, isClassic); + case 'cosmos-sdk/MsgCreateVestingAccount': + return MsgCreateVestingAccount.fromAmino(data, isClassic); + case 'cosmos-sdk/MsgDonateAllVestingTokens': + return MsgDonateAllVestingTokens.fromAmino(data, isClassic); + // wasm case 'wasm/MsgStoreCode': return MsgStoreCode.fromAmino(data, isClassic); @@ -335,6 +353,14 @@ export namespace Msg { case '/cosmos.staking.v1beta1.MsgEditValidator': return MsgEditValidator.fromData(data, isClassic); + // vesting + case '/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount': + return MsgCreatePeriodicVestingAccount.fromData(data, isClassic); + case '/cosmos.vesting.v1beta1.MsgCreateVestingAccount': + return MsgCreateVestingAccount.fromData(data, isClassic); + case '/cosmos.vesting.v1beta1.MsgDonateAllVestingTokens': + return MsgDonateAllVestingTokens.fromData(data, isClassic); + // wasm case '/terra.wasm.v1beta1.MsgStoreCode': case '/cosmwasm.wasm.v1.MsgStoreCode': @@ -480,6 +506,14 @@ export namespace Msg { case '/cosmos.staking.v1beta1.MsgEditValidator': return MsgEditValidator.unpackAny(proto, isClassic); + // vesting + case '/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount': + return MsgCreatePeriodicVestingAccount.unpackAny(proto, isClassic); + case '/cosmos.vesting.v1beta1.MsgCreateVestingAccount': + return MsgCreateVestingAccount.unpackAny(proto, isClassic); + case '/cosmos.vesting.v1beta1.MsgDonateAllVestingTokens': + return MsgDonateAllVestingTokens.unpackAny(proto, isClassic); + // wasm case '/terra.wasm.v1beta1.MsgStoreCode': case '/cosmwasm.wasm.v1.MsgStoreCode': diff --git a/src/core/index.ts b/src/core/index.ts index ce9ec3839..efd4be3af 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -69,6 +69,9 @@ export * from './staking/Validator'; // Treasury export * from './treasury/PolicyConstraints'; +// Vesting +export * from './vesting'; + // Upgrade export * from './upgrade'; diff --git a/src/core/vesting/Period.ts b/src/core/vesting/Period.ts new file mode 100644 index 000000000..d57044a6c --- /dev/null +++ b/src/core/vesting/Period.ts @@ -0,0 +1,86 @@ +import { Coins } from '../Coins'; +import { Period as Period_pb } from '@terra-money/terra.proto/cosmos/vesting/v1beta1/vesting'; + +import { JSONSerializable } from '../../util/json'; +import * as Long from 'long'; +/** + * Period defines a length of time and amount of coins that will vest. + */ +export class Period extends JSONSerializable< + Period.Amino, + Period.Data, + Period.Proto +> { + public amount: Coins; + + /** + * @param length + * @param amount + */ + constructor(public length: number, amount: Coins.Input) { + super(); + this.amount = new Coins(amount); + } + + public static fromAmino(data: Period.Amino, _?: boolean): Period { + _; + const { length, amount } = data; + return new Period(Number.parseInt(length), Coins.fromAmino(amount)); + } + + public toAmino(_?: boolean): Period.Amino { + _; + const { length, amount } = this; + + const res: Period.Amino = { + length: length.toFixed(), + amount: amount.toAmino(), + }; + return res; + } + + public static fromData(data: Period.Data, _?: boolean): Period { + _; + const { length, amount } = data; + return new Period(Number.parseInt(length), Coins.fromData(amount)); + } + + public toData(_?: boolean): Period.Data { + _; + const { length, amount } = this; + + const res: Period.Amino = { + length: length.toFixed(), + amount: amount.toData(), + }; + return res; + } + + public static fromProto(proto: Period.Proto, _?: boolean): Period { + _; + return new Period(proto.length.toNumber(), Coins.fromProto(proto.amount)); + } + + public toProto(_?: boolean): Period.Proto { + _; + const { length, amount } = this; + return Period_pb.fromPartial({ + length: Long.fromNumber(length), + amount: amount.toProto(), + }); + } +} + +export namespace Period { + export interface Amino { + length: string; + amount: Coins.Amino; + } + + export interface Data { + length: string; + amount: Coins.Data; + } + + export type Proto = Period_pb; +} diff --git a/src/core/vesting/index.ts b/src/core/vesting/index.ts new file mode 100644 index 000000000..ebbdff52f --- /dev/null +++ b/src/core/vesting/index.ts @@ -0,0 +1,2 @@ +export * from './Period'; +export * from './msgs'; diff --git a/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.data.json b/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.data.json new file mode 100644 index 000000000..e0ba6e066 --- /dev/null +++ b/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.data.json @@ -0,0 +1,26 @@ +{ + "@type": "/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount", + "from_address": "terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v", + "to_address": "terra1av6ssz7k4xpc5nsjj2884nugakpp874ae0krx7", + "start_time": "1658121411", + "vesting_periods": [ + { + "length": "100", + "amount": [ + { + "denom": "uluna", + "amount": "1000000" + } + ] + }, + { + "length": "200", + "amount": [ + { + "denom": "uluna", + "amount": "2000000" + } + ] + } + ] +} diff --git a/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.spec.ts b/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.spec.ts new file mode 100644 index 000000000..ce3c756f1 --- /dev/null +++ b/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.spec.ts @@ -0,0 +1,23 @@ +const data = require('./MsgCreatePeriodicVestingAccount.data.json'); +import { MsgCreatePeriodicVestingAccount } from './MsgCreatePeriodicVestingAccount'; + +describe('MsgCreatePeriodicVestingAccount', () => { + it('deserializes', () => { + MsgCreatePeriodicVestingAccount.fromData(data); + }); + + it('conversion', () => { + const obj = MsgCreatePeriodicVestingAccount.fromData(data); + const p = obj.toProto(false); + expect(obj.from_address).toStrictEqual(p.fromAddress); + expect(obj.start_time).toStrictEqual(p.startTime.toNumber()); + expect(obj.to_address).toStrictEqual(p.toAddress); + expect(obj.vesting_periods.toString()).toStrictEqual( + p.vestingPeriods.toString() + ); + const d = obj.toData(false); + expect(obj).toStrictEqual(MsgCreatePeriodicVestingAccount.fromData(d)); + const a = obj.toAmino(false); + expect(obj).toStrictEqual(MsgCreatePeriodicVestingAccount.fromAmino(a)); + }); +}); diff --git a/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.ts b/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.ts new file mode 100644 index 000000000..deaed85c8 --- /dev/null +++ b/src/core/vesting/msgs/MsgCreatePeriodicVestingAccount.ts @@ -0,0 +1,168 @@ +import { Period } from '../Period'; +import { JSONSerializable } from '../../../util/json'; +import { AccAddress } from '../../bech32'; +import { Any } from '@terra-money/terra.proto/google/protobuf/any'; +import { MsgCreatePeriodicVestingAccount as MsgCreatePeriodicVestingAccount_pb } from '@terra-money/terra.proto/cosmos/vesting/v1beta1/tx'; +import Long from 'long'; + +/** + * CreatePeriodicVestingAccount defines a method that enables creating a periodic vesting account. + */ +export class MsgCreatePeriodicVestingAccount extends JSONSerializable< + MsgCreatePeriodicVestingAccount.Amino, + MsgCreatePeriodicVestingAccount.Data, + MsgCreatePeriodicVestingAccount.Proto +> { + /** + * @param from_address sender's address + * @param to_address recipient's address + */ + constructor( + public from_address: AccAddress, + public to_address: AccAddress, + public start_time: number, + public vesting_periods: Period[] + ) { + super(); + } + + public static fromAmino( + data: MsgCreatePeriodicVestingAccount.Amino, + isClassic?: boolean + ): MsgCreatePeriodicVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { + value: { from_address, to_address, start_time, vesting_periods }, + } = data; + return new MsgCreatePeriodicVestingAccount( + from_address, + to_address, + Number.parseInt(start_time), + vesting_periods.map(p => Period.fromAmino(p, isClassic)) + ); + } + + public toAmino(isClassic?: boolean): MsgCreatePeriodicVestingAccount.Amino { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, start_time, vesting_periods } = this; + return { + type: 'cosmos-sdk/MsgCreatePeriodicVestingAccount', + value: { + from_address, + to_address, + start_time: start_time.toFixed(), + vesting_periods: vesting_periods.map(p => p.toAmino(isClassic)), + }, + }; + } + + public static fromData( + data: MsgCreatePeriodicVestingAccount.Data, + isClassic?: boolean + ): MsgCreatePeriodicVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, start_time, vesting_periods } = data; + + return new MsgCreatePeriodicVestingAccount( + from_address, + to_address, + Number.parseInt(start_time), + vesting_periods.map(p => Period.fromData(p, isClassic)) + ); + } + + public toData(isClassic?: boolean): MsgCreatePeriodicVestingAccount.Data { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, start_time, vesting_periods } = this; + return { + '@type': '/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount', + from_address, + to_address, + start_time: start_time.toFixed(), + vesting_periods: vesting_periods.map(p => p.toData(isClassic)), + }; + } + + public static fromProto( + proto: MsgCreatePeriodicVestingAccount.Proto, + isClassic?: boolean + ): MsgCreatePeriodicVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return new MsgCreatePeriodicVestingAccount( + proto.fromAddress, + proto.toAddress, + proto.startTime.toNumber(), + proto.vestingPeriods.map(p => Period.fromProto(p, isClassic)) + ); + } + + public toProto(isClassic?: boolean): MsgCreatePeriodicVestingAccount.Proto { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, start_time, vesting_periods } = this; + return MsgCreatePeriodicVestingAccount_pb.fromPartial({ + fromAddress: from_address, + toAddress: to_address, + startTime: Long.fromNumber(start_time), + vestingPeriods: vesting_periods.map(p => p.toProto(isClassic)), + }); + } + + public packAny(isClassic?: boolean): Any { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return Any.fromPartial({ + typeUrl: '/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount', + value: MsgCreatePeriodicVestingAccount_pb.encode( + this.toProto(isClassic) + ).finish(), + }); + } + + public static unpackAny( + msgAny: Any, + isClassic?: boolean + ): MsgCreatePeriodicVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return MsgCreatePeriodicVestingAccount.fromProto( + MsgCreatePeriodicVestingAccount_pb.decode(msgAny.value), + isClassic + ); + } +} + +export namespace MsgCreatePeriodicVestingAccount { + export interface Amino { + type: 'cosmos-sdk/MsgCreatePeriodicVestingAccount'; + value: { + from_address: AccAddress; + to_address: AccAddress; + start_time: string; + vesting_periods: Period.Amino[]; + }; + } + + export interface Data { + '@type': '/cosmos.vesting.v1beta1.MsgCreatePeriodicVestingAccount'; + from_address: AccAddress; + to_address: AccAddress; + start_time: string; + vesting_periods: Period.Data[]; + } + + export type Proto = MsgCreatePeriodicVestingAccount_pb; +} diff --git a/src/core/vesting/msgs/MsgCreateVestingAccount.data.json b/src/core/vesting/msgs/MsgCreateVestingAccount.data.json new file mode 100644 index 000000000..9432256c8 --- /dev/null +++ b/src/core/vesting/msgs/MsgCreateVestingAccount.data.json @@ -0,0 +1,13 @@ +{ + "@type": "/cosmos.vesting.v1beta1.MsgCreateVestingAccount", + "from_address": "terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v", + "to_address": "terra1av6ssz7k4xpc5nsjj2884nugakpp874ae0krx7", + "amount": [ + { + "denom": "uluna", + "amount": "3000000" + } + ], + "end_time": "1658121411", + "delayed": false +} diff --git a/src/core/vesting/msgs/MsgCreateVestingAccount.spec.ts b/src/core/vesting/msgs/MsgCreateVestingAccount.spec.ts new file mode 100644 index 000000000..51114f3fa --- /dev/null +++ b/src/core/vesting/msgs/MsgCreateVestingAccount.spec.ts @@ -0,0 +1,24 @@ +const data = require('./MsgCreateVestingAccount.data.json'); +import { Coins } from '../../Coins'; +import { MsgCreateVestingAccount } from './MsgCreateVestingAccount'; + +describe('MsgCreateVestingAccount', () => { + it('deserializes', () => { + MsgCreateVestingAccount.fromData(data); + }); + + it('conversion', () => { + const obj = MsgCreateVestingAccount.fromData(data); + const p = obj.toProto(); + expect(obj.from_address).toStrictEqual(p.fromAddress); + expect(obj.to_address).toStrictEqual(p.toAddress); + expect(obj.delayed).toStrictEqual(p.delayed); + expect(obj.end_time).toStrictEqual(p.endTime.toNumber()); + expect(obj.amount).toStrictEqual(Coins.fromProto(p.amount)); + + const d = obj.toData(false); + expect(obj).toStrictEqual(MsgCreateVestingAccount.fromData(d)); + const a = obj.toAmino(false); + expect(obj).toStrictEqual(MsgCreateVestingAccount.fromAmino(a)); + }); +}); diff --git a/src/core/vesting/msgs/MsgCreateVestingAccount.ts b/src/core/vesting/msgs/MsgCreateVestingAccount.ts new file mode 100644 index 000000000..cdb34f8b2 --- /dev/null +++ b/src/core/vesting/msgs/MsgCreateVestingAccount.ts @@ -0,0 +1,181 @@ +import { Coins } from '../../Coins'; +import { JSONSerializable } from '../../../util/json'; +import { AccAddress } from '../../bech32'; +import { Any } from '@terra-money/terra.proto/google/protobuf/any'; +import { MsgCreateVestingAccount as MsgCreateVestingAccount_pb } from '@terra-money/terra.proto/cosmos/vesting/v1beta1/tx'; +import Long from 'long'; + +/** + * MsgCreateVestingAccount defines a message that enables creating a vesting account. + */ +export class MsgCreateVestingAccount extends JSONSerializable< + MsgCreateVestingAccount.Amino, + MsgCreateVestingAccount.Data, + MsgCreateVestingAccount.Proto +> { + public amount: Coins; + + /** + * @param from_address sender's address + * @param to_address recipient's address + * @param amount value of the transaction + */ + constructor( + public from_address: AccAddress, + public to_address: AccAddress, + amount: Coins.Input, + public end_time: number, + public delayed: boolean + ) { + super(); + this.amount = new Coins(amount); + } + + public static fromAmino( + data: MsgCreateVestingAccount.Amino, + isClassic?: boolean + ): MsgCreateVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { + value: { from_address, to_address, amount, end_time, delayed }, + } = data; + return new MsgCreateVestingAccount( + from_address, + to_address, + Coins.fromAmino(amount), + Number.parseInt(end_time), + delayed + ); + } + + public toAmino(isClassic?: boolean): MsgCreateVestingAccount.Amino { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, amount, end_time, delayed } = this; + return { + type: 'cosmos-sdk/MsgCreateVestingAccount', + value: { + from_address, + to_address, + amount: amount.toAmino(), + end_time: end_time.toFixed(), + delayed, + }, + }; + } + + public static fromData( + data: MsgCreateVestingAccount.Data, + isClassic?: boolean + ): MsgCreateVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, amount, end_time, delayed } = data; + + return new MsgCreateVestingAccount( + from_address, + to_address, + Coins.fromData(amount), + Number.parseInt(end_time), + delayed + ); + } + + public toData(isClassic?: boolean): MsgCreateVestingAccount.Data { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, amount, end_time, delayed } = this; + return { + '@type': '/cosmos.vesting.v1beta1.MsgCreateVestingAccount', + from_address, + to_address, + amount: amount.toData(), + end_time: end_time.toFixed(), + delayed, + }; + } + + public static fromProto( + proto: MsgCreateVestingAccount.Proto, + isClassic?: boolean + ): MsgCreateVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return new MsgCreateVestingAccount( + proto.fromAddress, + proto.toAddress, + Coins.fromProto(proto.amount), + proto.endTime.toNumber(), + proto.delayed + ); + } + + public toProto(isClassic?: boolean): MsgCreateVestingAccount.Proto { + if (isClassic) { + throw new Error('Not supported for the network'); + } + const { from_address, to_address, amount, end_time, delayed } = this; + return MsgCreateVestingAccount_pb.fromPartial({ + fromAddress: from_address, + toAddress: to_address, + amount: amount.toProto(), + endTime: Long.fromNumber(end_time), + delayed, + }); + } + + public packAny(isClassic?: boolean): Any { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return Any.fromPartial({ + typeUrl: '/cosmos.vesting.v1beta1.MsgCreateVestingAccount', + value: MsgCreateVestingAccount_pb.encode( + this.toProto(isClassic) + ).finish(), + }); + } + + public static unpackAny( + msgAny: Any, + isClassic?: boolean + ): MsgCreateVestingAccount { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return MsgCreateVestingAccount.fromProto( + MsgCreateVestingAccount_pb.decode(msgAny.value), + isClassic + ); + } +} + +export namespace MsgCreateVestingAccount { + export interface Amino { + type: 'cosmos-sdk/MsgCreateVestingAccount'; + value: { + from_address: AccAddress; + to_address: AccAddress; + amount: Coins.Amino; + end_time: string; + delayed: boolean; + }; + } + + export interface Data { + '@type': '/cosmos.vesting.v1beta1.MsgCreateVestingAccount'; + from_address: AccAddress; + to_address: AccAddress; + amount: Coins.Data; + end_time: string; + delayed: boolean; + } + + export type Proto = MsgCreateVestingAccount_pb; +} diff --git a/src/core/vesting/msgs/MsgDonateAllVestingTokens.data.json b/src/core/vesting/msgs/MsgDonateAllVestingTokens.data.json new file mode 100644 index 000000000..f25be0b4f --- /dev/null +++ b/src/core/vesting/msgs/MsgDonateAllVestingTokens.data.json @@ -0,0 +1,4 @@ +{ + "@type": "/cosmos.vesting.v1beta1.MsgDonateAllVestingTokens", + "from_address": "terra1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v" +} diff --git a/src/core/vesting/msgs/MsgDonateAllVestingTokens.spec.ts b/src/core/vesting/msgs/MsgDonateAllVestingTokens.spec.ts new file mode 100644 index 000000000..e9a6501c2 --- /dev/null +++ b/src/core/vesting/msgs/MsgDonateAllVestingTokens.spec.ts @@ -0,0 +1,20 @@ +const data = require('./MsgDonateAllVestingTokens.data.json'); +import { Coins } from '../../Coins'; +import { MsgDonateAllVestingTokens } from './MsgDonateAllVestingTokens'; + +describe('MsgDonateAllVestingTokens', () => { + it('deserializes', () => { + MsgDonateAllVestingTokens.fromData(data); + }); + + it('conversion', () => { + const obj = MsgDonateAllVestingTokens.fromData(data); + const p = obj.toProto(); + expect(obj.from_address).toStrictEqual(p.fromAddress); + + const d = obj.toData(false); + expect(obj).toStrictEqual(MsgDonateAllVestingTokens.fromData(d)); + const a = obj.toAmino(false); + expect(obj).toStrictEqual(MsgDonateAllVestingTokens.fromAmino(a)); + }); +}); diff --git a/src/core/vesting/msgs/MsgDonateAllVestingTokens.ts b/src/core/vesting/msgs/MsgDonateAllVestingTokens.ts new file mode 100644 index 000000000..380b80390 --- /dev/null +++ b/src/core/vesting/msgs/MsgDonateAllVestingTokens.ts @@ -0,0 +1,122 @@ +import { JSONSerializable } from '../../../util/json'; +import { AccAddress } from '../../bech32'; +import { Any } from '@terra-money/terra.proto/google/protobuf/any'; +import { MsgDonateAllVestingTokens as MsgDonateAllVestingTokens_pb } from '@terra-money/terra.proto/cosmos/vesting/v1beta1/tx'; + +/** + * DonateAllVestingTokens defines a method that enables donating all vesting + */ +export class MsgDonateAllVestingTokens extends JSONSerializable< + MsgDonateAllVestingTokens.Amino, + MsgDonateAllVestingTokens.Data, + MsgDonateAllVestingTokens.Proto +> { + /** + * @param from_address donor's address + */ + constructor(public from_address: AccAddress) { + super(); + } + + public static fromAmino( + data: MsgDonateAllVestingTokens.Amino, + isClassic?: boolean + ): MsgDonateAllVestingTokens { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return new MsgDonateAllVestingTokens(data.value.from_address); + } + + public toAmino(isClassic?: boolean): MsgDonateAllVestingTokens.Amino { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return { + type: 'cosmos-sdk/MsgDonateAllVestingTokens', + value: { + from_address: this.from_address, + }, + }; + } + + public static fromData( + data: MsgDonateAllVestingTokens.Data, + isClassic?: boolean + ): MsgDonateAllVestingTokens { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return new MsgDonateAllVestingTokens(data.from_address); + } + + public toData(isClassic?: boolean): MsgDonateAllVestingTokens.Data { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return { + '@type': '/cosmos.vesting.v1beta1.MsgDonateAllVestingTokens', + from_address: this.from_address, + }; + } + + public static fromProto( + proto: MsgDonateAllVestingTokens.Proto, + isClassic?: boolean + ): MsgDonateAllVestingTokens { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return new MsgDonateAllVestingTokens(proto.fromAddress); + } + + public toProto(isClassic?: boolean): MsgDonateAllVestingTokens.Proto { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return MsgDonateAllVestingTokens_pb.fromPartial({ + fromAddress: this.from_address, + }); + } + + public packAny(isClassic?: boolean): Any { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return Any.fromPartial({ + typeUrl: '/cosmos.vesting.v1beta1.MsgDonateAllVestingTokens', + value: MsgDonateAllVestingTokens_pb.encode( + this.toProto(isClassic) + ).finish(), + }); + } + + public static unpackAny( + msgAny: Any, + isClassic?: boolean + ): MsgDonateAllVestingTokens { + if (isClassic) { + throw new Error('Not supported for the network'); + } + return MsgDonateAllVestingTokens.fromProto( + MsgDonateAllVestingTokens_pb.decode(msgAny.value), + isClassic + ); + } +} + +export namespace MsgDonateAllVestingTokens { + export interface Amino { + type: 'cosmos-sdk/MsgDonateAllVestingTokens'; + value: { + from_address: AccAddress; + }; + } + + export interface Data { + '@type': '/cosmos.vesting.v1beta1.MsgDonateAllVestingTokens'; + from_address: AccAddress; + } + + export type Proto = MsgDonateAllVestingTokens_pb; +} diff --git a/src/core/vesting/msgs/index.ts b/src/core/vesting/msgs/index.ts new file mode 100644 index 000000000..c8150245b --- /dev/null +++ b/src/core/vesting/msgs/index.ts @@ -0,0 +1,27 @@ +import { MsgCreatePeriodicVestingAccount } from './MsgCreatePeriodicVestingAccount'; +import { MsgCreateVestingAccount } from './MsgCreateVestingAccount'; +import { MsgDonateAllVestingTokens } from './MsgDonateAllVestingTokens'; + +export * from './MsgCreatePeriodicVestingAccount'; +export * from './MsgCreateVestingAccount'; +export * from './MsgDonateAllVestingTokens'; + +export type VestingMsg = + | MsgCreatePeriodicVestingAccount + | MsgCreateVestingAccount + | MsgDonateAllVestingTokens; + +export namespace VestingMsg { + export type Amino = + | MsgCreatePeriodicVestingAccount.Amino + | MsgCreateVestingAccount.Amino + | MsgDonateAllVestingTokens.Amino; + export type Data = + | MsgCreatePeriodicVestingAccount.Data + | MsgCreateVestingAccount.Data + | MsgDonateAllVestingTokens.Data; + export type Proto = + | MsgCreatePeriodicVestingAccount.Proto + | MsgCreateVestingAccount.Proto + | MsgDonateAllVestingTokens.Proto; +}