Skip to content

Commit

Permalink
Refactor the sendTransaction signature thanks to @clockworkgr
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Sep 12, 2023
1 parent 57ae4c5 commit e6ebe6e
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 72 deletions.
7 changes: 4 additions & 3 deletions src/provider/jsonrpc/jsonrpc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { newResponse, stringToBase64, uint8ArrayToBase64 } from '../utility';
import { mock } from 'jest-mock-extended';
import { Tx } from '../../proto';
import { sha256 } from '@cosmjs/crypto';
import { CommonEndpoint } from '../endpoints';
import { CommonEndpoint, TransactionEndpoint } from '../endpoints';
import { UnauthorizedErrorMessage } from '../errors/messages';
import { TM2Error } from '../errors';

Expand Down Expand Up @@ -101,8 +101,9 @@ describe('JSON-RPC Provider', () => {
try {
// Create the provider
const provider = new JSONRPCProvider(mockURL);
const tx = await provider.sendTransaction<BroadcastTxSyncResult>(
'encoded tx'
const tx = await provider.sendTransaction(
'encoded tx',
TransactionEndpoint.BROADCAST_TX_SYNC
);

expect(axios.post).toHaveBeenCalled();
Expand Down
34 changes: 14 additions & 20 deletions src/provider/jsonrpc/jsonrpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {
ABCIResponse,
BlockInfo,
BlockResult,
BroadcastTransactionMap,
BroadcastTxCommitResult,
BroadcastTxSyncResult,
BroadcastType,
ConsensusParams,
NetworkInfo,
RPCRequest,
Expand Down Expand Up @@ -147,27 +147,21 @@ export class JSONRPCProvider implements Provider {
});
}

async sendTransaction<BroadcastTransactionResult>(
async sendTransaction<K extends keyof BroadcastTransactionMap>(
tx: string,
endpoint?: BroadcastType
): Promise<BroadcastTransactionResult> {
const queryEndpoint = endpoint
? endpoint
: TransactionEndpoint.BROADCAST_TX_SYNC;

const request: RPCRequest = newRequest(queryEndpoint, [tx]);

if (queryEndpoint == TransactionEndpoint.BROADCAST_TX_SYNC) {
return (await this.broadcastTxSync(
request
)) as BroadcastTransactionResult;
endpoint: K
): Promise<BroadcastTransactionMap[K]['result']> {
const request: RPCRequest = newRequest(endpoint, [tx]);

switch (endpoint) {
case TransactionEndpoint.BROADCAST_TX_COMMIT:
// The endpoint is a commit broadcast
// (it waits for the transaction to be committed) to the chain before returning
return this.broadcastTxCommit(request);
case TransactionEndpoint.BROADCAST_TX_SYNC:
default:
return this.broadcastTxSync(request);
}

// The endpoint is a commit broadcast
// (it waits for the transaction to be committed) to the chain before returning
return (await this.broadcastTxCommit(
request
)) as BroadcastTransactionResult;
}

private async broadcastTxSync(
Expand Down
17 changes: 9 additions & 8 deletions src/provider/provider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {
BlockInfo,
BlockResult,
BroadcastType,
BroadcastAsGeneric,
BroadcastTransactionMap,
ConsensusParams,
NetworkInfo,
Status,
Expand Down Expand Up @@ -93,17 +94,17 @@ export interface Provider {
// Transaction specific methods //

/**
* Sends the transaction to the node for committing.
* Sends the transaction to the node. If the type of endpoint
* is a broadcast commit, waits for the transaction to be committed to the chain.
* The transaction needs to be signed beforehand.
* Returns the transaction hash
* Returns the transaction broadcast result.
* @param {string} tx the base64-encoded signed transaction
* @param {BroadcastType} endpoint the transaction broadcast type (sync / commit).
* Defaults to broadcast_sync
* @param {BroadcastType} endpoint the transaction broadcast type (sync / commit)
*/
sendTransaction<BroadcastTransactionResult>(
sendTransaction<K extends keyof BroadcastTransactionMap>(
tx: string,
endpoint?: BroadcastType
): Promise<BroadcastTransactionResult>;
endpoint: K
): Promise<BroadcastAsGeneric<K>['result']>;

/**
* Waits for the transaction to be committed on the chain.
Expand Down
23 changes: 20 additions & 3 deletions src/provider/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,23 @@ export type BroadcastType =
| TransactionEndpoint.BROADCAST_TX_SYNC
| TransactionEndpoint.BROADCAST_TX_COMMIT;

export type BroadcastTransactionResult =
| BroadcastTxSyncResult
| BroadcastTxCommitResult;
export type BroadcastTransactionSync = {
endpoint: TransactionEndpoint.BROADCAST_TX_SYNC;
result: BroadcastTxSyncResult;
};

export type BroadcastTransactionCommit = {
endpoint: TransactionEndpoint.BROADCAST_TX_COMMIT;
result: BroadcastTxCommitResult;
};

export type BroadcastTransactionMap = {
[TransactionEndpoint.BROADCAST_TX_COMMIT]: BroadcastTransactionCommit;
[TransactionEndpoint.BROADCAST_TX_SYNC]: BroadcastTransactionSync;
};

export type BroadcastAsGeneric<
K extends keyof BroadcastTransactionMap = keyof BroadcastTransactionMap,
> = {
[P in K]: BroadcastTransactionMap[P];
}[K];
9 changes: 6 additions & 3 deletions src/provider/websocket/ws.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { WSProvider } from './ws';
import WS from 'jest-websocket-mock';
import { Tx } from '../../proto';
import { sha256 } from '@cosmjs/crypto';
import { CommonEndpoint } from '../endpoints';
import { CommonEndpoint, TransactionEndpoint } from '../endpoints';
import { UnauthorizedErrorMessage } from '../errors/messages';
import { TM2Error } from '../errors';

Expand Down Expand Up @@ -278,9 +278,12 @@ describe('WS Provider', () => {
await setHandler<BroadcastTxSyncResult>(response);

try {
const hash = await wsProvider.sendTransaction('encoded tx');
const tx = await wsProvider.sendTransaction(
'encoded tx',
TransactionEndpoint.BROADCAST_TX_SYNC
);

expect(hash).toEqual(expectedHash);
expect(tx.hash).toEqual(expectedHash);

if (expectedErr != '') {
fail('expected error');
Expand Down
46 changes: 22 additions & 24 deletions src/provider/websocket/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {
ABCIResponse,
BlockInfo,
BlockResult,
BroadcastTransactionMap,
BroadcastTxCommitResult,
BroadcastTxSyncResult,
BroadcastType,
ConsensusParams,
NetworkInfo,
RPCRequest,
Expand Down Expand Up @@ -258,30 +258,26 @@ export class WSProvider implements Provider {
return this.parseResponse<Status>(response);
}

async sendTransaction<BroadcastTransactionResult>(
async sendTransaction<K extends keyof BroadcastTransactionMap>(
tx: string,
endpoint?: BroadcastType
): Promise<BroadcastTransactionResult> {
const queryEndpoint = endpoint
? endpoint
: TransactionEndpoint.BROADCAST_TX_SYNC;

const request: RPCRequest = newRequest(queryEndpoint, [tx]);

if (queryEndpoint == TransactionEndpoint.BROADCAST_TX_SYNC) {
return (await this.broadcastTxSync(
request
)) as BroadcastTransactionResult;
endpoint: K
): Promise<BroadcastTransactionMap[K]['result']> {
const request: RPCRequest = newRequest(endpoint, [tx]);

switch (endpoint) {
case TransactionEndpoint.BROADCAST_TX_COMMIT:
// The endpoint is a commit broadcast
// (it waits for the transaction to be committed) to the chain before returning
return this.broadcastTxCommit(request);
case TransactionEndpoint.BROADCAST_TX_SYNC:
default:
return this.broadcastTxSync(request);
}

// The endpoint is a commit broadcast
// (it waits for the transaction to be committed) to the chain before returning
return (await this.broadcastTxCommit(
request
)) as BroadcastTransactionResult;
}

private async broadcastTxSync(request: RPCRequest): Promise<string> {
private async broadcastTxSync(
request: RPCRequest
): Promise<BroadcastTxSyncResult> {
const response: RPCResponse<BroadcastTxSyncResult> =
await this.sendRequest<BroadcastTxSyncResult>(request);

Expand All @@ -297,10 +293,12 @@ export class WSProvider implements Provider {
throw constructRequestError(errType, log);
}

return broadcastResponse.hash;
return broadcastResponse;
}

private async broadcastTxCommit(request: RPCRequest): Promise<string> {
private async broadcastTxCommit(
request: RPCRequest
): Promise<BroadcastTxCommitResult> {
const response: RPCResponse<BroadcastTxCommitResult> =
await this.sendRequest<BroadcastTxCommitResult>(request);

Expand All @@ -325,7 +323,7 @@ export class WSProvider implements Provider {
throw constructRequestError(errType, log);
}

return broadcastResponse.hash;
return broadcastResponse;
}

waitForTransaction(
Expand Down
13 changes: 10 additions & 3 deletions src/wallet/wallet.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { BroadcastTxSyncResult, JSONRPCProvider, Status } from '../provider';
import {
BroadcastTxSyncResult,
JSONRPCProvider,
Status,
TransactionEndpoint,
} from '../provider';
import { mock } from 'jest-mock-extended';
import { Wallet } from './wallet';
import { EnglishMnemonic, Secp256k1 } from '@cosmjs/crypto';
Expand Down Expand Up @@ -247,8 +252,10 @@ describe('Wallet', () => {
const wallet: Wallet = await Wallet.createRandom();
wallet.connect(mockProvider);

const tx: BroadcastTxSyncResult =
await wallet.sendTransaction<BroadcastTxSyncResult>(mockTx);
const tx: BroadcastTxSyncResult = await wallet.sendTransaction(
mockTx,
TransactionEndpoint.BROADCAST_TX_SYNC
);

expect(tx.hash).toBe(mockTxHash);
});
Expand Down
16 changes: 8 additions & 8 deletions src/wallet/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
BroadcastType,
BroadcastTransactionMap,
Provider,
Status,
uint8ArrayToBase64,
Expand Down Expand Up @@ -297,17 +297,17 @@ export class Wallet {
};

/**
* Encodes and sends the transaction.
* Encodes and sends the transaction. If the type of endpoint
* is a broadcast commit, waits for the transaction to be committed to the chain.
* The transaction needs to be signed beforehand.
* Returns the transaction hash (base-64)
* @param {Tx} tx the signed transaction
* @param {BroadcastType} endpoint the transaction broadcast type (sync / commit).
* Defaults to broadcast_sync
* @param {BroadcastType} endpoint the transaction broadcast type (sync / commit)
*/
sendTransaction = async <BroadcastTransactionResult>(
async sendTransaction<K extends keyof BroadcastTransactionMap>(
tx: Tx,
endpoint?: BroadcastType
): Promise<BroadcastTransactionResult> => {
endpoint: K
): Promise<BroadcastTransactionMap[K]['result']> {
if (!this.provider) {
throw new Error('provider not connected');
}
Expand All @@ -317,7 +317,7 @@ export class Wallet {

// Send the encoded transaction
return this.provider.sendTransaction(encodedTx, endpoint);
};
}

/**
* Returns the associated signer
Expand Down

0 comments on commit e6ebe6e

Please sign in to comment.