Skip to content

Commit

Permalink
add txpool_content RPC (#950)
Browse files Browse the repository at this point in the history
* add txpool_content RPC

* fix

* fix

* fix

* update
  • Loading branch information
shunjizhan authored Feb 28, 2024
1 parent 5ae06b4 commit 272e716
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
52 changes: 52 additions & 0 deletions packages/eth-providers/src/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,27 @@ export interface CallReturnInfo {
logs: Log[];
}

export interface PendingTx {
blockHash: string;
blockNumber: null;
from: string;
gas: string;
gasPrice: string;
hash: string;
input: string;
nonce: string;
to: string | null;
transactionIndex: null;
value: string;
v: string;
r: string;
s: string;
}
export interface TxpoolContent {
pending: { [from: string]: { [nonce: string]: PendingTx } };
queued: { [from: string]: { [nonce: string]: PendingTx } };
}

export abstract class BaseProvider extends AbstractProvider {
readonly _api?: ApiPromise;
readonly subql?: SubqlProvider;
Expand Down Expand Up @@ -2070,6 +2091,37 @@ export abstract class BaseProvider extends AbstractProvider {
return found;
};

txpoolContent = async (): Promise<TxpoolContent> => {
const pendingExtrinsics = await this.api.rpc.author.pendingExtrinsics();
const pendingTxs = await Promise.all(pendingExtrinsics
.filter(isEvmExtrinsic)
.map(async extrinsic => {
const from = await this.getEvmAddress(extrinsic.signer.toString());

return {
blockHash: null,
blockNumber: null,
from,
gasPrice: 0, // hard to calculate
hash: extrinsic.hash.toHex(),
transactionIndex: null,
...parseExtrinsic(extrinsic),
};
}));

const pending = pendingTxs.reduce((res, tx) => {
res[tx.from] ??= {};
res[tx.from][tx.nonce] = hexlifyRpcResult(tx);

return res;
}, {} as TxpoolContent['pending']);

return {
pending,
queued: {},
};
};

on = (_eventName: EventType, _listener: Listener): Provider => throwNotImplemented('on');
once = (_eventName: EventType, _listener: Listener): Provider => throwNotImplemented('once');
emit = (_eventName: EventType, ..._args: Array<any>): boolean => throwNotImplemented('emit');
Expand Down
5 changes: 2 additions & 3 deletions packages/eth-providers/src/utils/receiptHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { TX } from '../base-provider';
import { TransactionReceipt as TransactionReceiptSubql } from './gqlTypes';
import { hexToU8a, nToU8a } from '@polkadot/util';
import { hexValue } from '@ethersproject/bytes';
import { isOrphanEvmEvent } from './utils';
import { isEvmExtrinsic, isOrphanEvmEvent } from './utils';
import { keccak256 } from '@ethersproject/keccak256';
import { logger } from './logger';
import type { EventRecord, SignedBlock } from '@polkadot/types/interfaces';
Expand Down Expand Up @@ -176,7 +176,6 @@ export const findEvmEvent = (events: EventRecord[]): EventRecord | undefined =>
};

// parse info that can be extracted from extrinsic alone
// only works for EVM extrinsics
export const parseExtrinsic = (
extrinsic: GenericExtrinsic
): {
Expand All @@ -200,7 +199,7 @@ export const parseExtrinsic = (
...DUMMY_V_R_S, // TODO: get correct VRS
};

if (extrinsic.method.section.toUpperCase() !== 'EVM') {
if (!isEvmExtrinsic(extrinsic)){
return NONE_EVM_TX_DEFAULT_DATA;
}

Expand Down
7 changes: 6 additions & 1 deletion packages/eth-rpc-adapter/src/eip1193-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class Eip1193Bridge extends EventEmitter {
}

isMethodValid(method: string): boolean {
return method.startsWith('eth_') || method.startsWith('net_') || method.startsWith('web3_');
return method.startsWith('eth_') || method.startsWith('net_') || method.startsWith('web3_') || method.startsWith('txpool_');
}

isMethodImplemented(method: string): method is keyof Eip1193BridgeImpl {
Expand Down Expand Up @@ -495,4 +495,9 @@ class Eip1193BridgeImpl {

return this.#provider.removeEventListener(params[0]);
}

async txpool_content(params: any[]): Promise<any> {
validate([], params);
return this.#provider.txpoolContent();
}
}

0 comments on commit 272e716

Please sign in to comment.