Skip to content

Commit

Permalink
feat: add support for cosmos.gov.v1 messages (#629)
Browse files Browse the repository at this point in the history
## Description



This PR adds the support to the new x/gov messages

Closes: SDK-13
Closes: #625

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/desmos-labs/desmjs/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed all author checklist items have been addressed
- [ ] confirmed that this PR does not change production code
  • Loading branch information
manu0466 authored Jun 28, 2023
1 parent 1c72d79 commit a7af404
Show file tree
Hide file tree
Showing 155 changed files with 44,863 additions and 2,093 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@
"publish-latest": "yarn workspaces foreach --exclude desmjs-documentation --no-private exec npm publish"
},
"devDependencies": {
"@cosmjs/cosmwasm-stargate": "0.30.1",
"@cosmjs/crypto": "0.30.1",
"@cosmjs/cosmwasm-stargate": "0.31.0",
"@cosmjs/crypto": "0.31.0",
"@cosmjs/encoding": "0.31.0",
"@cosmjs/proto-signing": "0.30.1",
"@cosmjs/proto-signing": "0.31.0",
"@cosmjs/utils": "^0.31.0",
"@desmoslabs/desmjs": "workspace:packages/core",
"@desmoslabs/desmjs-types": "workspace:packages/types",
Expand Down
14 changes: 7 additions & 7 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
"lint-fix": "yarn lint --fix"
},
"dependencies": {
"@cosmjs/amino": "0.30.1",
"@cosmjs/cosmwasm-stargate": "0.30.1",
"@cosmjs/crypto": "0.30.1",
"@cosmjs/amino": "0.31.0",
"@cosmjs/cosmwasm-stargate": "0.31.0",
"@cosmjs/crypto": "0.31.0",
"@cosmjs/encoding": "0.31.0",
"@cosmjs/math": "0.30.1",
"@cosmjs/proto-signing": "0.30.1",
"@cosmjs/stargate": "0.30.1",
"@cosmjs/tendermint-rpc": "0.30.1",
"@cosmjs/math": "0.31.0",
"@cosmjs/proto-signing": "0.31.0",
"@cosmjs/stargate": "0.31.0",
"@cosmjs/tendermint-rpc": "0.31.0",
"@cosmjs/utils": "^0.31.0",
"@desmoslabs/desmjs-types": "workspace:packages/types",
"cosmjs-types": "^0.5.2",
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/aminomessages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ import { createSubspacesConverters, subspacesRegistryTypes } from "./subspaces";
import { createPostsConverters, postsRegistryTypes } from "./posts";
import { createReactionsConverters, reactionsRegistryTypes } from "./reactions";
import { createReportsConverters, reportsRegistryTypes } from "./reports";
import GovV1Beta1AminoConverter from "../modules/gov/v1beta1/aminoconverter";
import GovV1AminoConverter from "../modules/gov/v1/aminoconverter";
import GovV1Registry from "../modules/gov/v1/registry";
import GovV1Beta1Registry from "../modules/gov/v1beta1/registry";

export * from "./cosmos/authz/messages";
export * from "./cosmos/bank/messages";
Expand All @@ -42,6 +46,8 @@ export function createDesmosTypes(): AminoConverters {
...createBankAminoConverters(),
...createDistributionAminoConverters(),
...createGovAminoConverters(),
...GovV1Beta1AminoConverter,
...GovV1AminoConverter,
...createStakingAminoConverters(),
...createIbcAminoConverters(),
...createVestingAminoConverters(),
Expand All @@ -63,6 +69,8 @@ export function createDesmosTypes(): AminoConverters {

export const desmosRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [
...defaultRegistryTypes,
...GovV1Beta1Registry,
...GovV1Registry,

...cosmosRegistryTypes,
...desmjsRegistryTypes,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/aminomessages/testutils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function runConverterTest(
) {
return async () => {
const converter = converters[data.typeUrl];
if (!converter || converter === "not_supported_by_chain") {
if (!converter) {
fail(`Cannot find converter for msg with type url ${data.typeUrl}`);
}

Expand Down
127 changes: 127 additions & 0 deletions packages/core/src/aminotypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { AminoMsg } from "@cosmjs/amino";
import { EncodeObject, Registry } from "@cosmjs/proto-signing";
import {
AminoConverter as CosmJSAminoConverter,
AminoTypes as CosmJSAminoTypes,
} from "@cosmjs/stargate";
import { Any } from "@desmoslabs/desmjs-types/google/protobuf/any";

/**
* Interface that represents an object capable of convert
* an {@link EncodeObject} from and to {@link AminoMsg}.
* NOTE: This is an extension of the {@link CosmJSAminoConverter} from
* cosmjs to allow the conversion of objects that have a field with
* type {@link Any} like the MsgExec of the x/authz module.
*/
export interface AminoConverter extends CosmJSAminoConverter {
/**
* Converts an {@link EncodeObject} to its amino representation.
* @param encodeObject - The object to convert to {@link AminoMsg}.
* @param aminoTypes - An object to convert an {@link Any} encoded object
* from and to {@link AminoMsg}.
* NOTE: This is optional to make the interface backward compatible with
* {@link CosmJSAminoConverter}.
*/
readonly toAmino: (
encodeObject: EncodeObject,
aminoTypes?: AminoTypes
) => AminoMsg;
/**
* Converts an {@link AminoMsg} to its {@link EncodeObject} representation.
* @param aminoMsg - The object to convert to {@link AminoMsg}
* @param aminoTypes - An object to convert an {@link Any} encoded object
* from and to {@link AminoMsg}.
* NOTE: This is optional to make the interface backward compatible with
* {@link CosmJSAminoConverter}.
*/
readonly fromAmino: (
aminoMsg: AminoMsg,
aminoTypes?: AminoTypes
) => EncodeObject;
}

declare type AminoConverters = Record<string, AminoConverter>;

/**
* Extensions of the {@link CosmJSAminoTypes} that supports
* the amino serialization of messages that have {@link Any} encoed
* messages as child like the MsgExec of the x/authz module.
*/
export class AminoTypes extends CosmJSAminoTypes {
private readonly converters;

private readonly registry;

constructor(converters: AminoConverters, registry: Registry) {
super(converters);
this.converters = converters;
this.registry = registry;
}

public override toAmino({ typeUrl, value }: EncodeObject): AminoMsg {
const converter = this.converters[typeUrl];
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."
);
}

return {
type: converter.aminoType,
value: converter.toAmino(value, this),
};
}

public override fromAmino({ type, value }: AminoMsg): EncodeObject {
const matches = Object.entries(this.converters).filter(
([, converter]) => converter.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,
value: converter.fromAmino(value, this),
};
}
default:
throw new Error(
`Multiple types are registered with Amino type identifier '${type}': '${matches
.map(([key]) => key)
.sort()
.join("', '")}'. Thus fromAmino cannot be performed.`
);
}
}

/**
* Function to convert a {@link Any} encoded object to its
* amino representation.
* @param anyEncodedObject - The object to convert to amino.
*/
public fromAny(anyEncodedObject: Any): AminoMsg {
return this.toAmino({
typeUrl: anyEncodedObject.typeUrl,
value: this.registry.decode(anyEncodedObject),
});
}

/**
* Function to convert a {@link AminoMsg} to its {@link Any}
* representation.
* @param aminoEncodedObject - The object to convert to {@link Any}.
*/
public toAny(aminoEncodedObject: AminoMsg): Any {
return this.registry.encodeAsAny(this.fromAmino(aminoEncodedObject));
}
}
2 changes: 0 additions & 2 deletions packages/core/src/cosmjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export {
IndexedTx,
SearchByHeightQuery,
SearchBySentFromOrToQuery,
SearchByTagsQuery,
SearchTxFilter,
SearchTxQuery,
SequenceResponse,
StdFee,
Expand Down
82 changes: 13 additions & 69 deletions packages/core/src/desmosclient.integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ChainConfig,
Proof,
SignatureValueType,
SingleSignature,
SingleSignature
} from "@desmoslabs/desmjs-types/desmos/profiles/v3/models_chain_links";
import { Any } from "@desmoslabs/desmjs-types/google/protobuf/any";
import { MsgLinkChainAccount } from "@desmoslabs/desmjs-types/desmos/profiles/v3/msgs_chain_links";
Expand All @@ -19,17 +19,21 @@ import { sleep } from "@cosmjs/utils";
import { DesmosClient } from "./desmosclient";
import { OfflineSignerAdapter, Signer, SigningMode } from "./signers";
import {
assertTxSuccess,
defaultGasPrice,
getAminoSignerAndClient,
getDirectSignerAndClient,
pollTx,
TEST_CHAIN_URL,
testUser1,
testUser2,
testUser2
} from "./testutils";
import {
getPubKeyBytes,
getPubKeyRawBytes,
getSignatureBytes,
getSignedBytes,
SignatureResult,
SignatureResult
} from "./signatureresult";
import {
MsgAddReactionEncodeObject,
Expand All @@ -41,12 +45,9 @@ import {
MsgCreateSubspaceEncodeObject,
MsgLinkChainAccountEncodeObject,
MsgMultiSendEncodeObject,
MsgSaveProfileEncodeObject,
MsgSaveProfileEncodeObject
} from "./encodeobjects";
import {
bech32AddressToAny,
singleSignatureToAny,
} from "./aminomessages/profiles";
import { bech32AddressToAny, singleSignatureToAny } from "./aminomessages/profiles";
import { postTargetToAny } from "./aminomessages/reports";
import { registeredReactionValueToAny } from "./aminomessages/reactions";
import {
Expand All @@ -58,71 +59,13 @@ import {
MsgCreateReportTypeUrl,
MsgCreateSubspaceTypeUrl,
MsgMultiSendTypeUrl,
MsgSaveProfileTypeUrl,
MsgSaveProfileTypeUrl
} from "./const";
import MsgAuthenticateTypeUrl from "./const/desmjs";

describe("DesmosClient", () => {
jest.setTimeout(60 * 1000);

/**
* Builds a Signer and DesmosClient instance based on a test mnemonic.
* The returned signer will sign transactions using the AMINO signing mode.
*/
async function getAminoSignerAndClient(): Promise<[Signer, DesmosClient]> {
const signer = await OfflineSignerAdapter.fromMnemonic(
SigningMode.AMINO,
testUser1.mnemonic
);
const client = await DesmosClient.connectWithSigner(
TEST_CHAIN_URL,
signer,
{
gasPrice: defaultGasPrice,
gasAdjustment: 1.5,
}
);
return [signer, client];
}

/**
* Builds a Signer and DesmosClient instance based on a test mnemonic.
* The returned signer will sign transactions using the DIRECT signing mode.
*/
async function getDirectSignerAndClient(): Promise<[Signer, DesmosClient]> {
const signer = await OfflineSignerAdapter.fromMnemonic(
SigningMode.DIRECT,
testUser1.mnemonic
);
const client = await DesmosClient.connectWithSigner(
TEST_CHAIN_URL,
signer,
{
gasPrice: defaultGasPrice,
gasAdjustment: 1.8,
}
);
return [signer, client];
}

async function pollTx(client: DesmosClient, txHash: string): Promise<void> {
let timedOut = false;
const txPollTimeout = setTimeout(() => {
timedOut = true;
}, 60000);

while (!timedOut) {
const tx = await client.getTx(txHash);
if (tx !== null) {
clearTimeout(txPollTimeout);
return;
}
await sleep(3000);
}

throw new Error(`Timed out waiting for tx ${txHash}`);
}

describe("SignatureResult utils", () => {
async function getSignatureResult(): Promise<SignatureResult> {
const [signer, client] = await getDirectSignerAndClient();
Expand Down Expand Up @@ -813,7 +756,7 @@ describe("DesmosClient", () => {
},
} as MsgSaveProfileEncodeObject,
]);
const response = await client.broadcastTxSync(signResult.txRaw);
const response = await client.broadcastTxRawSync(signResult.txRaw);
await pollTx(client, response.hash);
});

Expand All @@ -830,7 +773,8 @@ describe("DesmosClient", () => {
},
} as MsgSaveProfileEncodeObject,
]);
await client.broadcastTxBlock(signResult.txRaw);
const response = await client.broadcastTxBlock(signResult.txRaw);
assertTxSuccess(response);
});
});
});
Loading

0 comments on commit a7af404

Please sign in to comment.