Skip to content

Commit

Permalink
Start exactly _one_ transaction confirmer, and a separate send retry …
Browse files Browse the repository at this point in the history
…loop on the side
  • Loading branch information
steveluscher committed Oct 6, 2024
1 parent b0e5f51 commit ba8d65f
Showing 1 changed file with 32 additions and 28 deletions.
60 changes: 32 additions & 28 deletions ping-thing-client.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { safeRace } from "@solana/promises";
import {
createTransactionMessage,
pipe,
Expand All @@ -12,18 +11,20 @@ import {
isSolanaError,
getSignatureFromTransaction,
sendAndConfirmTransactionFactory,
sendTransactionWithoutConfirmingFactory,
// Address,
} from "@solana/web3.js";
import dotenv from "dotenv";
import bs58 from "bs58";
import { getSetComputeUnitLimitInstruction } from "@solana-program/compute-budget";
import { getTransferSolInstruction } from "@solana-program/system";
import { sleep, timeout } from "./utils/misc.mjs";
import { sleep } from "./utils/misc.mjs";
import { getLatestBlockhash } from "./utils/blockhash.mjs";
import { rpc, rpcSubscriptions } from "./utils/rpc.mjs";
import { getNextSlot } from "./utils/slot.mjs";
import { setMaxListeners } from "events";
import axios from "axios";
import { createRecentSignatureConfirmationPromiseFactory } from "@solana/transaction-confirmation";

dotenv.config();

Expand Down Expand Up @@ -58,10 +59,11 @@ const TX_RETRY_INTERVAL = 2000;

setMaxListeners(100);

const mSendAndConfirmTransaction = sendAndConfirmTransactionFactory({
const mConfirmRecentSignature = createRecentSignatureConfirmationPromiseFactory({
rpc,
rpcSubscriptions,
});
const mSendTransactionWithoutConfirming = sendTransactionWithoutConfirmingFactory({ rpc });

async function pingThing() {
USER_KEYPAIR = await createKeyPairFromBytes(
Expand Down Expand Up @@ -116,35 +118,37 @@ async function pingThing() {

console.log(`Sending ${signature}`);

while (true) {
try {
slotSent = await getNextSlot();

txStart = Date.now();

await safeRace([
mSendAndConfirmTransaction(transactionSignedWithFeePayer, {
commitment: "confirmed",
maxRetries: 0n,
skipPreflight: true,
}),
timeout(TX_RETRY_INTERVAL * txSendAttempts),
]);

console.log(`Confirmed tx ${signature}`);

break;
} catch (e) {
if (e.message === "Timeout") {
console.log(
`Tx not confirmed after ${TX_RETRY_INTERVAL * txSendAttempts++
}ms, resending`
);
let sendAbortController;
function sendTransaction() {
sendAbortController = new AbortController()
mSendTransactionWithoutConfirming(transactionSignedWithFeePayer, {
abortSignal: sendAbortController.signal,
commitment: COMMITMENT_LEVEL,
maxRetries: 0n,
skipPreflight: true,
}).catch(e => {
if (e instanceof Error && e.name === 'AbortError') {
return;
} else {
throw e;
}
}
});
}
const sendRetryInterval = setInterval(() => {
sendAbortController.abort();
console.log(`Tx not confirmed after ${TX_RETRY_INTERVAL * txSendAttempts++}ms, resending`);
sendTransaction();
}, TX_RETRY_INTERVAL);
slotSent = await getNextSlot();
txStart = Date.now();
sendTransaction();
await mConfirmRecentSignature({
abortSignal: AbortSignal.any([]),
commitment: COMMITMENT_LEVEL,
signature,
});
clearInterval(sendRetryInterval);
console.log(`Confirmed tx ${signature}`);
} catch (e) {
// Log and loop if we get a bad blockhash.
if (isSolanaError(e, SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND)) {
Expand Down

0 comments on commit ba8d65f

Please sign in to comment.