Skip to content

Instantly share code, notes, and snippets.

@giansalex
Last active May 5, 2023 04:20
Show Gist options
  • Save giansalex/f8e0719ac7b3879aeb8be2fd204bc716 to your computer and use it in GitHub Desktop.
Save giansalex/f8e0719ac7b3879aeb8be2fd204bc716 to your computer and use it in GitHub Desktop.
Authz Ledger support for Cosmos sdk 45.x
function isAminoConverter(
converter,
) {
return typeof converter[1] !== "string";
}
/**
* A map from Stargate message types as used in the messages's `Any` type
* to Amino types.
*/
export class AminoTypes {
constructor(types) {
this.register = types;
}
toAmino({ typeUrl, value }) {
const converter = this.register[typeUrl];
if (converter === "not_supported_by_chain") {
throw new Error(
`The message type '${typeUrl}' cannot be signed using the Amino JSON sign mode because this is not supported by chain.`,
);
}
if (!converter) {
throw new Error(
`Type URL '${typeUrl}' 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.",
);
}
if (typeUrl === "/cosmos.authz.v1beta1.MsgGrant" || typeUrl === "/cosmos.authz.v1beta1.MsgRevoke") {
return converter.toAmino(value)
}
return {
type: converter.aminoType,
value: converter.toAmino(value),
};
}
fromAmino(data) {
if (!data.type) {
const typeUrl = data.msg_type_url ? "/cosmos.authz.v1beta1.MsgRevoke" : "/cosmos.authz.v1beta1.MsgGrant"
const converter = this.register[typeUrl];
return {
typeUrl: typeUrl,
value: converter.fromAmino(data),
}
}
const { type, value } = data
const matches = Object.entries(this.register)
.filter(isAminoConverter)
.filter(([_typeUrl, { aminoType }]) => aminoType === type);
switch (matches.length) {
case 0: {
throw new Error(
`Amino type identifier '${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.",
);
}
case 1: {
const [typeUrl, converter] = matches[0];
return {
typeUrl: typeUrl,
value: converter.fromAmino(value),
};
}
default:
throw new Error(
`Multiple types are registered with Amino type identifier '${type}': '` +
matches
.map(([key, _value]) => key)
.sort()
.join("', '") +
"'. Thus fromAmino cannot be performed.",
);
}
}
}
import { MsgGrant, MsgRevoke } from "cosmjs-types/cosmos/authz/v1beta1/tx"
import { GenericAuthorization } from "cosmjs-types/cosmos/authz/v1beta1/authz"
import { Timestamp } from "cosmjs-types/google/protobuf/timestamp"
import dayjs from 'dayjs'
export function createAuthzAminoConverters() {
return {
"/cosmos.authz.v1beta1.MsgGrant": {
aminoType: "cosmos-sdk/MsgGrant",
toAmino: ({ granter, grantee, grant }) => {
if (grant.authorization.typeUrl !== "/cosmos.authz.v1beta1.GenericAuthorization") {
throw new Error(`Unsupported grant type: '${grant.authorization.typeUrl}'`);
}
const generic = GenericAuthorization.decode(grant.authorization.value);
const t = new Date(1970, 0, 1);
t.setSeconds(grant.expiration.seconds);
return {
granter: granter,
grantee: grantee,
grant: {
authorization: {
msg: generic.msg,
},
expiration: dayjs(t).format("YYYY-MM-DDTHH:mm:ss") + "Z",
}
}
},
fromAmino: ({ granter, grantee, grant }) => MsgGrant.fromPartial({
granter: granter,
grantee: grantee,
grant: {
authorization: {
typeUrl: "/cosmos.authz.v1beta1.GenericAuthorization",
value: GenericAuthorization.encode({
msg: grant.authorization.msg,
}).finish(),
},
expiration: Timestamp.fromPartial({
nanos: 0,
seconds: dayjs(grant.expiration).unix(),
})
}
})
},
"/cosmos.authz.v1beta1.MsgRevoke": {
aminoType: "cosmos-sdk/MsgRevoke",
toAmino: ({ granter, grantee, msgTypeUrl }) => ({
granter: granter,
grantee: grantee,
msg_type_url: msgTypeUrl,
}),
fromAmino: ({ granter, grantee, msg_type_url }) => MsgRevoke.fromPartial({
granter: granter,
grantee: grantee,
msgTypeUrl: msg_type_url,
}),
},
}
}
import {
createBankAminoConverters,
createDistributionAminoConverters,
createFreegrantAminoConverters,
createGovAminoConverters,
createIbcAminoConverters,
createStakingAminoConverters,
SigningStargateClient
} from "@cosmjs/stargate";
import { createAuthzAminoConverters } from "./authz";
import { AminoTypes } from "./amino";
function demo() {
const client = await SigningStargateClient.connectWithSigner(
"http://127.0.0.1:26657",
signer,
{
aminoTypes: new AminoTypes(createDefaultTypes("juno")),
},
)
}
function createDefaultTypes(prefix) {
return {
...createBankAminoConverters(),
...createDistributionAminoConverters(),
...createGovAminoConverters(),
...createStakingAminoConverters(prefix),
...createIbcAminoConverters(),
...createFreegrantAminoConverters(),
...createAuthzAminoConverters(),
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment