Skip to content

Commit

Permalink
feat: implement tx spammer
Browse files Browse the repository at this point in the history
  • Loading branch information
macalinao committed May 20, 2022
1 parent 4e4b341 commit d776427
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
47 changes: 42 additions & 5 deletions packages/solana-contrib/src/broadcaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,51 @@ import { firstAggregateError } from "./error";
import type { Broadcaster } from "./interfaces";
import { DEFAULT_PROVIDER_OPTIONS } from "./provider";
import { PendingTransaction } from "./transaction";
import { suppressConsoleErrorAsync } from "./utils";
import { sleep, suppressConsoleErrorAsync } from "./utils";
import { simulateTransactionWithCommitment } from "./utils/simulateTransactionWithCommitment";

/**
* Sends and spams a raw transaction multiple times.
* @param connection Connection to send the transaction to. We recommend using a public endpoint such as GenesysGo.
* @param rawTx
* @param opts
*/
const sendAndSpamRawTx = async (
connection: Connection,
rawTx: Buffer,
{
retryTimes = 10,
...opts
}: SendOptions & Pick<BroadcastOptions, "retryTimes">
) => {
const result = await connection.sendRawTransaction(rawTx);
// if we could send the TX with preflight, let's spam it.
void (async () => {
// technique stolen from Mango.
for (let i = 0; i < retryTimes; i++) {
try {
await connection.sendRawTransaction(rawTx, {
...opts,
skipPreflight: true,
});
await sleep(300);
} catch (e) {
console.warn(`[Broadcaster] sendAndSpamRawTx error`, e);
}
}
})();
return result;
};

export interface BroadcastOptions extends ConfirmOptions {
/**
* Prints the transaction logs as emitted by @solana/web3.js. Defaults to true.
*/
printLogs?: boolean;
/**
* Number of times to retry the transaction being sent.
*/
retryTimes?: number;
}

/**
Expand Down Expand Up @@ -67,15 +104,15 @@ export class SingleConnectionBroadcaster implements Broadcaster {
if (printLogs) {
return new PendingTransaction(
this.sendConnection,
await this.sendConnection.sendRawTransaction(rawTx, opts)
await sendAndSpamRawTx(this.sendConnection, rawTx, opts)
);
}

return await suppressConsoleErrorAsync(async () => {
// hide the logs of TX errors if printLogs = false
return new PendingTransaction(
this.sendConnection,
await this.sendConnection.sendRawTransaction(rawTx, opts)
await sendAndSpamRawTx(this.sendConnection, rawTx, opts)
);
});
}
Expand Down Expand Up @@ -152,14 +189,14 @@ export class MultipleConnectionBroadcaster implements Broadcaster {

private async _sendRawTransaction(
encoded: Buffer,
options?: SendOptions
options?: SendOptions & Pick<BroadcastOptions, "retryTimes">
): Promise<PendingTransaction> {
try {
return await Promise.any(
this.connections.map(async (connection) => {
return new PendingTransaction(
connection,
await connection.sendRawTransaction(encoded, options)
await sendAndSpamRawTx(connection, encoded, options ?? {})
);
})
);
Expand Down
4 changes: 4 additions & 0 deletions packages/solana-contrib/src/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,7 @@ export const mapN = <T extends unknown[], U>(
})
);
};

export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}

0 comments on commit d776427

Please sign in to comment.