From 67c5d469316712379480aacda244347597f255cf Mon Sep 17 00:00:00 2001 From: Troy Kessler <43882936+troykessler@users.noreply.github.com> Date: Thu, 9 Feb 2023 16:19:32 +0100 Subject: [PATCH] Refactor/fees (#21) * started implementing dynamic gas pricing * finished refactoring sdk * refactored sdk config * added new sdk config structure to core and kysor * refactored fee metrics * fixed sdk options * implemented fees in cosmostation * fixed linting errors --- common/protocol/src/index.ts | 9 +- .../src/methods/setups/setupMetrics.ts | 26 ++-- .../protocol/src/methods/setups/setupSDK.ts | 5 +- .../src/methods/txs/claimUploaderRole.ts | 2 +- .../src/methods/txs/skipUploaderRole.ts | 2 +- .../src/methods/txs/submitBundleProposal.ts | 4 +- .../src/methods/txs/voteBundleProposal.ts | 2 +- common/protocol/src/types/metrics.ts | 10 +- common/sdk/src/clients/full-client.ts | 17 ++- common/sdk/src/clients/rpc-client/client.ts | 26 ++-- .../rpc-client/kyve/base/v1beta1/base.ts | 57 +++---- .../kyve/bundles/v1beta1/bundles.ts | 46 ++---- .../kyve/delegation/v1beta1/delegation.ts | 45 ++---- .../src/clients/rpc-client/kyve/gov/v1/gov.ts | 80 ++-------- .../rpc-client/kyve/pool/v1beta1/pool.ts | 31 +--- .../kyve/stakers/v1beta1/stakers.ts | 56 ++----- common/sdk/src/clients/rpc-client/signing.ts | 143 ++++++++++++++++++ .../sdk/src/clients/rpc-client/web.client.ts | 4 +- common/sdk/src/constants.ts | 90 ++++++++--- common/sdk/src/sdk.ts | 92 ++++++----- common/sdk/src/utils/cosmostation-helper.ts | 8 +- common/sdk/src/utils/helper.ts | 98 ------------ common/sdk/src/utils/keplr-helper.ts | 7 +- tools/kysor/src/commands/init.ts | 19 +-- tools/kysor/src/commands/valaccounts.ts | 38 ++--- tools/kysor/src/index.ts | 2 +- tools/kysor/src/kysor.ts | 5 +- tools/kysor/src/types/interfaces.ts | 5 +- tools/kysor/src/utils/constants.ts | 5 +- tools/kysor/src/utils/index.ts | 1 + 30 files changed, 441 insertions(+), 494 deletions(-) create mode 100644 common/sdk/src/clients/rpc-client/signing.ts delete mode 100644 common/sdk/src/utils/helper.ts diff --git a/common/protocol/src/index.ts b/common/protocol/src/index.ts index 25ff58dc..55989fcc 100644 --- a/common/protocol/src/index.ts +++ b/common/protocol/src/index.ts @@ -51,6 +51,7 @@ import { } from "./methods"; import { ICacheProvider, IMetrics, IRuntime } from "./types"; import { standardizeJSON } from "./utils"; +import { SupportedChains } from "@kyvejs/sdk/dist/constants"; /** * Main class of KYVE protocol nodes representing a validator node. @@ -85,9 +86,10 @@ export class Validator { protected staker!: string; protected valaccount!: string; protected storagePriv!: string; - protected chainId!: string; + protected chainId!: SupportedChains; protected rpc!: string[]; protected rest!: string[]; + protected gasPrice: number | undefined; protected cache!: string; protected debug!: boolean; protected metrics!: boolean; @@ -218,6 +220,10 @@ export class Validator { "Comma separated list of rest endpoints. If the first fails the next endpoint will be used as fallback.", parseEndpoints ) + .option( + "--gas-price ", + "The gas price the node should use to calculate transaction fees" + ) .option( "--cache ", "The cache this node should use", @@ -267,6 +273,7 @@ export class Validator { this.chainId = options.chainId; this.rpc = options.rpc; this.rest = options.rest; + this.gasPrice = options.gasPrice; this.cache = options.cache; this.debug = options.debug; this.metrics = options.metrics; diff --git a/common/protocol/src/methods/setups/setupMetrics.ts b/common/protocol/src/methods/setups/setupMetrics.ts index 648271a0..e9896fbe 100644 --- a/common/protocol/src/methods/setups/setupMetrics.ts +++ b/common/protocol/src/methods/setups/setupMetrics.ts @@ -360,33 +360,33 @@ export function setupMetrics(this: Validator): void { help: "The current index of the first data item in the cache.", }); - // GAS METRICS + // FEE METRICS - this.logger.debug(`Initializing metrics: gas_claim_uploader_role`); + this.logger.debug(`Initializing metrics: fees_claim_uploader_role`); - this.m.gas_claim_uploader_role = new prom_client.Gauge({ - name: "gas_claim_uploader_role", + this.m.fees_claim_uploader_role = new prom_client.Counter({ + name: "fees_claim_uploader_role", help: "The current gas costs of tx claim uploader role metrics", }); - this.logger.debug(`Initializing metrics: gas_vote_bundle_proposal`); + this.logger.debug(`Initializing metrics: fees_vote_bundle_proposal`); - this.m.gas_vote_bundle_proposal = new prom_client.Gauge({ - name: "gas_vote_bundle_proposal", + this.m.fees_vote_bundle_proposal = new prom_client.Counter({ + name: "fees_vote_bundle_proposal", help: "The current gas costs of tx vote bundle proposal metrics", }); - this.logger.debug(`Initializing metrics: gas_submit_bundle_proposal`); + this.logger.debug(`Initializing metrics: fees_submit_bundle_proposal`); - this.m.gas_submit_bundle_proposal = new prom_client.Gauge({ - name: "gas_submit_bundle_proposal", + this.m.fees_submit_bundle_proposal = new prom_client.Counter({ + name: "fees_submit_bundle_proposal", help: "The current gas costs of tx submit bundle proposal metrics", }); - this.logger.debug(`Initializing metrics: gas_skip_uploader_role`); + this.logger.debug(`Initializing metrics: fees_skip_uploader_role`); - this.m.gas_skip_uploader_role = new prom_client.Gauge({ - name: "gas_skip_uploader_role", + this.m.fees_skip_uploader_role = new prom_client.Counter({ + name: "fees_skip_uploader_role", help: "The current gas costs of tx skip uploader role metrics", }); diff --git a/common/protocol/src/methods/setups/setupSDK.ts b/common/protocol/src/methods/setups/setupSDK.ts index 88ac17f7..53156a5b 100644 --- a/common/protocol/src/methods/setups/setupSDK.ts +++ b/common/protocol/src/methods/setups/setupSDK.ts @@ -23,11 +23,10 @@ export async function setupSDK(this: Validator): Promise { this.sdk = this.rpc.map( (_, i) => - new KyveSDK({ + new KyveSDK(this.chainId, { rpc: this.rpc[i], rest: this.rest[i], - chainId: this.chainId, - chainName: `KYVE - ${this.chainId}`, + gasPrice: this.gasPrice, }) ); diff --git a/common/protocol/src/methods/txs/claimUploaderRole.ts b/common/protocol/src/methods/txs/claimUploaderRole.ts index dc4c8cc6..1506ca8e 100644 --- a/common/protocol/src/methods/txs/claimUploaderRole.ts +++ b/common/protocol/src/methods/txs/claimUploaderRole.ts @@ -42,7 +42,7 @@ export async function claimUploaderRole(this: Validator): Promise { if (receipt.code === 0) { this.logger.info(`Successfully claimed uploader role`); this.m.tx_claim_uploader_role_successful.inc(); - this.m.gas_claim_uploader_role.set(receipt?.gasUsed ?? 0); + this.m.fees_claim_uploader_role.inc(parseInt(tx.fee.amount[0].amount)); return true; } else { diff --git a/common/protocol/src/methods/txs/skipUploaderRole.ts b/common/protocol/src/methods/txs/skipUploaderRole.ts index 552de3f4..dfbf895c 100644 --- a/common/protocol/src/methods/txs/skipUploaderRole.ts +++ b/common/protocol/src/methods/txs/skipUploaderRole.ts @@ -48,7 +48,7 @@ export async function skipUploaderRole( if (receipt.code === 0) { this.logger.info(`Successfully skipped uploader role`); this.m.tx_skip_uploader_role_successful.inc(); - this.m.gas_skip_uploader_role.set(receipt?.gasUsed ?? 0); + this.m.fees_skip_uploader_role.inc(parseInt(tx.fee.amount[0].amount)); return true; } else { diff --git a/common/protocol/src/methods/txs/submitBundleProposal.ts b/common/protocol/src/methods/txs/submitBundleProposal.ts index d9c51177..5b7cd185 100644 --- a/common/protocol/src/methods/txs/submitBundleProposal.ts +++ b/common/protocol/src/methods/txs/submitBundleProposal.ts @@ -63,7 +63,9 @@ export async function submitBundleProposal( if (receipt.code === 0) { this.m.tx_submit_bundle_proposal_successful.inc(); - this.m.gas_submit_bundle_proposal.set(receipt?.gasUsed ?? 0); + this.m.fees_submit_bundle_proposal.inc( + parseInt(tx.fee.amount[0].amount) + ); this.m.bundles_proposed.inc(); this.m.bundles_amount.inc(); diff --git a/common/protocol/src/methods/txs/voteBundleProposal.ts b/common/protocol/src/methods/txs/voteBundleProposal.ts index 1c3d00a3..1bbed12f 100644 --- a/common/protocol/src/methods/txs/voteBundleProposal.ts +++ b/common/protocol/src/methods/txs/voteBundleProposal.ts @@ -59,7 +59,7 @@ export async function voteBundleProposal( this.logger.info(`Voted ${voteMessage} on bundle "${storageId}"`); this.m.tx_vote_bundle_proposal_successful.inc(); - this.m.gas_vote_bundle_proposal.set(receipt?.gasUsed ?? 0); + this.m.fees_vote_bundle_proposal.inc(parseInt(tx.fee.amount[0].amount)); if (vote === 1) { this.m.bundles_voted_valid.inc(); diff --git a/common/protocol/src/types/metrics.ts b/common/protocol/src/types/metrics.ts index 1a767691..a82ecfcb 100644 --- a/common/protocol/src/types/metrics.ts +++ b/common/protocol/src/types/metrics.ts @@ -91,10 +91,10 @@ export interface IMetrics { cache_index_tail: PromGauge; cache_index_head: PromGauge; - // GAS METRICS + // FEE METRICS - gas_claim_uploader_role: PromGauge; - gas_vote_bundle_proposal: PromGauge; - gas_submit_bundle_proposal: PromGauge; - gas_skip_uploader_role: PromGauge; + fees_claim_uploader_role: PromCounter; + fees_vote_bundle_proposal: PromCounter; + fees_submit_bundle_proposal: PromCounter; + fees_skip_uploader_role: PromCounter; } diff --git a/common/sdk/src/clients/full-client.ts b/common/sdk/src/clients/full-client.ts index 07d47123..00d123f5 100644 --- a/common/sdk/src/clients/full-client.ts +++ b/common/sdk/src/clients/full-client.ts @@ -1,14 +1,14 @@ import { OfflineAminoSigner } from "@cosmjs/amino/build/signer"; import { OfflineSigner, Registry } from "@cosmjs/proto-signing"; import { GasPrice, SigningStargateClient } from "@cosmjs/stargate"; -import { SDKConfig } from "../constants"; +import { IConfig } from "../constants"; import * as KyveRegistryTx from "../registry/tx.registry"; import KyveClient from "./rpc-client/client"; import KyveWebClient from "./rpc-client/web.client"; export async function getSigningKyveClient( - config: SDKConfig, + config: IConfig, signer: OfflineSigner, aminoSigner: OfflineAminoSigner | null, walletName?: undefined, @@ -16,7 +16,7 @@ export async function getSigningKyveClient( ): Promise; export async function getSigningKyveClient( - config: SDKConfig, + config: IConfig, signer: OfflineSigner, aminoSigner: OfflineAminoSigner | null, walletName?: string, @@ -24,20 +24,25 @@ export async function getSigningKyveClient( ): Promise; export async function getSigningKyveClient( - config: SDKConfig, + config: IConfig, signer: OfflineSigner, aminoSigner: OfflineAminoSigner | null, walletName?: string ): Promise { const registry = new Registry([...KyveRegistryTx.registry]); - const gasPrice = GasPrice.fromString("0tkyve"); + const gasPrice = GasPrice.fromString(`${config.gasPrice}${config.coinDenom}`); + const client: SigningStargateClient = await SigningStargateClient.connectWithSigner(config.rpc, signer, { registry, gasPrice, }); + const [account] = await signer.getAccounts(); - if (typeof walletName === "string") + + if (typeof walletName === "string") { return new KyveWebClient(client, account, config, aminoSigner, walletName); + } + return new KyveClient(client, account, config, aminoSigner); } diff --git a/common/sdk/src/clients/rpc-client/client.ts b/common/sdk/src/clients/rpc-client/client.ts index bcc15e67..77866538 100644 --- a/common/sdk/src/clients/rpc-client/client.ts +++ b/common/sdk/src/clients/rpc-client/client.ts @@ -1,11 +1,9 @@ import { StdSignature } from "@cosmjs/amino"; -import { StdFee } from "@cosmjs/amino/build/signdoc"; import { AccountData, OfflineAminoSigner } from "@cosmjs/amino/build/signer"; import { SigningStargateClient } from "@cosmjs/stargate"; import { makeADR36AminoSignDoc } from "@keplr-wallet/cosmos"; -import { SDKConfig } from "../../constants"; -import { signTx, TxPromise } from "../../utils/helper"; +import { IConfig } from "../../constants"; import KyveBaseMethods from "./kyve/base/v1beta1/base"; import KyveBundlesMethods from "./kyve/bundles/v1beta1/bundles"; import KyveDelegationMethods from "./kyve/delegation/v1beta1/delegation"; @@ -16,7 +14,7 @@ import KyveStakersMethods from "./kyve/stakers/v1beta1/stakers"; export default class KyveClient { public nativeClient: SigningStargateClient; public readonly account: AccountData; - public readonly config: SDKConfig; + public readonly config: IConfig; public kyve: { base: { v1beta1: KyveBaseMethods; @@ -42,7 +40,7 @@ export default class KyveClient { constructor( client: SigningStargateClient, account: AccountData, - config: SDKConfig, + config: IConfig, aminoSigner: OfflineAminoSigner | null ) { this.account = account; @@ -82,6 +80,7 @@ export default class KyveClient { }, }; } + async signString(message: string): Promise { if (this.aminoSigner === null) throw new Error("Wallet doesn't support adr-036"); @@ -92,17 +91,12 @@ export default class KyveClient { ); return signature; } - async txsAll( - txs: TxPromise[], - options?: { - fee?: StdFee | "auto" | number; - memo?: string; - } - ) { - const txMessages = txs.map((tx) => tx.tx).flat(); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, txMessages, options) + + async getKyveBalance(): Promise { + const data = await this.nativeClient.getBalance( + this.account.address, + this.config.coinDenom ); + return data.amount; } } diff --git a/common/sdk/src/clients/rpc-client/kyve/base/v1beta1/base.ts b/common/sdk/src/clients/rpc-client/kyve/base/v1beta1/base.ts index 0a5b8546..3816b4c7 100644 --- a/common/sdk/src/clients/rpc-client/kyve/base/v1beta1/base.ts +++ b/common/sdk/src/clients/rpc-client/kyve/base/v1beta1/base.ts @@ -1,26 +1,10 @@ import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { AccountData } from "@cosmjs/amino/build/signer"; -import { coins, SigningStargateClient } from "@cosmjs/stargate"; +import { coins } from "@cosmjs/stargate"; import BigNumber from "bignumber.js"; -import { SDKConfig } from "../../../../../constants"; -import { signTx, TxPromise } from "../../../../../utils/helper"; - -export default class KyveBaseMsg { - private nativeClient: SigningStargateClient; - public readonly account: AccountData; - public readonly config: SDKConfig; - - constructor( - client: SigningStargateClient, - account: AccountData, - config: SDKConfig - ) { - this.account = account; - this.nativeClient = client; - this.config = config; - } +import { KyveSigning, PendingSignedTx } from "../../../signing"; +export default class KyveBaseMsg extends KyveSigning { async transfer( recipient: string, amount: string, @@ -38,13 +22,17 @@ export default class KyveBaseMsg { }, }; - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } - async multiTransfer(recipient: string[], amount: string) { + async multiTransfer( + recipient: string[], + amount: string, + options?: { + fee?: StdFee | "auto" | number; + memo?: string; + } + ) { const allAmount = new BigNumber(amount).multipliedBy(recipient.length); const tx = { typeUrl: "/cosmos.bank.v1beta1.MsgMultiSend", @@ -62,17 +50,18 @@ export default class KyveBaseMsg { }, }; - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx) - ); + return await this.getPendingSignedTx(tx, options); } - async getKyveBalance() { - const data = await this.nativeClient.getBalance( - this.account.address, - this.config.coinDenom - ); - return data.amount; + async txsAll( + txs: PendingSignedTx[], + options?: { + fee?: StdFee | "auto" | number; + memo?: string; + } + ) { + const txMessages = txs.map((tx) => tx.tx).flat(); + + return await this.getPendingSignedTx(txMessages, options); } } diff --git a/common/sdk/src/clients/rpc-client/kyve/bundles/v1beta1/bundles.ts b/common/sdk/src/clients/rpc-client/kyve/bundles/v1beta1/bundles.ts index 31e74c5e..9194cda8 100644 --- a/common/sdk/src/clients/rpc-client/kyve/bundles/v1beta1/bundles.ts +++ b/common/sdk/src/clients/rpc-client/kyve/bundles/v1beta1/bundles.ts @@ -1,30 +1,13 @@ import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { AccountData } from "@cosmjs/amino/build/signer"; -import { SigningStargateClient } from "@cosmjs/stargate"; import { MsgSubmitBundleProposal } from "@kyvejs/types/client/kyve/bundles/v1beta1/tx"; import { MsgVoteBundleProposal } from "@kyvejs/types/client/kyve/bundles/v1beta1/tx"; import { MsgClaimUploaderRole } from "@kyvejs/types/client/kyve/bundles/v1beta1/tx"; import { MsgSkipUploaderRole } from "@kyvejs/types/client/kyve/bundles/v1beta1/tx"; -import { SDKConfig } from "../../../../../constants"; import { withTypeUrl } from "../../../../../registry/tx.registry"; -import { signTx, TxPromise } from "../../../../../utils/helper"; - -export default class { - private nativeClient: SigningStargateClient; - public readonly account: AccountData; - public readonly config: SDKConfig; - - constructor( - client: SigningStargateClient, - account: AccountData, - config: SDKConfig - ) { - this.account = account; - this.config = config; - this.nativeClient = client; - } +import { KyveSigning } from "../../../signing"; +export default class KyveBundlesMethods extends KyveSigning { public async submitBundleProposal( value: Omit, options?: { @@ -36,10 +19,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async voteBundleProposal( @@ -53,10 +34,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async claimUploaderRole( @@ -70,11 +49,10 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } + public async skipUploaderRole( value: Omit, options?: { @@ -86,9 +64,7 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } } diff --git a/common/sdk/src/clients/rpc-client/kyve/delegation/v1beta1/delegation.ts b/common/sdk/src/clients/rpc-client/kyve/delegation/v1beta1/delegation.ts index 87fb7bd4..b62c819a 100644 --- a/common/sdk/src/clients/rpc-client/kyve/delegation/v1beta1/delegation.ts +++ b/common/sdk/src/clients/rpc-client/kyve/delegation/v1beta1/delegation.ts @@ -1,29 +1,12 @@ import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { AccountData } from "@cosmjs/amino/build/signer"; -import { SigningStargateClient } from "@cosmjs/stargate"; import { MsgDelegate } from "@kyvejs/types/client/kyve/delegation/v1beta1/tx"; import { MsgWithdrawRewards } from "@kyvejs/types/client/kyve/delegation/v1beta1/tx"; import { MsgUndelegate } from "@kyvejs/types/client/kyve/delegation/v1beta1/tx"; import { MsgRedelegate } from "@kyvejs/types/client/kyve/delegation/v1beta1/tx"; -import { SDKConfig } from "../../../../../constants"; import { withTypeUrl } from "../../../../../registry/tx.registry"; -import { signTx, TxPromise } from "../../../../../utils/helper"; -export default class { - private nativeClient: SigningStargateClient; - public readonly account: AccountData; - public readonly config: SDKConfig; - - constructor( - client: SigningStargateClient, - account: AccountData, - config: SDKConfig - ) { - this.account = account; - this.config = config; - this.nativeClient = client; - } - +import { KyveSigning } from "../../../signing"; +export default class KyveDelegationMethods extends KyveSigning { public async delegate( value: Omit, options?: { @@ -35,10 +18,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async withdrawRewards( value: Omit, @@ -51,10 +32,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async undelegate( @@ -68,10 +47,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async redelegate( @@ -85,9 +62,7 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } } diff --git a/common/sdk/src/clients/rpc-client/kyve/gov/v1/gov.ts b/common/sdk/src/clients/rpc-client/kyve/gov/v1/gov.ts index 1e742b5a..c558d536 100644 --- a/common/sdk/src/clients/rpc-client/kyve/gov/v1/gov.ts +++ b/common/sdk/src/clients/rpc-client/kyve/gov/v1/gov.ts @@ -1,6 +1,5 @@ import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { AccountData } from "@cosmjs/amino/build/signer"; -import { coins, SigningStargateClient } from "@cosmjs/stargate"; +import { coins } from "@cosmjs/stargate"; import { VoteOption } from "@kyvejs/types/client/cosmos/gov/v1/gov"; import { MsgUpdateParams as MsgUpdateParamsBundles } from "@kyvejs/types/client/kyve/bundles/v1beta1/tx"; import { MsgUpdateParams as MsgUpdateParamsDelegation } from "@kyvejs/types/client/kyve/delegation/v1beta1/tx"; @@ -9,31 +8,17 @@ import { MsgCancelRuntimeUpgrade, MsgCreatePool, MsgDisablePool, - MsgScheduleRuntimeUpgrade, MsgEnablePool, + MsgScheduleRuntimeUpgrade, MsgUpdatePool, } from "@kyvejs/types/client/kyve/pool/v1beta1/tx"; import { MsgUpdateParams as MsgUpdateParamsStakers } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; -import { GOV_AUTHORITY, SDKConfig } from "../../../../../constants"; +import { GOV_AUTHORITY } from "../../../../../constants"; import { encodeTxMsg } from "../../../../../registry/tx.registry"; -import { signTx, TxPromise } from "../../../../../utils/helper"; - -export default class KyveGovMsg { - protected nativeClient: SigningStargateClient; - public readonly account: AccountData; - public readonly config: SDKConfig; - - constructor( - client: SigningStargateClient, - account: AccountData, - config: SDKConfig - ) { - this.account = account; - this.config = config; - this.nativeClient = client; - } +import { KyveSigning } from "../../../signing"; +export default class KyveGovMsg extends KyveSigning { private createGovTx( content: { type_url: string; value: unknown }, deposit: string, @@ -68,10 +53,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async updatePool( @@ -92,10 +74,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async disablePool( @@ -116,10 +95,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async enablePool( @@ -140,10 +116,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async scheduleRuntimeUpgrade( @@ -164,10 +137,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async cancelRuntimeUpgrade( @@ -188,10 +158,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async updateParamsStakers( @@ -212,10 +179,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async updateParamsDelegation( @@ -236,10 +200,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async updateParamsBundles( @@ -260,10 +221,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async updateParamsGlobal( @@ -284,10 +242,7 @@ export default class KyveGovMsg { metadata ); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async vote( @@ -324,9 +279,6 @@ export default class KyveGovMsg { }, }; - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } } diff --git a/common/sdk/src/clients/rpc-client/kyve/pool/v1beta1/pool.ts b/common/sdk/src/clients/rpc-client/kyve/pool/v1beta1/pool.ts index 50f27c29..bb95f699 100644 --- a/common/sdk/src/clients/rpc-client/kyve/pool/v1beta1/pool.ts +++ b/common/sdk/src/clients/rpc-client/kyve/pool/v1beta1/pool.ts @@ -1,28 +1,11 @@ import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { AccountData } from "@cosmjs/amino/build/signer"; -import { SigningStargateClient } from "@cosmjs/stargate"; import { MsgDefundPool } from "@kyvejs/types/client/kyve/pool/v1beta1/tx"; import { MsgFundPool } from "@kyvejs/types/client/kyve/pool/v1beta1/tx"; -import { SDKConfig } from "../../../../../constants"; import { withTypeUrl } from "../../../../../registry/tx.registry"; -import { signTx, TxPromise } from "../../../../../utils/helper"; - -export default class { - private nativeClient: SigningStargateClient; - public readonly account: AccountData; - public readonly config: SDKConfig; - - constructor( - client: SigningStargateClient, - account: AccountData, - config: SDKConfig - ) { - this.account = account; - this.config = config; - this.nativeClient = client; - } +import { KyveSigning } from "../../../signing"; +export default class KyvePoolMethods extends KyveSigning { public async fundPool( value: Omit, options?: { @@ -35,10 +18,7 @@ export default class { creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } public async defundPool( @@ -52,9 +32,6 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + return await this.getPendingSignedTx(tx, options); } } diff --git a/common/sdk/src/clients/rpc-client/kyve/stakers/v1beta1/stakers.ts b/common/sdk/src/clients/rpc-client/kyve/stakers/v1beta1/stakers.ts index 3f7fec13..39e30468 100644 --- a/common/sdk/src/clients/rpc-client/kyve/stakers/v1beta1/stakers.ts +++ b/common/sdk/src/clients/rpc-client/kyve/stakers/v1beta1/stakers.ts @@ -1,33 +1,16 @@ import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { AccountData } from "@cosmjs/amino/build/signer"; -import { SigningStargateClient } from "@cosmjs/stargate"; -import { MsgCreateStaker as MsgStake } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; +import { MsgCreateStaker } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; import { MsgUpdateMetadata } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; import { MsgUpdateCommission } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; import { MsgJoinPool } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; import { MsgLeavePool } from "@kyvejs/types/client/kyve/stakers/v1beta1/tx"; -import { SDKConfig } from "../../../../../constants"; import { withTypeUrl } from "../../../../../registry/tx.registry"; -import { signTx, TxPromise } from "../../../../../utils/helper"; - -export default class { - private nativeClient: SigningStargateClient; - public readonly account: AccountData; - public readonly config: SDKConfig; - - constructor( - client: SigningStargateClient, - account: AccountData, - config: SDKConfig - ) { - this.account = account; - this.config = config; - this.nativeClient = client; - } +import { KyveSigning } from "../../../signing"; +export default class KyveStakersMethods extends KyveSigning { public async createStaker( - value: Omit, + value: Omit, options?: { fee?: StdFee | "auto" | number; memo?: string; @@ -37,10 +20,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async updateMetadata( @@ -54,10 +35,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async updateCommission( @@ -71,11 +50,10 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } + public async joinPool( value: Omit, options?: { @@ -87,10 +65,8 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } public async leavePool( @@ -104,9 +80,7 @@ export default class { ...value, creator: this.account.address, }); - return new TxPromise( - this.nativeClient, - await signTx(this.nativeClient, this.account.address, tx, options) - ); + + return await this.getPendingSignedTx(tx, options); } } diff --git a/common/sdk/src/clients/rpc-client/signing.ts b/common/sdk/src/clients/rpc-client/signing.ts new file mode 100644 index 00000000..e77c2974 --- /dev/null +++ b/common/sdk/src/clients/rpc-client/signing.ts @@ -0,0 +1,143 @@ +import { StdFee } from "@cosmjs/amino/build/signdoc"; +import { sha256 } from "@cosmjs/crypto"; +import { toHex } from "@cosmjs/encoding"; +import { AccountData, EncodeObject } from "@cosmjs/proto-signing"; +import { + calculateFee, + GasPrice, + SigningStargateClient, +} from "@cosmjs/stargate"; +import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; + +import { GAS_MULTIPLIER, IConfig } from "../../constants"; + +type SignedTx = { + tx: EncodeObject[]; + txRawBytes: Uint8Array; + fee: StdFee; +}; + +export class PendingSignedTx { + private nativeClient: SigningStargateClient; + private txBytes: Uint8Array; + readonly txHash: string; + readonly fee: StdFee; + readonly tx: EncodeObject[]; + + constructor(nativeClient: SigningStargateClient, tx: SignedTx) { + this.nativeClient = nativeClient; + this.txBytes = tx.txRawBytes; + this.fee = tx.fee; + this.tx = tx.tx; + this.txHash = toHex(sha256(this.txBytes)).toUpperCase(); + } + + async execute() { + return await this.nativeClient.broadcastTx(this.txBytes); + } +} + +export class KyveSigning { + public nativeClient: SigningStargateClient; + public readonly account: AccountData; + public readonly config: IConfig; + + constructor( + client: SigningStargateClient, + account: AccountData, + config: IConfig + ) { + this.nativeClient = client; + this.account = account; + this.config = config; + } + + async getPendingSignedTx( + tx: EncodeObject | EncodeObject[], + options?: { + fee?: StdFee | "auto" | number; + memo?: string; + } + ): Promise { + return new PendingSignedTx( + this.nativeClient, + await this.signTx(tx, options) + ); + } + + async signTx( + tx: EncodeObject | EncodeObject[], + options?: { + fee?: StdFee | "auto" | number; + memo?: string; + } + ): Promise { + const txArr = Array.isArray(tx) ? tx : [tx]; + + if (!options) { + const gasEstimation = await this.nativeClient.simulate( + this.account.address, + txArr, + undefined + ); + const multiplier = GAS_MULTIPLIER; + + const fee = calculateFee( + Math.round(gasEstimation * multiplier), + GasPrice.fromString(`${this.config.gasPrice}${this.config.coinDenom}`) + ); + + const txRaw = await this.nativeClient.sign( + this.account.address, + txArr, + fee, + "" + ); + + return { + txRawBytes: TxRaw.encode(txRaw).finish(), + fee, + tx: txArr, + }; + } else if (options.fee === "auto" || typeof options.fee === "number") { + const gasEstimation = await this.nativeClient.simulate( + this.account.address, + txArr, + options.memo + ); + const multiplier = + typeof options.fee === "number" ? options.fee : GAS_MULTIPLIER; + + const fee = calculateFee( + Math.round(gasEstimation * multiplier), + GasPrice.fromString(`${this.config.gasPrice}${this.config.coinDenom}`) + ); + + const txRaw = await this.nativeClient.sign( + this.account.address, + txArr, + fee, + options.memo || "" + ); + + return { + txRawBytes: TxRaw.encode(txRaw).finish(), + fee, + tx: txArr, + }; + } else { + const txRaw = await this.nativeClient.sign( + this.account.address, + txArr, + options.fee as StdFee, + options.memo || "" + ); + + return { + txRawBytes: TxRaw.encode(txRaw).finish(), + tx: txArr, + fee: options.fee as StdFee, + }; + } + } +} diff --git a/common/sdk/src/clients/rpc-client/web.client.ts b/common/sdk/src/clients/rpc-client/web.client.ts index 44cf5bd7..8a0a3377 100644 --- a/common/sdk/src/clients/rpc-client/web.client.ts +++ b/common/sdk/src/clients/rpc-client/web.client.ts @@ -1,7 +1,7 @@ import { AccountData, OfflineAminoSigner } from "@cosmjs/amino/build/signer"; import { SigningStargateClient } from "@cosmjs/stargate"; -import { SDKConfig } from "../../constants"; +import { IConfig } from "../../constants"; import KyveClient from "./client"; export default class KyveWebClient extends KyveClient { @@ -9,7 +9,7 @@ export default class KyveWebClient extends KyveClient { constructor( client: SigningStargateClient, account: AccountData, - config: SDKConfig, + config: IConfig, aminoSigner: OfflineAminoSigner | null, walletName: string ) { diff --git a/common/sdk/src/constants.ts b/common/sdk/src/constants.ts index 499bbb91..9d7c3af9 100644 --- a/common/sdk/src/constants.ts +++ b/common/sdk/src/constants.ts @@ -2,43 +2,89 @@ import { AddChainParams } from "@cosmostation/extension-client/types/message"; import { Bech32Address } from "@keplr-wallet/cosmos"; import { ChainInfo } from "@keplr-wallet/types"; -export const DEFAULT_COIN_DENOM = "tkyve"; -export const DEFAULT_COIN_DECIMALS = 9; - -export const COIN = "KYVE"; export const PREFIX = "kyve"; export const GOV_AUTHORITY = "kyve10d07y265gmmuvt4z0w9aw880jnsr700jdv7nah"; +export const GAS_MULTIPLIER = 1.3; -export const SUPPORTED_WALLETS = { - KEPLER: "KEPLER", - COSMOSTATION: "COSMOSTATION", -} as const; - -export type SDKConfig = { +export type IConfig = { chainId: string; chainName: string; rpc: string; rest: string; + coin: string; coinDenom: string; coinDecimals: number; + gasPrice: number; }; -export type SDKConfigInput = { - chainId: string; - chainName: string; - rpc: string; - rest: string; - coinDenom?: string; - coinDecimals?: number; +// chains are always identified by their chain id +export const SUPPORTED_CHAIN_CONFIGS = { + "kyve-local": { + chainId: "kyve-local", + chainName: "KYVE Local", + rpc: "http://0.0.0.0:26657", + rest: "http://0.0.0.0:1317", + coin: "KYVE", + coinDenom: "tkyve", + coinDecimals: 9, + gasPrice: 1, + }, + "kyve-alpha": { + chainId: "kyve-alpha", + chainName: "KYVE Alpha", + rpc: "https://rpc.alpha.kyve.network", + rest: "https://api.alpha.kyve.network", + coin: "KYVE", + coinDenom: "tkyve", + coinDecimals: 9, + gasPrice: 1, + }, + "kyve-beta": { + chainId: "kyve-beta", + chainName: "KYVE Beta", + rpc: "https://rpc.beta.kyve.network", + rest: "https://api.beta.kyve.network", + coin: "KYVE", + coinDenom: "tkyve", + coinDecimals: 9, + gasPrice: 1, + }, + korellia: { + chainId: "korellia", + chainName: "KYVE Korellia", + rpc: "https://rpc.kyve.network", + rest: "https://api.kyve.network", + coin: "KYVE", + coinDenom: "tkyve", + coinDecimals: 9, + gasPrice: 1, + }, + "kaon-1": { + chainId: "kaon-1", + chainName: "KYVE Kaon", + rpc: "https://rpc-eu-1.kaon.kyve.network/", + rest: "https://api-eu-1.kaon.kyve.network", + coin: "KYVE", + coinDenom: "tkyve", + coinDecimals: 6, + gasPrice: 0.02, + }, }; +export type SupportedChains = keyof typeof SUPPORTED_CHAIN_CONFIGS; + +export const SUPPORTED_WALLETS = { + KEPLER: "KEPLER", + COSMOSTATION: "COSMOSTATION", +} as const; + export const KYVE_KEPLR_CONFIG: ChainInfo = { rpc: "", rest: "", chainId: "", chainName: "", stakeCurrency: { - coinDenom: "KYVE", + coinDenom: "", coinMinimalDenom: "", coinDecimals: 0, }, @@ -57,13 +103,13 @@ export const KYVE_COSMOSTATION_CONFIG: AddChainParams = { restURL: "", chainName: "", baseDenom: "", - displayDenom: "KYVE", + displayDenom: "", addressPrefix: PREFIX, coinType: "118", decimals: 0, gasRate: { - tiny: "1.6", - low: "2", - average: "0.8", + tiny: "1", + low: "1.5", + average: "3", }, }; diff --git a/common/sdk/src/sdk.ts b/common/sdk/src/sdk.ts index 6621122e..5f68e973 100644 --- a/common/sdk/src/sdk.ts +++ b/common/sdk/src/sdk.ts @@ -8,24 +8,21 @@ import { DirectSecp256k1HdWallet, DirectSecp256k1Wallet, } from "@cosmjs/proto-signing"; -import { - RequestAccountResponse, - SignOptions, -} from "@cosmostation/extension-client/types/message"; +import { RequestAccountResponse } from "@cosmostation/extension-client/types/message"; import { verifyADR36Amino } from "@keplr-wallet/cosmos"; + import { getSigningKyveClient } from "./clients/full-client"; import { createKyveLCDClient } from "./clients/lcd-client/client"; import KyveClient from "./clients/rpc-client/client"; import KyveWebClient from "./clients/rpc-client/web.client"; import { + IConfig, KYVE_COSMOSTATION_CONFIG, KYVE_KEPLR_CONFIG, PREFIX, + SUPPORTED_CHAIN_CONFIGS, SUPPORTED_WALLETS, - SDKConfig, - DEFAULT_COIN_DENOM, - DEFAULT_COIN_DECIMALS, - SDKConfigInput, + SupportedChains, } from "./constants"; import { cosmostationMethods, @@ -35,23 +32,44 @@ import { KeplrAminoSigner } from "./utils/keplr-helper"; /** Class representing a KyveSDK. */ export class KyveSDK { - public readonly config: SDKConfig; - private walletSupports: Set; + public readonly config: IConfig; + private walletSupports = new Set(); /** * Create sdk instance. - * @param config - The config type, e.g mainnet, testnet, etc + * @param chainId - The chainId of the chain the sdk should connect to + * @param options - The default config of the sdk can be overwritten here */ - constructor(config: SDKConfigInput) { - this.walletSupports = new Set(); - this.config = { - chainId: config.chainId, - chainName: config.chainName, - rpc: config.rpc, - rest: config.rest, - coinDenom: config.coinDenom || DEFAULT_COIN_DENOM, - coinDecimals: config.coinDecimals || DEFAULT_COIN_DECIMALS, - }; + constructor( + chainId: SupportedChains, + options?: { + chainName?: string; + rpc?: string; + rest?: string; + gasPrice?: number; + } + ) { + if (!SUPPORTED_CHAIN_CONFIGS[chainId]) { + throw new Error(`ChainId "${chainId}" not supported.`); + } + + this.config = { ...SUPPORTED_CHAIN_CONFIGS[chainId] }; + + if (options?.chainName) { + this.config = { ...this.config, chainName: options.chainName }; + } + + if (options?.rpc) { + this.config = { ...this.config, rpc: options.rpc }; + } + + if (options?.rest) { + this.config = { ...this.config, rest: options.rest }; + } + + if (options?.gasPrice) { + this.config = { ...this.config, gasPrice: options.gasPrice }; + } } /** @@ -95,7 +113,7 @@ export class KyveSDK { if (!window.keplr) throw new Error("Please install Keplr."); const KYVE_COIN = { - coinDenom: "KYVE", + coinDenom: this.config.coin, coinMinimalDenom: this.config.coinDenom, coinDecimals: this.config.coinDecimals, }; @@ -112,20 +130,17 @@ export class KyveSDK { { ...KYVE_COIN, gasPriceStep: { - low: 2, - average: 2.5, - high: 10, + low: this.config.gasPrice, + average: this.config.gasPrice * 1.5, + high: this.config.gasPrice * 3, }, }, ], }); + await window.keplr.enable(this.config.chainId); - window.keplr.defaultOptions = { - sign: { - preferNoSetFee: true, - }, - }; - const signer = window.keplr.getOfflineSigner(this.config.chainId); + + const signer = await window.keplr.getOfflineSignerAuto(this.config.chainId); const walletName = (await window.keplr.getKey(this.config.chainId)).name; const keplr = window.keplr; const keplrAminoSigner = new KeplrAminoSigner(keplr, this.config); @@ -143,7 +158,7 @@ export class KyveSDK { * Crate a client from Cosmostaion wallet if installed * @return Promise */ - async fromCosmostation(config?: SignOptions): Promise { + async fromCosmostation(): Promise { if (typeof window === "undefined") throw new Error("Unsupported."); if (!window.cosmostation) throw new Error("Please install cosmostation."); @@ -160,8 +175,14 @@ export class KyveSDK { restURL: this.config.rest, chainId: this.config.chainId, chainName: this.config.chainName, + displayDenom: this.config.coin, baseDenom: this.config.coinDenom, - decimals: this.config.coinDecimals || DEFAULT_COIN_DECIMALS, + decimals: this.config.coinDecimals, + gasRate: { + tiny: this.config.gasPrice.toString(), + low: (this.config.gasPrice * 1.5).toString(), + average: (this.config.gasPrice * 3).toString(), + }, }); cosmostationAccount = await cosmostationMethods.requestAccount( this.config.chainName @@ -171,7 +192,10 @@ export class KyveSDK { const cosmostationSigner = new CosmostationSigner( cosmostationAccount, this.config, - config ? config : {} + { + memo: true, + fee: true, + } ); const client = await getSigningKyveClient( diff --git a/common/sdk/src/utils/cosmostation-helper.ts b/common/sdk/src/utils/cosmostation-helper.ts index 435ff5b7..72984b8f 100644 --- a/common/sdk/src/utils/cosmostation-helper.ts +++ b/common/sdk/src/utils/cosmostation-helper.ts @@ -11,7 +11,8 @@ import { SignOptions, } from "@cosmostation/extension-client/types/message"; import { SignDoc } from "cosmjs-types/cosmos/tx/v1beta1/tx"; -import { SDKConfig } from "../constants"; + +import { IConfig } from "../constants"; export const cosmostationMethods = { getSupportedChains() { @@ -39,7 +40,6 @@ export const cosmostationMethods = { doc, isEditMemo: !!options?.memo, isEditFee: !!options?.fee, - gasRate: options?.gasRate, }, }); }, @@ -58,13 +58,13 @@ export const cosmostationMethods = { }; export class CosmostationSigner implements OfflineDirectSigner { - private config: SDKConfig; + private config: IConfig; private cosmostationAccount: RequestAccountResponse; private cosmostationOption: SignOptions | undefined; constructor( cosmostationAccount: RequestAccountResponse, - config: SDKConfig, + config: IConfig, cosmostationOption?: SignOptions ) { this.config = config; diff --git a/common/sdk/src/utils/helper.ts b/common/sdk/src/utils/helper.ts deleted file mode 100644 index bfd11fe2..00000000 --- a/common/sdk/src/utils/helper.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { EncodeObject } from "@cosmjs/proto-signing"; -import { StdFee } from "@cosmjs/amino/build/signdoc"; -import { sha256 } from "@cosmjs/crypto"; -import { toHex } from "@cosmjs/encoding"; -import { coins, SigningStargateClient } from "@cosmjs/stargate"; -import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; - -type signTxResponseType = { - tx: EncodeObject[]; - txRawBytes: Uint8Array; - fee: StdFee; -}; -export class TxPromise { - private nativeClient: SigningStargateClient; - private txBytes: Uint8Array; - readonly txHash: string; - readonly fee: StdFee; - readonly tx: EncodeObject[]; - constructor(nativeClient: SigningStargateClient, tx: signTxResponseType) { - this.nativeClient = nativeClient; - this.txBytes = tx.txRawBytes; - this.fee = tx.fee; - this.tx = tx.tx; - this.txHash = toHex(sha256(this.txBytes)).toUpperCase(); - } - async execute() { - return await this.nativeClient.broadcastTx(this.txBytes); - } -} -async function calcFee(gasEstimation: number, fee: "auto" | number) { - const multiplier = typeof fee === "number" ? fee : 1.5; - // calculateFee(Math.round(gasEstimation * multiplier), "5000000tkyve"); - return { - amount: coins("5000000", "tkyve"), - gas: Math.floor(gasEstimation * multiplier).toString(), - }; -} - -export async function signTx( - nativeClient: SigningStargateClient, - address: string, - tx: EncodeObject | EncodeObject[], - options?: { - fee?: StdFee | "auto" | number; - memo?: string; - } -): Promise { - const txArr = Array.isArray(tx) ? tx : [tx]; - if (!options || options.fee == undefined) { - const gasEstimation = await nativeClient.simulate( - address, - txArr, - undefined - ); - const fee = await calcFee(gasEstimation, "auto"); - const txRaw = await nativeClient.sign( - address, - txArr, - fee, - options?.memo ? options?.memo : "" - ); - return { - txRawBytes: TxRaw.encode(txRaw).finish(), - fee, - tx: txArr, - }; - } else if (options.fee === "auto" || typeof options.fee == "number") { - const gasEstimation = await nativeClient.simulate( - address, - txArr, - options?.memo - ); - const fee = await calcFee(gasEstimation, options.fee); - const txRaw = await nativeClient.sign( - address, - txArr, - fee, - options?.memo ? options?.memo : "" - ); - return { - txRawBytes: TxRaw.encode(txRaw).finish(), - fee, - tx: txArr, - }; - } else { - const txRaw = await nativeClient.sign( - address, - txArr, - options.fee, - options?.memo ? options?.memo : "" - ); - return { - tx: txArr, - txRawBytes: TxRaw.encode(txRaw).finish(), - fee: options.fee, - }; - } -} diff --git a/common/sdk/src/utils/keplr-helper.ts b/common/sdk/src/utils/keplr-helper.ts index 8a89d636..cc11d7cc 100644 --- a/common/sdk/src/utils/keplr-helper.ts +++ b/common/sdk/src/utils/keplr-helper.ts @@ -5,12 +5,13 @@ import { OfflineAminoSigner, } from "@cosmjs/amino/build/signer"; import { Keplr } from "@keplr-wallet/types"; -import { SDKConfig } from "../constants"; + +import { IConfig } from "../constants"; export class KeplrAminoSigner implements OfflineAminoSigner { private keplr: Keplr; - private config: SDKConfig; - constructor(keplr: Keplr, config: SDKConfig) { + private config: IConfig; + constructor(keplr: Keplr, config: IConfig) { this.keplr = keplr; this.config = config; } diff --git a/tools/kysor/src/commands/init.ts b/tools/kysor/src/commands/init.ts index 1d548c89..54764393 100644 --- a/tools/kysor/src/commands/init.ts +++ b/tools/kysor/src/commands/init.ts @@ -3,6 +3,7 @@ import KyveSDK from "@kyvejs/sdk"; import { Command } from "commander"; import fs from "fs"; import path from "path"; + import { HOME } from "../utils/constants"; const init = new Command("init").description("Init KYSOR"); @@ -18,14 +19,8 @@ init "Comma separated list of rest endpoints. If the first fails the next endpoint will be used as fallback. " ) .option( - "--denom ", - "The denom of the base currency [default = tkyve]", - "tkyve" - ) - .option( - "--decimals ", - "The decimals of the base currency [default = 9]", - "9" + "--gas-price ", + "The gas price the node should use to calculate transaction fees" ) .option( "-d, --auto-download-binaries", @@ -68,11 +63,10 @@ init } try { - new KyveSDK({ - chainId: options.chainId, + new KyveSDK(options.chainId, { rpc: rpc[0], rest: rest[0], - chainName: `KYVE - ${options.chainId}`, + gasPrice: options.gasPrice, }); } catch (err) { console.log( @@ -86,8 +80,7 @@ init chainId: options.chainId, rpc: options.rpc, rest: options.rest, - denom: options.denom, - decimals: parseInt(options.decimals), + gasPrice: options.gasPrice, autoDownloadBinaries: options.autoDownloadBinaries, }; diff --git a/tools/kysor/src/commands/valaccounts.ts b/tools/kysor/src/commands/valaccounts.ts index 9734ef58..6920db4c 100644 --- a/tools/kysor/src/commands/valaccounts.ts +++ b/tools/kysor/src/commands/valaccounts.ts @@ -7,12 +7,7 @@ import path from "path"; import prompts from "prompts"; import { IValaccountConfig } from "../types/interfaces"; -import { - DEFAULT_COIN_DECIMALS, - DEFAULT_COIN_DENOM, - FILE_ACCESS, - HOME, -} from "../utils/constants"; +import { FILE_ACCESS, HOME } from "../utils/constants"; const valaccounts = new Command("valaccounts").description( "Create and delete valaccounts" @@ -193,19 +188,15 @@ valaccounts ) ) as any; - const client = await new KyveSDK({ - chainId: config.chainId, - chainName: config.chainId.toUpperCase(), + const client = await new KyveSDK(config.chainId, { rpc: config.rpc.split(",")[0], rest: config.rest.split(",")[0], + gasPrice: config.gasPrice, }).fromMnemonic(valaccount.valaccount); - const balance = await client.nativeClient.getBalance( - client.account.address, - config.denom || DEFAULT_COIN_DENOM - ); + const balance = await client.getKyveBalance(); - console.log(`${balance.amount} ${config.denom || DEFAULT_COIN_DENOM}`); + console.log(`${balance} ${client.config.coinDenom}`); } catch (err) { console.log(`ERROR: Could not show balance of valaccount: ${err}`); } @@ -243,11 +234,10 @@ valaccounts ) ) as any; - const client = await new KyveSDK({ - chainId: config.chainId, - chainName: config.chainId.toUpperCase(), + const client = await new KyveSDK(config.chainId, { rpc: config.rpc.split(",")[0], rest: config.rest.split(",")[0], + gasPrice: config.gasPrice, }).fromMnemonic(valaccount.valaccount); const tx = await client.kyve.base.v1beta1.transfer( @@ -260,14 +250,14 @@ valaccounts type: "confirm", name: "value", message: `Confirm transfer of ${options.amount} ${ - options.denom || DEFAULT_COIN_DENOM + client.config.coinDenom } (${new BigNumber(options.amount) .dividedBy( - new BigNumber(10).exponentiatedBy( - options.denom || DEFAULT_COIN_DECIMALS - ) + new BigNumber(10).exponentiatedBy(client.config.coinDecimals) ) - .toString(10)} $KYVE) to recipient ${options.recipient}`, + .toString(10)} ${client.config.coin}) to recipient ${ + options.recipient + }`, }, { onCancel: () => { @@ -283,9 +273,7 @@ valaccounts if (receipt.code === 0) { console.log( - `Successfully transferred ${options.amount} ${ - config.denom || DEFAULT_COIN_DENOM - } to recipient ${options.recipient}` + `Successfully transferred ${options.amount} ${client.config.coinDenom} to recipient ${options.recipient}` ); } else { `Transfer failed with receipt ${JSON.stringify(receipt)}`; diff --git a/tools/kysor/src/index.ts b/tools/kysor/src/index.ts index 03ab74ba..10aae32b 100644 --- a/tools/kysor/src/index.ts +++ b/tools/kysor/src/index.ts @@ -1,9 +1,9 @@ import { Command } from "commander"; -import version from "./commands/version"; import init from "./commands/init"; import start from "./commands/start"; import valaccounts from "./commands/valaccounts"; +import version from "./commands/version"; const main = async () => { // define main program diff --git a/tools/kysor/src/kysor.ts b/tools/kysor/src/kysor.ts index eeb4d36f..9b62aa0b 100644 --- a/tools/kysor/src/kysor.ts +++ b/tools/kysor/src/kysor.ts @@ -118,11 +118,10 @@ export const run = async (options: any) => { // create lcd clients const lcd = rpc.map((_, i) => { try { - return new KyveSDK({ - chainId: config.chainId, + return new KyveSDK(config.chainId, { rpc: rpc[i], rest: rest[i], - chainName: `KYVE - ${config.chainId}`, + gasPrice: config.gasPrice, }).createLCDClient(); } catch (err) { logger.error( diff --git a/tools/kysor/src/types/interfaces.ts b/tools/kysor/src/types/interfaces.ts index 50e3c2fb..6525b24f 100644 --- a/tools/kysor/src/types/interfaces.ts +++ b/tools/kysor/src/types/interfaces.ts @@ -1,7 +1,10 @@ +import { SupportedChains } from "@kyvejs/sdk/dist/constants"; + export interface IConfig { - chainId: string; + chainId: SupportedChains; rpc: string; rest: string; + gasPrice: number; autoDownloadBinaries: boolean; } diff --git a/tools/kysor/src/utils/constants.ts b/tools/kysor/src/utils/constants.ts index cf526fd6..8c1a0bd4 100644 --- a/tools/kysor/src/utils/constants.ts +++ b/tools/kysor/src/utils/constants.ts @@ -1,10 +1,7 @@ -import path from "path"; import os from "os"; +import path from "path"; export const HOME = path.join(process.env.HOME!, ".kysor"); export const PLATFORM = os.platform() === "darwin" ? "macos" : os.platform(); export const ARCH = os.arch(); export const FILE_ACCESS = "600"; - -export const DEFAULT_COIN_DENOM = "tkyve"; -export const DEFAULT_COIN_DECIMALS = 9; diff --git a/tools/kysor/src/utils/index.ts b/tools/kysor/src/utils/index.ts index 65cedcc7..11f58bfa 100644 --- a/tools/kysor/src/utils/index.ts +++ b/tools/kysor/src/utils/index.ts @@ -3,6 +3,7 @@ import crypto from "crypto"; import fs from "fs"; import path from "path"; import { ILogObject, Logger } from "tslog"; + import { HOME } from "./constants"; export const setupLogger = () => {