UNPKG

@kyve/sdk

Version:

<p align="center"> <a href="https://kyve.network"> <img src="https://user-images.githubusercontent.com/62398724/137493477-63868209-a19b-4efa-9413-f06d41197d6d.png" style="border-radius: 50%" height="96"> </a> <h3 align="center"><code>@kyve/sdk</

402 lines (378 loc) 11.9 kB
import KyveClient from "../../src/clients/rpc-client/client"; import { createValidator } from "../helper"; import * as fs from "fs"; import { resolve } from "path"; import { kyve, cosmos as cosmosProto } from "@kyve/proto"; import MsgSubmitBundleProposal = kyve.registry.v1beta1.kyveBundles.MsgSubmitBundleProposal; import MsgVoteBundleProposal = kyve.registry.v1beta1.kyveBundles.MsgVoteBundleProposal; import MsgClaimUploaderRole = kyve.registry.v1beta1.kyveBundles.MsgClaimUploaderRole; import MsgSkipUploaderRole = kyve.registry.v1beta1.kyveBundles.MsgSkipUploaderRole; import MsgDelegate = kyve.registry.v1beta1.kyveDelegation.MsgDelegate; import MsgWithdrawRewards = kyve.registry.v1beta1.kyveDelegation.MsgWithdrawRewards; import MsgUndelegate = kyve.registry.v1beta1.kyveDelegation.MsgUndelegate; import MsgRedelegate = kyve.registry.v1beta1.kyveDelegation.MsgRedelegate; import MsgFundPool = kyve.registry.v1beta1.kyvePool.MsgFundPool; import MsgDefundPool = kyve.registry.v1beta1.kyvePool.MsgDefundPool; import MsgCreateStaker = kyve.registry.v1beta1.kyveStakers.MsgCreateStaker; import MsgUpdateMetadata = kyve.registry.v1beta1.kyveStakers.MsgUpdateMetadata; import MsgUpdateCommission = kyve.registry.v1beta1.kyveStakers.MsgUpdateCommission; import MsgJoinPool = kyve.registry.v1beta1.kyveStakers.MsgJoinPool; import MsgLeavePool = kyve.registry.v1beta1.kyveStakers.MsgLeavePool; import TextProposal = cosmosProto.registry.v1beta1.cosmosGov.TextProposal; import ParameterChangeProposal = cosmosProto.registry.v1beta1.cosmosParams.ParameterChangeProposal; import CreatePoolProposal = kyve.registry.v1beta1.kyveGovPool.CreatePoolProposal; import CancelPoolUpgradeProposal = kyve.registry.v1beta1.kyveGov.CancelPoolUpgradeProposal; import PausePoolProposal = kyve.registry.v1beta1.kyveGov.PausePoolProposal; import ResetPoolProposal = kyve.registry.v1beta1.kyveGov.ResetPoolProposal; import SchedulePoolUpgradeProposal = kyve.registry.v1beta1.kyveGov.SchedulePoolUpgradeProposal; import UnpausePoolProposal = kyve.registry.v1beta1.kyveGov.UnpausePoolProposal; import UpdatePoolProposal = kyve.registry.v1beta1.kyveGov.UpdatePoolProposal; import Mock = jest.Mock; import { DENOM, KYVE_DECIMALS } from "../../src/constants"; import BigNumber from "bignumber.js"; import { SigningStargateClient } from "@cosmjs/stargate"; import { cosmos } from "@keplr-wallet/cosmos"; import TxRaw = cosmos.tx.v1beta1.TxRaw; import { OfflineAminoSigner } from "@cosmjs/amino/build/signer"; function extractTsFromPath(path: string) { return fs .readdirSync(path) .filter((files) => files.endsWith("d.ts")) .map((dtsFiles) => resolve(path, dtsFiles)); } const mockAccountData = { address: "kyve19jc64sd773gtjljksjhls0n5mqay7xj83yeqvk", algo: "secp256k1" as const, pubkey: new Uint8Array(), }; const TEST_MEMO = "test_memo"; const TEST_FEE = 1; const TEST_AMOUNT = "1000000000"; const methodsByGroup = [ [ { name: "bundles", pathToTypes: extractTsFromPath( "../proto/dist/proto/kyve/bundles/v1beta1" ), }, [ { methodName: "submitBundleProposal", parameters: { params: MsgSubmitBundleProposal.fromJSON({}), schemaType: "MsgSubmitBundleProposal", }, }, { methodName: "voteBundleProposal", parameters: { params: MsgVoteBundleProposal.fromJSON({}), schemaType: "MsgVoteBundleProposal", }, }, { methodName: "claimUploaderRole", parameters: { params: MsgClaimUploaderRole.fromJSON({}), schemaType: "MsgClaimUploaderRole", }, }, { methodName: "skipUploaderRole", parameters: { params: MsgSkipUploaderRole.fromJSON({}), schemaType: "MsgSkipUploaderRole", }, }, ], ], [ { name: "delegation", pathToTypes: extractTsFromPath( "../proto/dist/proto/kyve/delegation/v1beta1" ), }, [ { methodName: "delegate", parameters: { params: MsgDelegate.fromJSON({}), schemaType: "MsgDelegate", }, }, { methodName: "withdrawRewards", parameters: { params: MsgWithdrawRewards.fromJSON({}), schemaType: "MsgWithdrawRewards", }, }, { methodName: "undelegate", parameters: { params: MsgUndelegate.fromJSON({}), schemaType: "MsgUndelegate", }, }, { methodName: "redelegate", parameters: { params: MsgRedelegate.fromJSON({}), schemaType: "MsgRedelegate", }, }, ], ], [ { name: "pool", pathToTypes: extractTsFromPath("../proto/dist/proto/kyve/pool/v1beta1"), }, [ { methodName: "fundPool", parameters: { params: MsgFundPool.fromJSON({}), schemaType: "MsgFundPool", }, }, { methodName: "defundPool", parameters: { params: MsgDefundPool.fromJSON({}), schemaType: "MsgDefundPool", }, }, ], ], [ { name: "stakers", pathToTypes: extractTsFromPath( "../proto/dist/proto/kyve/stakers/v1beta1" ), }, [ { methodName: "createStaker", parameters: { params: MsgCreateStaker.fromJSON({}), schemaType: "MsgCreateStaker", }, }, { methodName: "updateMetadata", parameters: { params: MsgUpdateMetadata.fromJSON({}), schemaType: "MsgUpdateMetadata", }, }, { methodName: "updateCommission", parameters: { params: MsgUpdateCommission.fromJSON({}), schemaType: "MsgUpdateCommission", }, }, { methodName: "joinPool", parameters: { params: MsgJoinPool.fromJSON({}), schemaType: "MsgJoinPool", }, }, { methodName: "leavePool", parameters: { params: MsgLeavePool.fromJSON({}), schemaType: "MsgLeavePool", }, }, ], ], ] as const; let kyveClient: KyveClient; let mockSign: Mock; let mockSendTokens: Mock; let mockGetBalance: Mock; beforeEach(() => { mockSign = jest.fn(() => TxRaw.create()); mockSendTokens = jest.fn(); mockGetBalance = jest.fn(() => ({ amount: 0 })); const mockNativeClient = { simulate: () => Promise.resolve(1), sign: mockSign, sendTokens: mockSendTokens, getBalance: mockGetBalance, } as unknown as SigningStargateClient; const mockAminoSigner = { signAmino() {}, getAccounts() {}, } as unknown as OfflineAminoSigner; kyveClient = new KyveClient( mockNativeClient, mockAccountData, mockAminoSigner ); }); for (let [bundleConfig, methods] of methodsByGroup) { describe(`Methods ${bundleConfig.name}`, () => { const validator = createValidator(bundleConfig.pathToTypes); methods.forEach((method) => { it(`method ${method.methodName}`, async () => { // @ts-ignore await kyveClient.kyve[bundleConfig.name].v1beta1[method.methodName]( //@ts-ignore have no idea how to create it generic. btw ts-ignore is ok, because we check params from json schema method.parameters.params, { memo: TEST_MEMO, fee: TEST_FEE } ); expect(mockSign).toHaveBeenCalledTimes(1); const [[testAddress, [tx], fee, memo]] = mockSign.mock.calls; expect(testAddress).toEqual(mockAccountData.address); expect(tx).toEqual( expect.objectContaining({ typeUrl: expect.any(String), value: expect.any(Object), }) ); expect(memo).toEqual(TEST_MEMO); const validationResult = validator.validate( validator.typeQuerySchemas.getSchemaForSymbol( method.parameters.schemaType ), tx.value ); expect(validationResult.valid).toBeTruthy(); expect(Object.keys(fee).sort()).toEqual(["amount", "gas"].sort()); }); }); }); } describe("Base methods", () => { it("transfer", async () => { const testRecipient = "kyveTestRecipient"; const testAmount = "1"; await kyveClient.kyve.base.v1beta1.transfer(testRecipient, testAmount, { memo: TEST_MEMO, fee: TEST_FEE, }); expect(mockSendTokens).toHaveBeenCalledTimes(1); const [[ownerAddress, recipient, [coin], fee, memo]] = mockSendTokens.mock.calls; expect(ownerAddress).toEqual(mockAccountData.address); expect(recipient).toEqual(testRecipient); expect(memo).toEqual(TEST_MEMO); expect(fee).toEqual(TEST_FEE); expect(coin).toEqual({ denom: DENOM, amount: new BigNumber(10).pow(KYVE_DECIMALS).toString(), }); }); it("getKyveBalance", async () => { const result = await kyveClient.kyve.base.v1beta1.getKyveBalance(); expect(mockGetBalance).toHaveBeenCalledTimes(1); const [[ownerAddress, denom]] = mockGetBalance.mock.calls; expect(ownerAddress).toEqual(mockAccountData.address); expect(denom).toEqual(DENOM); expect(result).toEqual(0); }); }); const GovMethods = [ { method: "submitTextProposal", decoder: TextProposal, }, { method: "parameterChangeProposal", decoder: ParameterChangeProposal, }, { method: "pausePoolProposal", decoder: PausePoolProposal, }, { method: "updatePoolProposal", decoder: UpdatePoolProposal, }, { method: "pausePoolProposal", decoder: PausePoolProposal, }, { method: "unpausePoolProposal", decoder: UnpausePoolProposal, }, { method: "schedulePoolUpgradeProposal", decoder: SchedulePoolUpgradeProposal, }, // { // method: "cancelPoolUpgradeProposal", // decoder: CancelPoolUpgradeProposal, // }, { method: "resetPoolProposal", decoder: ResetPoolProposal, }, { method: "createPoolProposal", decoder: CreatePoolProposal, }, ] as const; describe("Gov methods", () => { GovMethods.forEach((method) => { it(`${method.method}`, async () => { const govParam = method.decoder.fromJSON({}); //@ts-ignore await kyveClient.kyve.gov.v1beta1[method.method](TEST_AMOUNT, govParam, { isExpedited: true, }); expect(mockSign).toHaveBeenCalledTimes(1); const [[testAddress, [tx], fee]] = mockSign.mock.calls; expect(testAddress).toEqual(mockAccountData.address); expect(tx).toEqual( expect.objectContaining({ typeUrl: expect.any(String), value: { content: { type_url: expect.any(String), value: expect.any(Uint8Array), }, initial_deposit: [ { denom: DENOM, amount: TEST_AMOUNT, }, ], proposer: mockAccountData.address, is_expedited: true, }, }) ); expect(Object.keys(fee).sort()).toEqual(["amount", "gas"].sort()); expect(method.decoder.decode(tx.value.content.value)).toEqual(govParam); }); }); it("`govVote`", async () => { const testProposalNumber = "1"; const testVoteOptions = "Yes"; await kyveClient.kyve.gov.v1beta1.govVote( testProposalNumber, testVoteOptions ); expect(mockSign).toHaveBeenCalledTimes(1); const [[testAddress, [tx], fee]] = mockSign.mock.calls; expect(testAddress).toEqual(mockAccountData.address); expect(Object.keys(fee).sort()).toEqual(["amount", "gas"].sort()); expect(tx).toEqual({ typeUrl: "/cosmos.gov.v1beta1.MsgVote", value: { proposalId: testProposalNumber, voter: mockAccountData.address, option: 1, }, }); }); });