Skip to content

Commit

Permalink
add broadcast options
Browse files Browse the repository at this point in the history
  • Loading branch information
Zetazzz committed Aug 18, 2024
1 parent fdf15d1 commit 3686190
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 195 deletions.
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@
"cwd": "${workspaceFolder}/libs/interchainjs",
"internalConsoleOptions": "neverOpen"
},
{
"type": "node",
"request": "launch",
"name": "Debug Jest Tests in Interchainjs gov",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": [
"--config",
"./jest.starship.config.js",
"--verbose",
"--bail",
"starship/__tests__/gov.test.ts"
],
"console": "integratedTerminal",
"cwd": "${workspaceFolder}/libs/interchainjs",
"internalConsoleOptions": "neverOpen"
},
{
"type": "node",
"request": "launch",
Expand Down
152 changes: 49 additions & 103 deletions libs/interchainjs/src/signing-client.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
import { AminoSigner } from '@interchainjs/cosmos/amino';
import { DirectSigner } from '@interchainjs/cosmos/direct';
import { RpcClient } from '@interchainjs/cosmos/query/rpc';
import { AminoSigner } from "@interchainjs/cosmos/amino";
import { DirectSigner } from "@interchainjs/cosmos/direct";
import { RpcClient } from "@interchainjs/cosmos/query/rpc";
import {
AminoConverter,
Encoder,
isICosmosAccount,
QueryClient,
} from '@interchainjs/cosmos/types';
} from "@interchainjs/cosmos/types";
import {
isOfflineAminoSigner,
isOfflineDirectSigner,
OfflineSigner,
} from '@interchainjs/cosmos/types/wallet';
import { toEncoder } from '@interchainjs/cosmos/utils';
import { IBinaryWriter } from '@interchainjs/cosmos-types/binary';
import { PubKey as Secp256k1PubKey } from '@interchainjs/cosmos-types/cosmos/crypto/secp256k1/keys';
import { TxBody, TxRaw } from '@interchainjs/cosmos-types/cosmos/tx/v1beta1/tx';
import { Any } from '@interchainjs/cosmos-types/google/protobuf/any';
import { TxRpc } from '@interchainjs/cosmos-types/types';
import {
AccountData,
HttpEndpoint,
IKey,
Price,
StdFee,
} from '@interchainjs/types';
import { fromBase64 } from '@interchainjs/utils';
} from "@interchainjs/cosmos/types/wallet";
import { toEncoder } from "@interchainjs/cosmos/utils";
import { IBinaryWriter } from "@interchainjs/cosmos-types/binary";
import { PubKey as Secp256k1PubKey } from "@interchainjs/cosmos-types/cosmos/crypto/secp256k1/keys";
import { TxBody, TxRaw } from "@interchainjs/cosmos-types/cosmos/tx/v1beta1/tx";
import { Any } from "@interchainjs/cosmos-types/google/protobuf/any";
import { TxRpc } from "@interchainjs/cosmos-types/types";
import { BroadcastOptions, HttpEndpoint, IKey, StdFee } from "@interchainjs/types";
import { fromBase64 } from "@interchainjs/utils";

import {
Block,
Expand All @@ -34,13 +28,13 @@ import {
SearchTxQuery,
SearchTxResponse,
TxResponse,
} from './types/query';
} from "./types/query";
import {
DeliverTxResponse,
EncodeObject,
SignerOptions,
} from './types/signing-client';
import { BroadcastTxError } from './utils';
} from "./types/signing-client";
import { BroadcastTxError } from "./utils";

/**
* implement the same methods as what in `cosmjs` signingClient
Expand All @@ -58,9 +52,6 @@ export class SigningClient {
readonly encoders: Encoder[] = [];
readonly converters: AminoConverter[] = [];

private readonly gasPrice?: Price | string;

private _endpoint: string | HttpEndpoint;
protected txRpc: TxRpc;

constructor(
Expand All @@ -78,7 +69,7 @@ export class SigningClient {

this.txRpc = {
request(): Promise<Uint8Array> {
throw new Error('Not implemented yet');
throw new Error("Not implemented yet");
},
signAndBroadcast: this.signAndBroadcast,
};
Expand Down Expand Up @@ -140,44 +131,6 @@ export class SigningClient {
}
}

private async getAccountData(address: string): Promise<AccountData> {
const accounts = await this.offlineSigner.getAccounts();
const account = accounts.find((account) => account.address === address);
if (!account) {
throw new Error(
`No such account found in OfflineSigner for address ${address}`
);
}

return isICosmosAccount(account) ? account.toAccountData() : account;
}

private async getPubkey(address: string): Promise<Any> {
const account = await this.getAccountData(address);
let typeUrl: string;
let PubKey: {
encode(
message: { key: Uint8Array },
writer?: IBinaryWriter
): IBinaryWriter;
};
switch (account.algo) {
case 'secp256k1':
typeUrl = Secp256k1PubKey.typeUrl;
PubKey = Secp256k1PubKey;
break;
default:
throw new Error(`${account.algo} not supported.`);
}
const publicKey: Any = {
typeUrl,
value: PubKey.encode({
key: account.pubkey,
}).finish(),
};
return publicKey;
}

private get queryClient() {
return this.client;
}
Expand Down Expand Up @@ -225,10 +178,10 @@ export class SigningClient {
private signWithAutoFee = async (
signerAddress: string,
messages: EncodeObject[],
fee: StdFee | 'auto',
memo = ''
fee: StdFee | "auto",
memo = ""
): Promise<TxRaw> => {
const usedFee = fee === 'auto' ? undefined : fee;
const usedFee = fee === "auto" ? undefined : fee;
return await this.sign(signerAddress, messages, usedFee, memo);
};

Expand Down Expand Up @@ -257,7 +210,7 @@ export class SigningClient {
return Promise.reject(
new BroadcastTxError(
broadcasted.check_tx?.code,
broadcasted.check_tx?.codespace ?? '',
broadcasted.check_tx?.codespace ?? "",
broadcasted.check_tx?.log
)
);
Expand All @@ -269,8 +222,8 @@ export class SigningClient {
public async signAndBroadcastSync(
signerAddress: string,
messages: EncodeObject[],
fee: StdFee | 'auto',
memo = ''
fee: StdFee | "auto",
memo = ""
): Promise<string> {
const txRaw = await this.signWithAutoFee(
signerAddress,
Expand All @@ -284,34 +237,28 @@ export class SigningClient {

public async broadcastTx(
tx: Uint8Array,
timeoutMs = 60_000,
pollIntervalMs = 3_000
broadcast: BroadcastOptions
): Promise<DeliverTxResponse> {
const resp = await this.queryClient.broadcast(tx, {
checkTx: true,
deliverTx: true,
timeoutMs,
pollIntervalMs,
});
const resp = await this.queryClient.broadcast(tx, broadcast);

return {
height: Number(resp.deliver_tx.height),
txIndex: resp.deliver_tx.txIndex,
code: resp.deliver_tx.code,
transactionHash: resp.hash,
events: resp.deliver_tx.events,
rawLog: resp.deliver_tx.rawLog,
msgResponses: resp.deliver_tx.msgResponses,
gasUsed: BigInt(resp.deliver_tx.gas_used),
gasWanted: BigInt(resp.deliver_tx.gas_wanted),
height: resp?.deliver_tx?.height ? Number(resp.deliver_tx.height) : 0,
txIndex: resp?.deliver_tx?.txIndex,
code: resp?.deliver_tx?.code,
transactionHash: resp?.hash,
events: resp?.deliver_tx?.events,
rawLog: resp?.deliver_tx?.rawLog,
msgResponses: resp?.deliver_tx?.msgResponses,
gasUsed: BigInt(resp?.deliver_tx?.gas_used ?? 0),
gasWanted: BigInt(resp?.deliver_tx?.gas_wanted ?? 0),
};
}

signAndBroadcast = async (
signerAddress: string,
messages: EncodeObject[],
fee: StdFee | 'auto',
memo = ''
fee: StdFee | "auto",
memo = ""
): Promise<DeliverTxResponse> => {
const txRaw = await this.signWithAutoFee(
signerAddress,
Expand All @@ -322,8 +269,7 @@ export class SigningClient {
const txBytes = TxRaw.encode(txRaw).finish();
return this.broadcastTx(
txBytes,
this.options.broadcastTimeoutMs,
this.options.broadcastPollIntervalMs
this.options.broadcast,
);
};

Expand All @@ -334,7 +280,7 @@ export class SigningClient {
async getTx(id: string): Promise<IndexedTx | null> {
const data = await fetch(`${this.endpoint.url}/tx?hash=0x${id}`);
const json = await data.json();
const tx: TxResponse = json['result'];
const tx: TxResponse = json["result"];
if (!tx) return null;
const txRaw = TxRaw.decode(fromBase64(tx.tx));
const txBody = TxBody.decode(txRaw.bodyBytes);
Expand All @@ -347,28 +293,28 @@ export class SigningClient {
rawLog: tx.tx_result.log,
tx: fromBase64(tx.tx),
msgResponses: txBody.messages,
gasUsed: BigInt(tx.tx_result.gas_used),
gasWanted: BigInt(tx.tx_result.gas_wanted),
gasUsed: tx?.tx_result?.gas_used ? BigInt(tx?.tx_result?.gas_used) : 0n,
gasWanted: tx?.tx_result?.gas_wanted ? BigInt(tx?.tx_result?.gas_wanted) : 0n,
};
}

async searchTx(query: SearchTxQuery): Promise<IndexedTx[]> {
let rawQuery: string;
if (typeof query === 'string') {
if (typeof query === "string") {
rawQuery = query;
} else if (Array.isArray(query)) {
rawQuery = query.map((t) => `${t.key}=${t.value}`).join(' AND ');
rawQuery = query.map((t) => `${t.key}=${t.value}`).join(" AND ");
} else {
throw new Error('Got unsupported query type.');
throw new Error("Got unsupported query type.");
}
const orderBy: 'asc' | 'desc' = 'asc';
const orderBy: "asc" | "desc" = "asc";
const data = await fetch(
`${this.endpoint.url}/tx_search?query="${rawQuery}"&order_by="${orderBy}"`
// `${this.endpoint.url}/tx_search?query="${rawQuery}"&order_by="${orderBy}"&page=1&per_page=100`
);
const json = await data.json();

const { txs }: SearchTxResponse = json['result'];
const { txs }: SearchTxResponse = json["result"];
return txs.map((tx) => {
return {
height: Number.parseInt(tx.height),
Expand All @@ -377,11 +323,11 @@ export class SigningClient {
code: 0,
// events: tx.tx_result.tags,
events: [],
rawLog: tx.tx_result.log || '',
rawLog: tx.tx_result.log || "",
tx: fromBase64(tx.tx),
msgResponses: [],
gasUsed: BigInt(tx.tx_result.gas_used),
gasWanted: BigInt(tx.tx_result.gas_wanted),
gasUsed: tx?.tx_result?.gas_used ? BigInt(tx.tx_result.gas_used) : 0n,
gasWanted: tx?.tx_result?.gas_wanted ? BigInt(tx.tx_result.gas_wanted) : 0n,
} as IndexedTx;
});
}
Expand All @@ -393,7 +339,7 @@ export class SigningClient {
: `${this.endpoint.url}/block`
);
const json = await data.json();
const { block_id, block }: BlockResponse = json['result'];
const { block_id, block }: BlockResponse = json["result"];
return {
id: block_id.hash.toUpperCase(),
header: {
Expand Down
5 changes: 2 additions & 3 deletions libs/interchainjs/src/types/signing-client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AminoConverter, Message } from '@interchainjs/cosmos/types';
import { Price } from '@interchainjs/types';
import { BroadcastOptions, Price } from '@interchainjs/types';
import { Event, TelescopeGeneratedType } from '@interchainjs/types';

export type EncodeObject = Message;
Expand All @@ -11,10 +11,9 @@ export type Registry = Array<[TypeUrl, TelescopeGeneratedType<any, any, any>]>;
export interface SignerOptions {
registry?: Registry;
aminoConverters?: Record<TypeUrl, AminoConverter>;
broadcastTimeoutMs?: number;
broadcastPollIntervalMs?: number;
gasPrice?: Price | string;
prefix?: string;
broadcast?: BroadcastOptions;
}

export interface SignerData {
Expand Down
36 changes: 32 additions & 4 deletions libs/interchainjs/starship/__tests__/gov.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,14 @@ describe('Governance tests for osmosis', () => {
it('stake tokens to genesis validator', async () => {
const signingClient = await StargateSigningClient.connectWithSigner(
await getRpcEndpoint(),
directSigner
directSigner,
{
broadcast: {
checkTx: true,
deliverTx: true,
useLegacyBroadcastTxCommit: true,
},
}
);

const { balance } = await queryClient.balance({
Expand Down Expand Up @@ -155,7 +162,14 @@ describe('Governance tests for osmosis', () => {
it('submit a txt proposal', async () => {
const signingClient = await StargateSigningClient.connectWithSigner(
await getRpcEndpoint(),
directSigner
directSigner,
{
broadcast: {
checkTx: true,
deliverTx: true,
useLegacyBroadcastTxCommit: true,
},
}
);

const contentMsg = TextProposal.fromPartial({
Expand Down Expand Up @@ -223,7 +237,14 @@ describe('Governance tests for osmosis', () => {
// create direct address signing client
const signingClient = await StargateSigningClient.connectWithSigner(
await getRpcEndpoint(),
directSigner
directSigner,
{
broadcast: {
checkTx: true,
deliverTx: true,
useLegacyBroadcastTxCommit: true,
},
}
);

// Vote on proposal from genesis mnemonic address
Expand Down Expand Up @@ -269,7 +290,14 @@ describe('Governance tests for osmosis', () => {
// create amino address signing client
const signingClient = await StargateSigningClient.connectWithSigner(
await getRpcEndpoint(),
aminoSigner
aminoSigner,
{
broadcast: {
checkTx: true,
deliverTx: true,
useLegacyBroadcastTxCommit: true,
},
}
);

// Vote on proposal from genesis mnemonic address
Expand Down
Loading

0 comments on commit 3686190

Please sign in to comment.