Merge pull request #721 from cosmos/657-independent-stargate

Reorganise logs/coins for Launchpad/Stargate
This commit is contained in:
Will Clark 2021-03-23 17:09:57 +01:00 committed by GitHub
commit e95acc81eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 294 additions and 56 deletions

View File

@ -22,6 +22,10 @@ and this project adheres to
connection tx, as well as Tendermint.
- @cosmjs/stargate: Add support for IBC message types in
`SigningStargateClient`.
- @cosmjs/stargate: Added new `logs` export with all the functionality from
@cosmjs/launchpad.
- @cosmjs/stargate: Added new `Coin`, `coin`, `coins` and `parseCoins` exports
which have the same functionality as already existed in @cosmjs/launchpad.
- @cosmjs/amino: New package created that contains the shared amino signing
functionality for @cosmjs/launchpad and @cosmjs/stargate.
- @cosmjs/amino: Split public key interfaces into `Pubkey`, `SinglePubkey` and
@ -31,6 +35,9 @@ and this project adheres to
single secp256k1 pubkey.
- @cosmjs/utils: The new `arrayContentStartsWith` works similar to
`arrayContentEquals` but only checks the start of an array.
- @cosmjs/proto-signing: Added new `Coin`, `coin`, `coins` and `parseCoins`
exports which have the same functionality as already existed in
@cosmjs/launchpad.
### Changed
@ -52,6 +59,7 @@ and this project adheres to
- @cosmjs/launchpad: `rawSecp256k1PubkeyToAddress` was removed. Instead use
`Bech32.encode(prefix, rawSecp256k1PubkeyToRawAddress(pubkeyRaw))` with
`rawSecp256k1PubkeyToRawAddress` from @cosmjs/amino.
- @cosmjs/stargate: `parseRawLog` is now nested under the `logs` export.
### Deprecated

View File

@ -42,8 +42,8 @@
"dependencies": {
"@cosmjs/crypto": "^0.25.0-alpha.0",
"@cosmjs/encoding": "^0.25.0-alpha.0",
"@cosmjs/math": "^0.25.0-alpha.0",
"@cosmjs/utils": "^0.25.0-alpha.0"
},
"devDependencies": {
}
"devDependencies": {}
}

View File

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { fromBase64, toUtf8 } from "@cosmjs/encoding";
import { coins } from "@cosmjs/launchpad";
import { AminoTypes } from "@cosmjs/stargate";
import { AminoTypes, coins } from "@cosmjs/stargate";
import Long from "long";
import {

View File

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { fromBase64, fromUtf8, toBase64, toUtf8 } from "@cosmjs/encoding";
import { Coin } from "@cosmjs/launchpad";
import { AminoConverter, coinFromProto } from "@cosmjs/stargate";
import { AminoConverter, Coin, coinFromProto } from "@cosmjs/stargate";
import { assertDefinedAndNotNull } from "@cosmjs/utils";
import Long from "long";

View File

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { fromBase64, toBase64 } from "@cosmjs/encoding";
import { Coin, coins } from "@cosmjs/launchpad";
import {
DirectSecp256k1HdWallet,
encodePubkey,
@ -8,7 +7,13 @@ import {
makeSignDoc,
Registry,
} from "@cosmjs/proto-signing";
import { BroadcastTxResponse, isBroadcastTxFailure, isBroadcastTxSuccess } from "@cosmjs/stargate";
import {
BroadcastTxResponse,
Coin,
coins,
isBroadcastTxFailure,
isBroadcastTxSuccess,
} from "@cosmjs/stargate";
import { Tx, TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
import { assert, sleep } from "@cosmjs/utils";

View File

@ -2,7 +2,7 @@
import { Code } from "@cosmjs/cosmwasm-launchpad";
import { sha256 } from "@cosmjs/crypto";
import { Bech32, fromAscii, fromBase64, fromHex, toAscii, toBase64 } from "@cosmjs/encoding";
import { coins, logs, StdFee } from "@cosmjs/launchpad";
import { StdFee } from "@cosmjs/launchpad";
import { Int53 } from "@cosmjs/math";
import {
DirectSecp256k1HdWallet,
@ -11,7 +11,7 @@ import {
makeSignDoc,
Registry,
} from "@cosmjs/proto-signing";
import { assertIsBroadcastTxSuccess, parseRawLog } from "@cosmjs/stargate";
import { assertIsBroadcastTxSuccess, coins, logs } from "@cosmjs/stargate";
import { TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
import { assert, sleep } from "@cosmjs/utils";
import { ReadonlyDate } from "readonly-date";
@ -210,7 +210,7 @@ describe("CosmWasmClient", () => {
const signedTx = Uint8Array.from(TxRaw.encode(txRaw).finish());
const result = await client.broadcastTx(signedTx);
assertIsBroadcastTxSuccess(result);
const amountAttr = logs.findAttribute(parseRawLog(result.rawLog), "transfer", "amount");
const amountAttr = logs.findAttribute(logs.parseRawLog(result.rawLog), "transfer", "amount");
expect(amountAttr.value).toEqual("1234567ucosm");
expect(result.transactionHash).toMatch(/^[0-9A-F]{64}$/);
});

View File

@ -9,7 +9,6 @@ import {
import { fromAscii, toHex } from "@cosmjs/encoding";
import {
Block,
Coin,
isSearchByHeightQuery,
isSearchBySentFromOrToQuery,
isSearchByTagsQuery,
@ -23,6 +22,7 @@ import {
AuthExtension,
BankExtension,
BroadcastTxResponse,
Coin,
coinFromProto,
IndexedTx,
QueryClient,

View File

@ -1,12 +1,15 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { sha256 } from "@cosmjs/crypto";
import { fromAscii, fromHex, toAscii, toHex } from "@cosmjs/encoding";
import { Coin, coin, coins, logs, StdFee } from "@cosmjs/launchpad";
import { StdFee } from "@cosmjs/launchpad";
import { DirectSecp256k1HdWallet, OfflineDirectSigner, Registry } from "@cosmjs/proto-signing";
import {
assertIsBroadcastTxSuccess,
BroadcastTxResponse,
parseRawLog,
Coin,
coin,
coins,
logs,
SigningStargateClient,
} from "@cosmjs/stargate";
import { assert, assertDefined } from "@cosmjs/utils";
@ -392,7 +395,7 @@ describe("WasmExtension", () => {
{
const result = await uploadContract(wallet, getHackatom());
assertIsBroadcastTxSuccess(result);
const parsedLogs = logs.parseLogs(parseRawLog(result.rawLog));
const parsedLogs = logs.parseLogs(logs.parseRawLog(result.rawLog));
const codeIdAttr = logs.findAttribute(parsedLogs, "message", "code_id");
codeId = Number.parseInt(codeIdAttr.value, 10);
expect(codeId).toBeGreaterThanOrEqual(1);
@ -412,7 +415,7 @@ describe("WasmExtension", () => {
{
const result = await instantiateContract(wallet, codeId, beneficiaryAddress, transferAmount);
assertIsBroadcastTxSuccess(result);
const parsedLogs = logs.parseLogs(parseRawLog(result.rawLog));
const parsedLogs = logs.parseLogs(logs.parseRawLog(result.rawLog));
const contractAddressAttr = logs.findAttribute(parsedLogs, "message", "contract_address");
contractAddress = contractAddressAttr.value;
const amountAttr = logs.findAttribute(parsedLogs, "transfer", "amount");
@ -437,7 +440,7 @@ describe("WasmExtension", () => {
{
const result = await executeContract(wallet, contractAddress, { release: {} });
assertIsBroadcastTxSuccess(result);
const parsedLogs = logs.parseLogs(parseRawLog(result.rawLog));
const parsedLogs = logs.parseLogs(logs.parseRawLog(result.rawLog));
const wasmEvent = parsedLogs.find(() => true)?.events.find((e) => e.type === "wasm");
assert(wasmEvent, "Event of type wasm expected");
expect(wasmEvent.attributes).toContain({ key: "action", value: "release" });

View File

@ -2,15 +2,9 @@
import { UploadMeta } from "@cosmjs/cosmwasm-launchpad";
import { sha256 } from "@cosmjs/crypto";
import { toHex } from "@cosmjs/encoding";
import {
coin,
coins,
GasPrice,
MsgDelegate as LaunchpadMsgDelegate,
Secp256k1HdWallet,
} from "@cosmjs/launchpad";
import { GasPrice, MsgDelegate as LaunchpadMsgDelegate, Secp256k1HdWallet } from "@cosmjs/launchpad";
import { DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
import { AminoTypes, assertIsBroadcastTxSuccess } from "@cosmjs/stargate";
import { AminoTypes, assertIsBroadcastTxSuccess, coin, coins } from "@cosmjs/stargate";
import { DeepPartial, MsgSend } from "@cosmjs/stargate/build/codec/cosmos/bank/v1beta1/tx";
import { Coin } from "@cosmjs/stargate/build/codec/cosmos/base/v1beta1/coin";
import { MsgDelegate } from "@cosmjs/stargate/build/codec/cosmos/staking/v1beta1/tx";

View File

@ -15,11 +15,9 @@ import { sha256 } from "@cosmjs/crypto";
import { fromBase64, toHex, toUtf8 } from "@cosmjs/encoding";
import {
buildFeeTable,
Coin,
CosmosFeeTable,
GasLimits,
GasPrice,
logs,
makeSignDoc as makeSignDocAmino,
StdFee,
} from "@cosmjs/launchpad";
@ -37,9 +35,10 @@ import {
AminoTypes,
BroadcastTxFailure,
BroadcastTxResponse,
Coin,
defaultRegistryTypes,
isBroadcastTxFailure,
parseRawLog,
logs,
} from "@cosmjs/stargate";
import { SignMode } from "@cosmjs/stargate/build/codec/cosmos/tx/signing/v1beta1/signing";
import { TxRaw } from "@cosmjs/stargate/build/codec/cosmos/tx/v1beta1/tx";
@ -165,7 +164,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
const parsedLogs = parseRawLog(result.rawLog);
const parsedLogs = logs.parseRawLog(result.rawLog);
const codeIdAttr = logs.findAttribute(parsedLogs, "message", "code_id");
return {
originalSize: wasmCode.length,
@ -200,7 +199,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
if (isBroadcastTxFailure(result)) {
throw new Error(createBroadcastTxErrorMessage(result));
}
const parsedLogs = parseRawLog(result.rawLog);
const parsedLogs = logs.parseRawLog(result.rawLog);
const contractAddressAttr = logs.findAttribute(parsedLogs, "message", "contract_address");
return {
contractAddress: contractAddressAttr.value,
@ -228,7 +227,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
throw new Error(createBroadcastTxErrorMessage(result));
}
return {
logs: parseRawLog(result.rawLog),
logs: logs.parseRawLog(result.rawLog),
transactionHash: result.transactionHash,
};
}
@ -250,7 +249,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
throw new Error(createBroadcastTxErrorMessage(result));
}
return {
logs: parseRawLog(result.rawLog),
logs: logs.parseRawLog(result.rawLog),
transactionHash: result.transactionHash,
};
}
@ -276,7 +275,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
throw new Error(createBroadcastTxErrorMessage(result));
}
return {
logs: parseRawLog(result.rawLog),
logs: logs.parseRawLog(result.rawLog),
transactionHash: result.transactionHash,
};
}
@ -302,7 +301,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
throw new Error(createBroadcastTxErrorMessage(result));
}
return {
logs: parseRawLog(result.rawLog),
logs: logs.parseRawLog(result.rawLog),
transactionHash: result.transactionHash,
};
}

View File

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Bip39, EnglishMnemonic, Random, Secp256k1, Slip10, Slip10Curve } from "@cosmjs/crypto";
import { Bech32, fromBase64 } from "@cosmjs/encoding";
import { AminoSignResponse, coins, Secp256k1HdWallet, StdSignDoc } from "@cosmjs/launchpad";
import { AminoSignResponse, Secp256k1HdWallet, StdSignDoc } from "@cosmjs/launchpad";
import {
DirectSecp256k1HdWallet,
DirectSignResponse,
@ -11,6 +11,7 @@ import {
import {
AuthExtension,
BankExtension,
coins,
QueryClient,
setupAuthExtension,
setupBankExtension,

View File

@ -0,0 +1,107 @@
import { coin, coins, parseCoins } from "./coins";
describe("coins", () => {
describe("coin", () => {
it("works for basic values", () => {
expect(coin(123, "utoken")).toEqual({ amount: "123", denom: "utoken" });
expect(coin(123.0, "utoken")).toEqual({ amount: "123", denom: "utoken" });
expect(coin(Number.MAX_SAFE_INTEGER, "utoken")).toEqual({
amount: "9007199254740991",
denom: "utoken",
});
expect(coin(+0, "utoken")).toEqual({ amount: "0", denom: "utoken" });
expect(coin(-0, "utoken")).toEqual({ amount: "0", denom: "utoken" });
});
it("throws for non-safe-integer values", () => {
expect(() => coin(1.23, "utoken")).toThrow();
expect(() => coin(NaN, "utoken")).toThrow();
expect(() => coin(Number.POSITIVE_INFINITY, "utoken")).toThrow();
expect(() => coin(Number.MAX_SAFE_INTEGER + 1, "utoken")).toThrow();
});
it("throws for negative values", () => {
expect(() => coin(-1, "utoken")).toThrow();
expect(() => coin(Number.MIN_SAFE_INTEGER, "utoken")).toThrow();
expect(() => coin(Number.NEGATIVE_INFINITY, "utoken")).toThrow();
});
});
describe("coins", () => {
it("returns one element array of coin", () => {
expect(coins(123, "utoken")).toEqual([{ amount: "123", denom: "utoken" }]);
});
});
describe("parseCoins", () => {
it("works for empty", () => {
expect(parseCoins("")).toEqual([]);
});
it("works for one element", () => {
expect(parseCoins("7643ureef")).toEqual([
{
amount: "7643",
denom: "ureef",
},
]);
});
it("works for two", () => {
expect(parseCoins("819966000ucosm,700000000ustake")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
});
it("ignores empty elements", () => {
// start
expect(parseCoins(",819966000ucosm,700000000ustake")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
// middle
expect(parseCoins("819966000ucosm,,700000000ustake")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
// end
expect(parseCoins("819966000ucosm,700000000ustake,")).toEqual([
{
amount: "819966000",
denom: "ucosm",
},
{
amount: "700000000",
denom: "ustake",
},
]);
});
it("throws for invalid inputs", () => {
// denom missing
expect(() => parseCoins("3456")).toThrowError(/invalid coin string/i);
// amount missing
expect(() => parseCoins("ucosm")).toThrowError(/invalid coin string/i);
});
});
});

View File

@ -0,0 +1,47 @@
import { Uint53, Uint64 } from "@cosmjs/math";
/**
* This is the same as Coin from @cosmjs/launchpad but those might diverge in the future.
*/
export interface Coin {
readonly denom: string;
readonly amount: string;
}
/**
* Creates a coin.
*
* This is the same as coin from @cosmjs/launchpad but those might diverge in the future.
*/
export function coin(amount: number, denom: string): Coin {
return { amount: new Uint53(amount).toString(), denom: denom };
}
/**
* Creates a list of coins with one element
*
* This is the same as coins from @cosmjs/launchpad but those might diverge in the future.
*/
export function coins(amount: number, denom: string): Coin[] {
return [coin(amount, denom)];
}
/**
* Takes a coins list like "819966000ucosm,700000000ustake" and parses it
*
* This is the same as parseCoins from @cosmjs/launchpad but those might diverge in the future.
*/
export function parseCoins(input: string): Coin[] {
return input
.replace(/\s/g, "")
.split(",")
.filter(Boolean)
.map((part) => {
const match = part.match(/^([0-9]+)([a-zA-Z]+)/);
if (!match) throw new Error("Got an invalid coin string");
return {
amount: Uint64.fromString(match[1]).toString(),
denom: match[2],
};
});
}

View File

@ -1,3 +1,4 @@
export { Coin, coin, coins, parseCoins } from "./coins";
export {
isPbjsGeneratedType,
isTsProtoGeneratedType,

View File

@ -2,8 +2,6 @@
import { encodeBech32Pubkey } from "@cosmjs/amino";
import { fromBase64 } from "@cosmjs/encoding";
import {
coin,
coins,
MsgBeginRedelegate as LaunchpadMsgBeginRedelegate,
MsgCreateValidator as LaunchpadMsgCreateValidator,
MsgDelegate as LaunchpadMsgDelegate,
@ -16,6 +14,7 @@ import {
MsgWithdrawDelegatorReward as LaunchpadMsgWithdrawDelegatorReward,
MsgWithdrawValidatorCommission as LaunchpadMsgWithdrawValidatorCommission,
} from "@cosmjs/launchpad";
import { coin, coins } from "@cosmjs/proto-signing";
import { AminoTypes } from "./aminotypes";
import { MsgMultiSend, MsgSend } from "./codec/cosmos/bank/v1beta1/tx";

View File

@ -1,6 +1,8 @@
export { Coin, coin, coins, parseCoins } from "@cosmjs/proto-signing";
export { Account, accountFromAny } from "./accounts";
export { AminoConverter, AminoTypes } from "./aminotypes";
export { parseRawLog } from "./logs";
export * as logs from "./logs";
export {
AuthExtension,
BankExtension,

View File

@ -1,11 +1,91 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { logs } from "@cosmjs/launchpad";
import { isNonNullObject } from "@cosmjs/utils";
export function parseRawLog(input = "[]"): readonly logs.Log[] {
export interface Attribute {
readonly key: string;
readonly value: string;
}
export interface Event {
readonly type: string;
readonly attributes: readonly Attribute[];
}
export interface Log {
readonly msg_index: number;
readonly log: string;
readonly events: readonly Event[];
}
export function parseAttribute(input: unknown): Attribute {
if (!isNonNullObject(input)) throw new Error("Attribute must be a non-null object");
const { key, value } = input as any;
if (typeof key !== "string" || !key) throw new Error("Attribute's key must be a non-empty string");
if (typeof value !== "string" && typeof value !== "undefined") {
throw new Error("Attribute's value must be a string or unset");
}
return {
key: key,
value: value || "",
};
}
export function parseEvent(input: unknown): Event {
if (!isNonNullObject(input)) throw new Error("Event must be a non-null object");
const { type, attributes } = input as any;
if (typeof type !== "string" || type === "") {
throw new Error(`Event type must be a non-empty string`);
}
if (!Array.isArray(attributes)) throw new Error("Event's attributes must be an array");
return {
type: type,
attributes: attributes.map(parseAttribute),
};
}
export function parseLog(input: unknown): Log {
if (!isNonNullObject(input)) throw new Error("Log must be a non-null object");
const { msg_index, log, events } = input as any;
if (typeof msg_index !== "number") throw new Error("Log's msg_index must be a number");
if (typeof log !== "string") throw new Error("Log's log must be a string");
if (!Array.isArray(events)) throw new Error("Log's events must be an array");
return {
msg_index: msg_index,
log: log,
events: events.map(parseEvent),
};
}
export function parseLogs(input: unknown): readonly Log[] {
if (!Array.isArray(input)) throw new Error("Logs must be an array");
return input.map(parseLog);
}
export function parseRawLog(input = "[]"): readonly Log[] {
const logsToParse = JSON.parse(input).map(({ events }: { events: readonly unknown[] }, i: number) => ({
msg_index: i,
events,
log: "",
}));
return logs.parseLogs(logsToParse);
return parseLogs(logsToParse);
}
/**
* Searches in logs for the first event of the given event type and in that event
* for the first first attribute with the given attribute key.
*
* Throws if the attribute was not found.
*/
export function findAttribute(logs: readonly Log[], eventType: string, attrKey: string): Attribute {
const firstLogs = logs.find(() => true);
const out = firstLogs?.events
.find((event) => event.type === eventType)
?.attributes.find((attr) => attr.key === attrKey);
if (!out) {
throw new Error(
`Could not find attribute '${attrKey}' in first event of type '${eventType}' in first log.`,
);
}
return out;
}

View File

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { coin, coins } from "@cosmjs/launchpad";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { coin, coins, DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import { sleep } from "@cosmjs/utils";

View File

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { coin, coins } from "@cosmjs/launchpad";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { coin, coins, DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import { sleep } from "@cosmjs/utils";

View File

@ -1,12 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention,no-bitwise */
import {
coin,
coins,
GasPrice,
MsgDelegate as LaunchpadMsgDelegate,
Secp256k1HdWallet,
} from "@cosmjs/launchpad";
import { DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
import { GasPrice, MsgDelegate as LaunchpadMsgDelegate, Secp256k1HdWallet } from "@cosmjs/launchpad";
import { coin, coins, DirectSecp256k1HdWallet, Registry } from "@cosmjs/proto-signing";
import { assert, sleep } from "@cosmjs/utils";
import protobuf from "protobufjs/minimal";

View File

@ -2,7 +2,6 @@ import { encodeSecp256k1Pubkey } from "@cosmjs/amino";
import { fromBase64 } from "@cosmjs/encoding";
import {
buildFeeTable,
Coin,
CosmosFeeTable,
GasLimits,
GasPrice,
@ -24,6 +23,7 @@ import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import { AminoTypes } from "./aminotypes";
import { MsgMultiSend } from "./codec/cosmos/bank/v1beta1/tx";
import { Coin } from "./codec/cosmos/base/v1beta1/coin";
import {
MsgFundCommunityPool,
MsgSetWithdrawAddress,

View File

@ -1,6 +1,6 @@
import { fromBase64, toBase64 } from "@cosmjs/encoding";
import { Coin, coins } from "@cosmjs/launchpad";
import {
coins,
DirectSecp256k1HdWallet,
encodePubkey,
makeAuthInfoBytes,
@ -9,6 +9,7 @@ import {
} from "@cosmjs/proto-signing";
import { assert, sleep } from "@cosmjs/utils";
import { Coin } from "./codec/cosmos/base/v1beta1/coin";
import { Tx, TxRaw } from "./codec/cosmos/tx/v1beta1/tx";
import {
BroadcastTxResponse,

View File

@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Bip39, EnglishMnemonic, Random, Secp256k1, Slip10, Slip10Curve } from "@cosmjs/crypto";
import { Bech32 } from "@cosmjs/encoding";
import { AminoSignResponse, coins, Secp256k1HdWallet, StdSignDoc } from "@cosmjs/launchpad";
import { AminoSignResponse, Secp256k1HdWallet, StdSignDoc } from "@cosmjs/launchpad";
import {
coins,
DirectSecp256k1HdWallet,
DirectSignResponse,
makeAuthInfoBytes,