diff --git a/CHANGELOG.md b/CHANGELOG.md index 7345a7e5..98d101cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ and this project adheres to `protected`. - @cosmjs/cosmwasm-stargate: Add `SigningCosmWasmClient.offline` static method for constructing offline clients without a Tendermint client. +- @cosmjs/stargate: Add `SigningStargateClient.sendIbcTokens` method. ### Changed diff --git a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts index 79d2844c..422b8645 100644 --- a/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm-stargate/src/signingcosmwasmclient.spec.ts @@ -95,6 +95,10 @@ describe("SigningCosmWasmClient", () => { amount: coins(502400, "utest"), gas: "160000", }, + transfer: { + amount: coins(502400, "utest"), + gas: "160000", + }, undelegate: { amount: coins(502400, "utest"), gas: "160000", @@ -146,6 +150,10 @@ describe("SigningCosmWasmClient", () => { amount: coins(4000, "ucosm"), gas: "160000", }, + transfer: { + amount: coins(4000, "ucosm"), + gas: "160000", + }, undelegate: { amount: coins(4000, "ucosm"), gas: "160000", @@ -198,6 +206,10 @@ describe("SigningCosmWasmClient", () => { amount: coins(502400, "utest"), gas: "160000", }, + transfer: { + amount: coins(502400, "utest"), + gas: "160000", + }, undelegate: { amount: coins(502400, "utest"), gas: "160000", diff --git a/packages/stargate/src/signingstargateclient.spec.ts b/packages/stargate/src/signingstargateclient.spec.ts index 4d79a1b6..45f42772 100644 --- a/packages/stargate/src/signingstargateclient.spec.ts +++ b/packages/stargate/src/signingstargateclient.spec.ts @@ -49,6 +49,15 @@ describe("SigningStargateClient", () => { ], gas: "160000", }, + transfer: { + amount: [ + { + amount: "4000", + denom: "ucosm", + }, + ], + gas: "160000", + }, undelegate: { amount: [ { @@ -107,6 +116,15 @@ describe("SigningStargateClient", () => { ], gas: "160000", }, + transfer: { + amount: [ + { + amount: "502400", + denom: "utest", + }, + ], + gas: "160000", + }, undelegate: { amount: [ { @@ -157,6 +175,15 @@ describe("SigningStargateClient", () => { ], gas: "120000", }, + transfer: { + amount: [ + { + amount: "4000", + denom: "ucosm", + }, + ], + gas: "160000", + }, undelegate: { amount: [ { @@ -207,6 +234,15 @@ describe("SigningStargateClient", () => { ], gas: "160000", }, + transfer: { + amount: [ + { + amount: "502400", + denom: "utest", + }, + ], + gas: "160000", + }, undelegate: { amount: [ { @@ -253,7 +289,6 @@ describe("SigningStargateClient", () => { // got tokens const after = await client.getBalance(beneficiaryAddress, "ucosm"); - assert(after); expect(after).toEqual(transferAmount[0]); }); @@ -280,7 +315,6 @@ describe("SigningStargateClient", () => { // got tokens const after = await client.getBalance(beneficiaryAddress, "ucosm"); - assert(after); expect(after).toEqual(transferAmount[0]); }); }); @@ -465,8 +499,6 @@ describe("SigningStargateClient", () => { assert(customDelegatorAddress, "missing customDelegatorAddress"); assert(customValidatorAddress, "missing validatorAddress"); assert(customAmount, "missing amount"); - assert(customAmount.amount, "missing amount.amount"); - assert(customAmount.denom, "missing amount.denom"); return { delegator_address: customDelegatorAddress, validator_address: customValidatorAddress, @@ -733,8 +765,6 @@ describe("SigningStargateClient", () => { assert(customDelegatorAddress, "missing customDelegatorAddress"); assert(customValidatorAddress, "missing validatorAddress"); assert(customAmount, "missing amount"); - assert(customAmount.amount, "missing amount.amount"); - assert(customAmount.denom, "missing amount.denom"); return { delegator_address: customDelegatorAddress, validator_address: customValidatorAddress, diff --git a/packages/stargate/src/signingstargateclient.ts b/packages/stargate/src/signingstargateclient.ts index 43f6beb7..c1215de6 100644 --- a/packages/stargate/src/signingstargateclient.ts +++ b/packages/stargate/src/signingstargateclient.ts @@ -13,6 +13,7 @@ import { } from "@cosmjs/proto-signing"; import { Tendermint34Client } from "@cosmjs/tendermint-rpc"; import { assert } from "@cosmjs/utils"; +import Long from "long"; import { AminoTypes } from "./aminotypes"; import { MsgMultiSend } from "./codec/cosmos/bank/v1beta1/tx"; @@ -45,6 +46,7 @@ import { MsgTimeout, MsgTimeoutOnClose, } from "./codec/ibc/core/channel/v1/tx"; +import { Height } from "./codec/ibc/core/client/v1/client"; import { MsgCreateClient, MsgSubmitMisbehaviour, @@ -68,6 +70,7 @@ import { BroadcastTxResponse, StargateClient } from "./stargateclient"; export interface CosmosFeeTable extends FeeTable { readonly send: StdFee; readonly delegate: StdFee; + readonly transfer: StdFee; readonly undelegate: StdFee; readonly withdraw: StdFee; } @@ -76,6 +79,7 @@ export const defaultGasPrice = GasPrice.fromString("0.025ucosm"); export const defaultGasLimits: GasLimits = { send: 80_000, delegate: 160_000, + transfer: 160_000, undelegate: 160_000, withdraw: 160_000, }; @@ -216,7 +220,11 @@ export class SigningStargateClient extends StargateClient { ): Promise { const delegateMsg = { typeUrl: "/cosmos.staking.v1beta1.MsgDelegate", - value: MsgDelegate.fromPartial({ delegatorAddress: delegatorAddress, validatorAddress, amount }), + value: MsgDelegate.fromPartial({ + delegatorAddress: delegatorAddress, + validatorAddress: validatorAddress, + amount: amount, + }), }; return this.signAndBroadcast(delegatorAddress, [delegateMsg], this.fees.delegate, memo); } @@ -229,7 +237,11 @@ export class SigningStargateClient extends StargateClient { ): Promise { const undelegateMsg = { typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate", - value: MsgUndelegate.fromPartial({ delegatorAddress: delegatorAddress, validatorAddress, amount }), + value: MsgUndelegate.fromPartial({ + delegatorAddress: delegatorAddress, + validatorAddress: validatorAddress, + amount: amount, + }), }; return this.signAndBroadcast(delegatorAddress, [undelegateMsg], this.fees.undelegate, memo); } @@ -241,11 +253,43 @@ export class SigningStargateClient extends StargateClient { ): Promise { const withdrawMsg = { typeUrl: "/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward", - value: MsgWithdrawDelegatorReward.fromPartial({ delegatorAddress: delegatorAddress, validatorAddress }), + value: MsgWithdrawDelegatorReward.fromPartial({ + delegatorAddress: delegatorAddress, + validatorAddress: validatorAddress, + }), }; return this.signAndBroadcast(delegatorAddress, [withdrawMsg], this.fees.withdraw, memo); } + public async sendIbcTokens( + senderAddress: string, + recipientAddress: string, + transferAmount: Coin, + sourcePort: string, + sourceChannel: string, + timeoutHeight: Height | undefined, + /** timeout in seconds */ + timeoutTimestamp: number | undefined, + memo = "", + ): Promise { + const timeoutTimestampNanoseconds = timeoutTimestamp + ? Long.fromNumber(timeoutTimestamp).multiply(1_000_000_000) + : undefined; + const transferMsg = { + typeUrl: "/ibc.applications.transfer.v1.MsgTransfer", + value: MsgTransfer.fromPartial({ + sourcePort: sourcePort, + sourceChannel: sourceChannel, + sender: senderAddress, + receiver: recipientAddress, + token: transferAmount, + timeoutHeight: timeoutHeight, + timeoutTimestamp: timeoutTimestampNanoseconds, + }), + }; + return this.signAndBroadcast(senderAddress, [transferMsg], this.fees.transfer, memo); + } + public async signAndBroadcast( signerAddress: string, messages: readonly EncodeObject[], @@ -280,7 +324,11 @@ export class SigningStargateClient extends StargateClient { } else { const { accountNumber, sequence } = await this.getSequence(signerAddress); const chainId = await this.getChainId(); - signerData = { accountNumber, sequence, chainId }; + signerData = { + accountNumber: accountNumber, + sequence: sequence, + chainId: chainId, + }; } return isOfflineDirectSigner(this.signer)