Create AminoTypes class and make it extensible

This commit is contained in:
Simon Warta 2020-12-21 17:53:04 +01:00
parent debe94935f
commit 017437994b
10 changed files with 63 additions and 40 deletions

View File

@ -35,13 +35,12 @@ import {
Registry,
} from "@cosmjs/proto-signing";
import {
AminoTypes,
BroadcastTxFailure,
BroadcastTxResponse,
codec,
fromAminoMsgType,
isBroadcastTxFailure,
parseRawLog,
toAminoMsgType,
} from "@cosmjs/stargate";
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
import Long from "long";
@ -110,6 +109,7 @@ export class SigningCosmWasmClient extends CosmWasmClient {
private readonly fees: CosmosFeeTable;
private readonly registry: Registry;
private readonly signer: OfflineSigner;
private readonly aminoTypes = new AminoTypes();
public static async connectWithWallet(
endpoint: string,
@ -368,14 +368,14 @@ export class SigningCosmWasmClient extends CosmWasmClient {
// Amino signer
const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON;
const msgs = messages.map((msg) => ({
type: toAminoMsgType(msg.typeUrl),
type: this.aminoTypes.toAmino(msg.typeUrl),
value: msg.value,
}));
const signDoc = makeSignDocAmino(msgs, fee, chainId, memo, accountNumber, sequence);
const { signature, signed } = await this.signer.signAmino(address, signDoc);
const signedTxBody = {
messages: signed.msgs.map((msg) => ({
typeUrl: fromAminoMsgType(msg.type),
typeUrl: this.aminoTypes.fromAmino(msg.type),
value: msg.value,
})),
memo: signed.memo,

View File

@ -25,6 +25,7 @@ export declare class SigningCosmWasmClient extends CosmWasmClient {
private readonly fees;
private readonly registry;
private readonly signer;
private readonly aminoTypes;
static connectWithWallet(
endpoint: string,
signer: OfflineSigner,

View File

@ -1,28 +1,28 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { fromAminoMsgType, toAminoMsgType } from "./encoding";
import { AminoTypes } from "./aminotypes";
describe("encoding", () => {
describe("toAminoMsgType", () => {
describe("AminoTypes", () => {
describe("toAmino", () => {
it("works for known type url", () => {
const msgType = toAminoMsgType("/cosmos.staking.v1beta1.MsgDelegate");
const msgType = new AminoTypes().toAmino("/cosmos.staking.v1beta1.MsgDelegate");
expect(msgType).toEqual("cosmos-sdk/MsgDelegate");
});
it("throws for unknown type url", () => {
expect(() => toAminoMsgType("/xxx.Unknown")).toThrowError(
expect(() => new AminoTypes().toAmino("/xxx.Unknown")).toThrowError(
/Type URL does not exist in the Amino message type register./i,
);
});
});
describe("fromAminoMsgType", () => {
describe("fromAmino", () => {
it("works for known type url", () => {
const msgUrl = fromAminoMsgType("cosmos-sdk/MsgDelegate");
const msgUrl = new AminoTypes().fromAmino("cosmos-sdk/MsgDelegate");
expect(msgUrl).toEqual("/cosmos.staking.v1beta1.MsgDelegate");
});
it("throws for unknown type url", () => {
expect(() => fromAminoMsgType("cosmos-sdk/MsgUnknown")).toThrowError(
expect(() => new AminoTypes().fromAmino("cosmos-sdk/MsgUnknown")).toThrowError(
/Type does not exist in the Amino message type register./i,
);
});

View File

@ -1,8 +1,4 @@
/**
* A map from Stargate message types as used in the messages's `Any` type
* to Amino types.
*/
const aminoTypeRegister: Record<string, string> = {
const defaultTypes: Record<string, string> = {
"/cosmos.bank.v1beta1.MsgSend": "cosmos-sdk/MsgSend",
"/cosmos.bank.v1beta1.MsgMultiSend": "cosmos-sdk/MsgMultiSend",
"/cosmos.crisis.v1beta1.MsgVerifyInvariant": "cosmos-sdk/MsgVerifyInvariant",
@ -23,22 +19,38 @@ const aminoTypeRegister: Record<string, string> = {
"/cosmos.vesting.v1beta1.MsgCreateVestingAccount": "cosmos-sdk/MsgCreateVestingAccount",
};
export function toAminoMsgType(typeUrl: string): string {
const type = aminoTypeRegister[typeUrl];
if (!type) {
throw new Error(
"Type URL does not exist in the Amino message type register. If you need support for this message, please open an issue at https://github.com/cosmos/cosmjs/issues.",
);
}
return type;
}
/**
* A map from Stargate message types as used in the messages's `Any` type
* to Amino types.
*/
export class AminoTypes {
private readonly register: Record<string, string>;
export function fromAminoMsgType(type: string): string {
const [typeUrl] = Object.entries(aminoTypeRegister).find(([_typeUrl, value]) => value === type) ?? [];
if (!typeUrl) {
throw new Error(
"Type does not exist in the Amino message type register. If you need support for this message, please open an issue at https://github.com/cosmos/cosmjs/issues.",
);
public constructor(additions: Record<string, string> = {}) {
this.register = { ...defaultTypes, ...additions };
}
public toAmino(typeUrl: string): string {
const type = defaultTypes[typeUrl];
if (!type) {
throw new Error(
"Type URL does not exist in the Amino message type register. " +
"If you need support for this message type, you can pass in additional entries to the AminoTypes constructor. " +
"If you think this message type should be included by default, please open an issue at https://github.com/cosmos/cosmjs/issues.",
);
}
return type;
}
public fromAmino(type: string): string {
const [typeUrl] = Object.entries(defaultTypes).find(([_typeUrl, value]) => value === type) ?? [];
if (!typeUrl) {
throw new Error(
"Type does not exist in the Amino message type register. " +
"If you need support for this message type, you can pass in additional entries to the AminoTypes constructor. " +
"If you think this message type should be included by default, please open an issue at https://github.com/cosmos/cosmjs/issues.",
);
}
return typeUrl;
}
return typeUrl;
}

View File

@ -1,5 +1,5 @@
export * as codec from "./codec";
export { toAminoMsgType, fromAminoMsgType } from "./encoding";
export { AminoTypes } from "./aminotypes";
export { parseRawLog } from "./logs";
export {
AuthExtension,

View File

@ -23,8 +23,8 @@ import {
} from "@cosmjs/proto-signing";
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
import { AminoTypes } from "./aminotypes";
import { cosmos } from "./codec";
import { fromAminoMsgType, toAminoMsgType } from "./encoding";
import { BroadcastTxResponse, StargateClient } from "./stargateclient";
const { TxRaw } = cosmos.tx.v1beta1;
@ -48,6 +48,7 @@ export class SigningStargateClient extends StargateClient {
private readonly fees: CosmosFeeTable;
private readonly registry: Registry;
private readonly signer: OfflineSigner;
private readonly aminoTypes = new AminoTypes();
public static async connectWithWallet(
endpoint: string,
@ -136,14 +137,14 @@ export class SigningStargateClient extends StargateClient {
// Amino signer
const signMode = cosmos.tx.signing.v1beta1.SignMode.SIGN_MODE_LEGACY_AMINO_JSON;
const msgs = messages.map((msg) => ({
type: toAminoMsgType(msg.typeUrl),
type: this.aminoTypes.toAmino(msg.typeUrl),
value: msg.value,
}));
const signDoc = makeSignDocAmino(msgs, fee, chainId, memo, accountNumber, sequence);
const { signature, signed } = await this.signer.signAmino(address, signDoc);
const signedTxBody = {
messages: signed.msgs.map((msg) => ({
typeUrl: fromAminoMsgType(msg.type),
typeUrl: this.aminoTypes.fromAmino(msg.type),
value: msg.value,
})),
memo: signed.memo,

10
packages/stargate/types/aminotypes.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
/**
* A map from Stargate message types as used in the messages's `Any` type
* to Amino types.
*/
export declare class AminoTypes {
private readonly register;
constructor(additions?: Record<string, string>);
toAmino(typeUrl: string): string;
fromAmino(type: string): string;
}

View File

@ -1,2 +0,0 @@
export declare function toAminoMsgType(typeUrl: string): string;
export declare function fromAminoMsgType(type: string): string;

View File

@ -1,5 +1,5 @@
export * as codec from "./codec";
export { toAminoMsgType, fromAminoMsgType } from "./encoding";
export { AminoTypes } from "./aminotypes";
export { parseRawLog } from "./logs";
export {
AuthExtension,

View File

@ -15,6 +15,7 @@ export declare class SigningStargateClient extends StargateClient {
private readonly fees;
private readonly registry;
private readonly signer;
private readonly aminoTypes;
static connectWithWallet(
endpoint: string,
signer: OfflineSigner,