Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/helpers poc #209

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
common utils
  • Loading branch information
Zetazzz committed Oct 7, 2024
commit 9f12f7263c6ea376bb3bb00f0778c7b0cf44773d
8 changes: 3 additions & 5 deletions examples/interchainjs/pages/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { SendTokensCard } from '../components/react/send-tokens-card';
import {
cosmos,
createRpcQueryHooks,
DEFAULT_SIGNING_CLIENT_QUERY_KEY,
useDefaultRpcClient,
} from '../src/codegen';
import { useRpcClient } from '../src/codegen';
Expand All @@ -53,10 +54,7 @@ import { SigningClient } from 'interchainjs/signing-client';
import { MsgSend } from '../src/codegen/cosmos/bank/v1beta1/tx';
import { DeliverTxResponse, StdFee } from '@interchainjs/cosmos-types/types';
import { useBalance } from '../src/codegen/cosmos/bank/v1beta1/query.rpc.funcs';
import {
SIGNING_CLIENT_QUERY_KEY,
useSend,
} from '../src/codegen/cosmos/bank/v1beta1/tx.rpc.func';
import { useSend } from '../src/codegen/cosmos/bank/v1beta1/tx.rpc.func';
import { useQueryClient } from '@tanstack/react-query';

const library = {
Expand Down Expand Up @@ -98,7 +96,7 @@ export default function Home() {

const queryClient = useQueryClient();

queryClient.setQueryData([SIGNING_CLIENT_QUERY_KEY], signingClient);
queryClient.setQueryData([DEFAULT_SIGNING_CLIENT_QUERY_KEY], signingClient);

const [resp, setResp] = useState('');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,7 @@
import { Rpc } from "../../../helpers";
import { BinaryReader, BinaryWriter } from "../../../binary";
import { QueryClient, createProtobufRpcClient, ProtobufRpcClient } from "@cosmjs/stargate";
import { ReactQueryParams, RPC_CLIENT_QUERY_KEY } from "../../../react-query";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { QueryStore } from "../../../mobx";
import { buildQuery, Rpc } from "../../../helpers";
import { UseQueryParams, buildUseQuery } from "../../../react-query";
import { QueryBalanceRequest, QueryBalanceResponse, QueryAllBalancesRequest, QueryAllBalancesResponse, QuerySpendableBalancesRequest, QuerySpendableBalancesResponse, QueryTotalSupplyRequest, QueryTotalSupplyResponse, QuerySupplyOfRequest, QuerySupplyOfResponse, QueryParamsRequest, QueryParamsResponse, QueryDenomMetadataRequest, QueryDenomMetadataResponse, QueryDenomsMetadataRequest, QueryDenomsMetadataResponse, QueryDenomOwnersRequest, QueryDenomOwnersResponse } from "./query";

// common utils

export interface QueryBuilderOptions<TReq, TRes> {
reqEncoderFn: (request: TReq, writer?: BinaryWriter) => BinaryWriter
resDecoderFn: (input: BinaryReader | Uint8Array, length?: number) => TRes
service: string,
method: string,
getRpcInstance: () => Rpc | undefined
}

export interface UseQueryBuilderOptions<TReq, TRes> {
builderQueryFn: (getRpcInstance: () => Rpc | undefined) => (request: TReq) => Promise<TRes>,
queryKeyPrefix: string
}

export function buildQuery<TReq, TRes>(opts: QueryBuilderOptions<TReq, TRes>) {
return async (request: TReq) => {
const rpc = opts.getRpcInstance();

if (!rpc) throw new Error("Query Rpc is not initialized");

const data = opts.reqEncoderFn(request).finish();
const response = await rpc.request(opts.service, opts.method, data);
return opts.resDecoderFn(new BinaryReader(response));
};
}

export function buildUseQuery<TReq, TRes>(opts: UseQueryBuilderOptions<TReq, TRes>) {
return <TData = TRes>({
request,
options,
rpcEndpoint
}: UseQueryParams<TReq, TRes, TData>) => {
const queryClient = useQueryClient();
const queryKey = rpcEndpoint ? [RPC_CLIENT_QUERY_KEY, rpcEndpoint] : [RPC_CLIENT_QUERY_KEY];
const rpc = queryClient.getQueryData<Rpc>(queryKey);
const queryFn = opts.builderQueryFn(()=>{
return rpc;
});
return useQuery<TRes, Error, TData>([opts.queryKeyPrefix, request], () => queryFn(request), options);
};
}

export interface UseQueryParams<TReq, TRes, TData = TRes> extends ReactQueryParams<TRes, TData> {
request: TReq;
}

// generated helper functions

export type UseBalanceQuery = UseQueryParams<QueryBalanceRequest, QueryBalanceResponse>;
Expand Down
108 changes: 3 additions & 105 deletions examples/interchainjs/src/codegen/cosmos/bank/v1beta1/tx.rpc.func.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,7 @@
import { Rpc } from "../../../helpers";
import { BinaryReader } from "../../../binary";
import { MsgSend, MsgSendResponse, MsgMultiSend, MsgMultiSendResponse } from "./tx";
import { DeliverTxResponse, StdFee } from '@interchainjs/cosmos-types/types';
import { AminoConverter, Encoder, Message } from '@interchainjs/cosmos/types/signer';
import { SigningClient } from "interchainjs/signing-client";
import { MutationOptions, useMutation, UseMutationOptions, useQueryClient } from "@tanstack/react-query";
import { HttpEndpoint } from "@cosmjs/stargate";
import { buildTx, ISigningClient } from "../../../helpers";
import { MsgSend, MsgMultiSend } from "./tx";
import { toConverters, toEncoders } from "@interchainjs/cosmos/utils";

// common utils
export const SIGNING_CLIENT_QUERY_KEY = 'signingClient';

export interface ITxArgs<TMsg> {
signerAddress: string;
message: TMsg;
fee: StdFee | 'auto';
memo: string;
}

export interface ISigningClient {
/**
* register converters
*/
addConverters: (converters: AminoConverter[]) => void;
/**
* register encoders
*/
addEncoders: (encoders: Encoder[]) => void;

signAndBroadcast: (
signerAddress: string,
message: Message[],
fee: StdFee | 'auto',
memo: string
) => Promise<DeliverTxResponse>;
}

export interface ReactMutationParams<TData, TError, TVariables, TContext = unknown> {
options?: MutationOptions<TData, TError, TVariables, TContext>;
rpcEndpoint?: string | HttpEndpoint;
signingClientQueryKey?: string;
}

export interface TxBuilderOptions {
getSigningClient: () => ISigningClient | undefined,
typeUrl: string,
encoders?: Encoder[],
converters?: AminoConverter[],
}

export interface UseMutationBuilderOptions<TMsg> {
builderMutationFn: (getSigningClientInstance: () => ISigningClient | undefined) => (
signerAddress: string,
message: TMsg,
fee: StdFee | 'auto',
memo: string
) => Promise<DeliverTxResponse>,
}

export function buildTx<TMsg>(opts: TxBuilderOptions) {
return async (
signerAddress: string,
message: TMsg,
fee: StdFee | 'auto',
memo: string
): Promise<DeliverTxResponse> => {
const client = opts.getSigningClient();

if (!client) throw new Error("SigningClient is not initialized");

//register all related encoders and converters
client.addEncoders(opts.encoders ?? []);
client.addConverters(opts.converters ?? []);

const data = [
{
typeUrl: opts.typeUrl,
value: message,
},
];
return client.signAndBroadcast!(signerAddress, data, fee, memo);
};
}

export function buildUseMutation<TMsg, TError>(opts: UseMutationBuilderOptions<TMsg>) {
return ({
options,
rpcEndpoint,
signingClientQueryKey
}: ReactMutationParams<DeliverTxResponse, TError, ITxArgs<TMsg>>) => {
const queryClient = useQueryClient();
const key = signingClientQueryKey || SIGNING_CLIENT_QUERY_KEY;
const queryKey = rpcEndpoint ? [key, rpcEndpoint] : [SIGNING_CLIENT_QUERY_KEY];
const signingClient = queryClient.getQueryData<ISigningClient>(queryKey);

const mutationFn = opts.builderMutationFn(() => {
return signingClient;
});

return useMutation<DeliverTxResponse, Error, ITxArgs<TMsg>>(
(reqData: ITxArgs<TMsg>) => mutationFn(reqData.signerAddress, reqData.message, reqData.fee, reqData.memo),
options as Omit<UseMutationOptions<DeliverTxResponse, Error, ITxArgs<TMsg>, unknown>, "mutationFn">
);
};
}
import { buildUseMutation } from "../../../react-query";

// generated helper functions

Expand Down
81 changes: 81 additions & 0 deletions examples/interchainjs/src/codegen/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
* and run the transpile command or yarn proto command to regenerate this bundle.
*/

import { BinaryReader, BinaryWriter } from "./binary";
import { StdFee, DeliverTxResponse } from '@interchainjs/cosmos-types/types';
import { AminoConverter, Encoder, Message } from '@interchainjs/cosmos/types/signer';


declare var self: any | undefined;
declare var window: any | undefined;
Expand Down Expand Up @@ -255,3 +259,80 @@ export function fromJsonTimestamp(o: any): Timestamp {
function numberToLong(number: number) {
return BigInt(number);
}

export interface QueryBuilderOptions<TReq, TRes> {
reqEncoderFn: (request: TReq, writer?: BinaryWriter) => BinaryWriter
resDecoderFn: (input: BinaryReader | Uint8Array, length?: number) => TRes
service: string,
method: string,
getRpcInstance: () => Rpc | undefined
}

export function buildQuery<TReq, TRes>(opts: QueryBuilderOptions<TReq, TRes>) {
return async (request: TReq) => {
const rpc = opts.getRpcInstance();

if (!rpc) throw new Error("Query Rpc is not initialized");

const data = opts.reqEncoderFn(request).finish();
const response = await rpc.request(opts.service, opts.method, data);
return opts.resDecoderFn(new BinaryReader(response));
};
}

export interface ITxArgs<TMsg> {
signerAddress: string;
message: TMsg;
fee: StdFee | 'auto';
memo: string;
}

export interface ISigningClient {
/**
* register converters
*/
addConverters: (converters: AminoConverter[]) => void;
/**
* register encoders
*/
addEncoders: (encoders: Encoder[]) => void;

signAndBroadcast: (
signerAddress: string,
message: Message[],
fee: StdFee | 'auto',
memo: string
) => Promise<DeliverTxResponse>;
}

export interface TxBuilderOptions {
getSigningClient: () => ISigningClient | undefined,
typeUrl: string,
encoders?: Encoder[],
converters?: AminoConverter[],
}

export function buildTx<TMsg>(opts: TxBuilderOptions) {
return async (
signerAddress: string,
message: TMsg,
fee: StdFee | 'auto',
memo: string
): Promise<DeliverTxResponse> => {
const client = opts.getSigningClient();

if (!client) throw new Error("SigningClient is not initialized");

//register all related encoders and converters
client.addEncoders(opts.encoders ?? []);
client.addConverters(opts.converters ?? []);

const data = [
{
typeUrl: opts.typeUrl,
value: message,
},
];
return client.signAndBroadcast!(signerAddress, data, fee, memo);
};
}
Loading
Loading