Skip to content

Commit

Permalink
feat: Backport v3 protocol release proto API
Browse files Browse the repository at this point in the history
  • Loading branch information
Eengineer1 committed Nov 25, 2024
1 parent dc1078a commit 77bf258
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 18 deletions.
21 changes: 14 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"README.md"
],
"dependencies": {
"@cheqd/ts-proto": "~2.3.2",
"@cheqd/ts-proto": "^2.4.0",
"@cosmjs/amino": "~0.30.1",
"@cosmjs/crypto": "~0.30.1",
"@cosmjs/encoding": "~0.30.1",
Expand Down
24 changes: 20 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CheqdNetwork, IContext, IModuleMethodMap } from './types';
import { GasPrice, QueryClient } from '@cosmjs/stargate';
import { CheqdQuerier } from './querier';
import { Tendermint37Client } from '@cosmjs/tendermint-rpc';
import { FeemarketExtension, FeemarketModule } from './modules/feemarket';

export interface ICheqdSDKOptions {
modules: AbstractCheqdSDKModule[];
Expand All @@ -32,7 +33,7 @@ export interface CheqdSDK extends DefaultCheqdSDKModules {}
export class CheqdSDK {
methods: IModuleMethodMap;
signer: CheqdSigningStargateClient;
querier: CheqdQuerier & DidExtension & ResourceExtension;
querier: CheqdQuerier & DidExtension & ResourceExtension & FeemarketExtension;
options: ICheqdSDKOptions;
private protectedMethods: string[] = ['constructor', 'build', 'loadModules', 'loadRegistry'];

Expand Down Expand Up @@ -92,12 +93,14 @@ export class CheqdSDK {
return createDefaultCheqdRegistry(registryTypes);
}

private async loadQuerierExtensions(): Promise<CheqdQuerier & DidExtension & ResourceExtension> {
private async loadQuerierExtensions(): Promise<
CheqdQuerier & DidExtension & ResourceExtension & FeemarketExtension
> {
const querierExtensions = this.options.modules.map((module) =>
instantiateCheqdSDKModuleQuerierExtensionSetup(module)
);
const querier = await CheqdQuerier.connectWithExtensions(this.options.rpcUrl, ...querierExtensions);
return <CheqdQuerier & DidExtension & ResourceExtension>querier;
return <CheqdQuerier & DidExtension & ResourceExtension & FeemarketExtension>querier;
}

async build(): Promise<CheqdSDK> {
Expand Down Expand Up @@ -133,7 +136,7 @@ export async function createCheqdSDK(options: ICheqdSDKOptions): Promise<CheqdSD
return await new CheqdSDK(options).build();
}

export { DIDModule, ResourceModule };
export { DIDModule, ResourceModule, FeemarketModule };
export { AbstractCheqdSDKModule, applyMixins } from './modules/_';
export {
DidExtension,
Expand Down Expand Up @@ -168,6 +171,19 @@ export {
setupResourceExtension,
isMsgCreateResourceEncodeObject,
} from './modules/resource';
export {
FeemarketExtension,
MinimalImportableFeemarketModule,
defaultFeemarketExtensionKey,
protobufLiterals as protobufLiteralsFeemarket,
typeUrlGasPriceResponse,
typeUrlGasPricesResponse,
typeUrlParamsResponse,
setupFeemarketExtension,
isGasPriceEncodeObject,
isGasPricesEncodeObject,
isParamsEncodeObject,
} from './modules/feemarket';
export * from './signer';
export * from './querier';
export * from './registry';
Expand Down
1 change: 1 addition & 0 deletions src/modules/did.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export const setupDidExtension = (base: QueryClient): DidExtension => {
};

export class DIDModule extends AbstractCheqdSDKModule {
//@ts-expect-error the underlying type is intentionally wider
static readonly registryTypes: Iterable<[string, GeneratedType]> = [
[typeUrlMsgCreateDidDoc, MsgCreateDidDoc],
[typeUrlMsgCreateDidDocResponse, MsgCreateDidDocResponse],
Expand Down
131 changes: 131 additions & 0 deletions src/modules/feemarket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import {
GasPriceResponse,
GasPricesResponse,
ParamsResponse,
QueryClientImpl,
protobufPackage,
} from '@cheqd/ts-proto/feemarket/feemarket/v1/index.js';
import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing';
import { createProtobufRpcClient, QueryClient } from '@cosmjs/stargate';
import { AbstractCheqdSDKModule, MinimalImportableCheqdSDKModule } from './_';
import { IContext, QueryExtensionSetup } from '../types';
import { CheqdQuerier } from '../querier';
import { CheqdSigningStargateClient } from '../signer';

export const defaultFeemarketExtensionKey = 'feemarket' as const;

export const protobufLiterals = {
GasPriceResponse: 'GasPriceResponse',
GasPricesResponse: 'GasPricesResponse',
ParamsResponse: 'ParamsResponse',
} as const;

export const typeUrlGasPriceResponse = `/${protobufPackage}.${protobufLiterals.GasPriceResponse}`;
export const typeUrlGasPricesResponse = `/${protobufPackage}.${protobufLiterals.GasPricesResponse}`;
export const typeUrlParamsResponse = `/${protobufPackage}.${protobufLiterals.ParamsResponse}`;

export interface GasPriceEncodeObject extends EncodeObject {
readonly typeUrl: typeof typeUrlGasPriceResponse;
readonly value: Partial<GasPriceResponse>;
}

export function isGasPriceEncodeObject(obj: EncodeObject): obj is GasPriceEncodeObject {
return obj.typeUrl === typeUrlGasPriceResponse;
}

export interface GasPricesEncodeObject extends EncodeObject {
readonly typeUrl: typeof typeUrlGasPricesResponse;
readonly value: Partial<GasPricesResponse>;
}

export function isGasPricesEncodeObject(obj: EncodeObject): obj is GasPricesEncodeObject {
return obj.typeUrl === typeUrlGasPricesResponse;
}

export interface ParamsEncodeObject extends EncodeObject {
readonly typeUrl: typeof typeUrlParamsResponse;
readonly value: Partial<ParamsResponse>;
}

export function isParamsEncodeObject(obj: EncodeObject): obj is ParamsEncodeObject {
return obj.typeUrl === typeUrlParamsResponse;
}

export type MinimalImportableFeemarketModule = MinimalImportableCheqdSDKModule<FeemarketModule>;

export type FeemarketExtension = {
readonly [defaultFeemarketExtensionKey]: {
readonly gasPrice: (denom: string) => Promise<GasPriceResponse>;
readonly gasPrices: () => Promise<GasPricesResponse>;
readonly params: () => Promise<ParamsResponse>;
};
};

export const setupFeemarketExtension = (base: QueryClient): FeemarketExtension => {
const rpc = createProtobufRpcClient(base);

const queryService = new QueryClientImpl(rpc);

return {
[defaultFeemarketExtensionKey]: {
gasPrice: async (denom: string) => {
return queryService.GasPrice({ denom });
},
gasPrices: async () => {
return queryService.GasPrices({});
},
params: async () => {
return queryService.Params({});
},
},
};
};

export class FeemarketModule extends AbstractCheqdSDKModule {
// @ts-expect-error underlying type `GeneratedType` is intentionally wider
static readonly registryTypes: Iterable<[string, GeneratedType]> = [
[typeUrlGasPriceResponse, GasPriceResponse],
[typeUrlGasPricesResponse, GasPricesResponse],
[typeUrlParamsResponse, ParamsResponse],
];

static readonly querierExtensionSetup: QueryExtensionSetup<FeemarketExtension> = setupFeemarketExtension;

querier: CheqdQuerier & FeemarketExtension;

constructor(signer: CheqdSigningStargateClient, querier: CheqdQuerier & FeemarketExtension) {
super(signer, querier);
this.querier = querier;
this.methods = {
queryGasPrice: this.queryGasPrice.bind(this),
queryGasPrices: this.queryGasPrices.bind(this),
queryParams: this.queryParams.bind(this),
};
}

getRegistryTypes(): Iterable<[string, GeneratedType]> {
return FeemarketModule.registryTypes;
}

getQuerierExtensionSetup(): QueryExtensionSetup<FeemarketExtension> {
return FeemarketModule.querierExtensionSetup;
}

async queryGasPrice(denom: string, context?: IContext): Promise<GasPriceResponse> {
if (!this.querier) this.querier = context!.sdk!.querier;

return this.querier[defaultFeemarketExtensionKey].gasPrice(denom);
}

async queryGasPrices(context?: IContext): Promise<GasPricesResponse> {
if (!this.querier) this.querier = context!.sdk!.querier;

return this.querier[defaultFeemarketExtensionKey].gasPrices();
}

async queryParams(context?: IContext): Promise<ParamsResponse> {
if (!this.querier) this.querier = context!.sdk!.querier;

return this.querier[defaultFeemarketExtensionKey].params();
}
}
7 changes: 4 additions & 3 deletions src/modules/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export const setupResourceExtension = (base: QueryClient): ResourceExtension =>
};

export class ResourceModule extends AbstractCheqdSDKModule {
//@ts-expect-error the underlying type is intentionally wider
static readonly registryTypes: Iterable<[string, GeneratedType]> = [
[typeUrlMsgCreateResource, MsgCreateResource],
[typeUrlMsgCreateResourceResponse, MsgCreateResourceResponse],
Expand Down Expand Up @@ -232,7 +233,7 @@ export class ResourceModule extends AbstractCheqdSDKModule {
static async generateCreateResourceImageFees(feePayer: string, granter?: string): Promise<DidStdFee> {
return {
amount: [ResourceModule.fees.DefaultCreateResourceImageFee],
gas: '1200000',
gas: '2000000',
payer: feePayer,
granter: granter,
} as DidStdFee;
Expand All @@ -241,7 +242,7 @@ export class ResourceModule extends AbstractCheqdSDKModule {
static async generateCreateResourceJsonFees(feePayer: string, granter?: string): Promise<DidStdFee> {
return {
amount: [ResourceModule.fees.DefaultCreateResourceJsonFee],
gas: '1200000',
gas: '2000000',
payer: feePayer,
granter: granter,
} as DidStdFee;
Expand All @@ -250,7 +251,7 @@ export class ResourceModule extends AbstractCheqdSDKModule {
static async generateCreateResourceDefaultFees(feePayer: string, granter?: string): Promise<DidStdFee> {
return {
amount: [ResourceModule.fees.DefaultCreateResourceDefaultFee],
gas: '1200000',
gas: '2000000',
payer: feePayer,
granter: granter,
} as DidStdFee;
Expand Down
6 changes: 5 additions & 1 deletion src/querier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ export class CheqdQuerier extends QueryClient {
}

const tmClient = await Tendermint37Client.connect(url);
const tupleLike = extensions as [QueryExtensionSetup<CheqdExtensions>, QueryExtensionSetup<CheqdExtensions>];
const tupleLike = extensions as [
QueryExtensionSetup<CheqdExtensions>,
QueryExtensionSetup<CheqdExtensions>,
QueryExtensionSetup<CheqdExtensions>,
];
return CheqdQuerier.withExtensions(tmClient, ...tupleLike);
}
}
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { QueryClient } from '@cosmjs/stargate';
import { DIDResolutionResult } from 'did-resolver';
import { DidExtension } from './modules/did';
import { ResourceExtension } from './modules/resource';
import { FeemarketExtension } from './modules/feemarket';
export { DIDDocument, VerificationMethod, Service, ServiceEndpoint, JsonWebKey } from 'did-resolver';

export enum CheqdNetwork {
Expand All @@ -22,7 +23,7 @@ export type CheqdExtension<K extends string, V = any> = {
[P in K]: Record<P, V> & Partial<Record<Exclude<K, P>, never>> extends infer O ? { [Q in keyof O]: O[Q] } : never;
}[K];

export type CheqdExtensions = DidExtension | ResourceExtension;
export type CheqdExtensions = DidExtension | ResourceExtension | FeemarketExtension;

export interface IModuleMethod {
(...args: any[]): Promise<any>;
Expand Down
43 changes: 43 additions & 0 deletions tests/modules/feemarket.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
import { faucet, localnet } from '../testutils.test';
import { CheqdQuerier, CheqdSigningStargateClient, DIDModule } from '../../src';
import { FeemarketExtension, FeemarketModule, setupFeemarketExtension } from '../../src/modules/feemarket';

const defaultAsyncTxTimeout = 30000;

(BigInt.prototype as any).toJSON = function () {
return this.toString();
};

describe('FeemarketModule', () => {
describe('constructor', () => {
it('should instantiate standalone module', async () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet);
const querier = (await CheqdQuerier.connectWithExtension(
localnet.rpcUrl,
setupFeemarketExtension
)) as CheqdQuerier & FeemarketExtension;
const feemarketModule = new FeemarketModule(signer, querier);
expect(feemarketModule).toBeInstanceOf(FeemarketModule);
});
});

describe('queryGasPrice', () => {
it('should query gas price', async () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet);
const querier = (await CheqdQuerier.connectWithExtension(
localnet.rpcUrl,
setupFeemarketExtension
)) as CheqdQuerier & FeemarketExtension;
const feemarketModule = new FeemarketModule(signer, querier);
const gasPrice = await feemarketModule.queryGasPrice('ncheq');

expect(gasPrice).toBeDefined();
expect(gasPrice.price).toBeDefined();
expect(gasPrice.price!.denom).toEqual(DIDModule.baseMinimalDenom);
expect(Number(gasPrice.price!.amount)).toBeGreaterThan(0);
});
});
});
1 change: 1 addition & 0 deletions tests/signer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('CheqdSigningStargateClient', () => {
it('can be constructed with cheqd custom registry', async () => {
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
const registry = new Registry();
//@ts-expect-error the underlying type is intentionally wider
registry.register(typeUrlMsgCreateDidDoc, MsgCreateDidDoc);
const signer = await CheqdSigningStargateClient.connectWithSigner(localnet.rpcUrl, wallet, { registry });
expect(signer.registry.lookupType(typeUrlMsgCreateDidDoc)).toBe(MsgCreateDidDoc);
Expand Down
2 changes: 1 addition & 1 deletion tests/testutils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const faucet = {

export const localnet = {
network: CheqdNetwork.Testnet,
rpcUrl: 'http://localhost:26657',
rpcUrl: 'https://rpc.cheqd.network:443',
gasPrice: GasPrice.fromString(`50${faucet.minimalDenom}`),
};

Expand Down

0 comments on commit 77bf258

Please sign in to comment.