Skip to content

Instantly share code, notes, and snippets.

@halaprix
Created November 25, 2025 12:58
Show Gist options
  • Select an option

  • Save halaprix/ecb84a6c0f78869432f7981c28143297 to your computer and use it in GitHub Desktop.

Select an option

Save halaprix/ecb84a6c0f78869432f7981c28143297 to your computer and use it in GitHub Desktop.
#!/usr/bin/env node
import { createPublicClient, createWalletClient, http, parseAbi } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import {arbitrum} from 'viem/chains'
import dotenv from 'dotenv'
dotenv.config()
const sleepTime = process.env.SLEEP_TIME || 1000
const rpcUrl = process.env.ARBITRUM_RPC_URL
if (!rpcUrl) {
console.error('Set ARBITRUM_RPC_URL in your environment')
process.exit(1)
}
const privateKeyEnv = process.env.KEEPER_PRIVATE_KEY
if (!privateKeyEnv) {
console.error('Set KEEPER_PRIVATE_KEY in your environment')
process.exit(1)
}
const executorAddress = process.env.executorAddress
if (!executorAddress) {
console.error('Set executorAddress in your environment')
process.exit(1)
}
const account = privateKeyToAccount(
privateKeyEnv.startsWith('0x') ? privateKeyEnv : `0x${privateKeyEnv}`,
)
const publicClient = createPublicClient({ transport: http(rpcUrl), chain: arbitrum })
const walletClient = createWalletClient({ account, transport: http(rpcUrl), chain: arbitrum })
const EXECUTOR_ABI = parseAbi([
'function execute() returns (uint256 sharesBurned)',
])
async function submitExecuteOnce() {
try {
const {request} = await publicClient.simulateContract({
address: executorAddress,
abi: EXECUTOR_ABI,
functionName: 'execute',
account,
})
request.gas = 5000000
const serialized = await walletClient.signTransaction(request)
const hash = await walletClient.sendRawTransaction({ serializedTransaction: serialized })
const receipt = await publicClient.waitForTransactionReceipt({ hash })
console.log(`Mined in block ${receipt.blockNumber}`)
} catch (err) {
const isError = err instanceof Error
const message = isError ? err.message : String(err)
console.error(`\x1b[91mError submitting execute() ${message}`)
// Surface nested viem/BaseError details if available
const anyErr = /** @type {any} */ (err)
if (anyErr?.shortMessage) console.error(anyErr.shortMessage)
if (anyErr?.details) console.error(anyErr.details)
if (anyErr?.metaMessages) console.error(anyErr.metaMessages.join('\n'))
if (anyErr?.cause) {
if (anyErr.cause?.message) console.error(anyErr.cause.message)
if (anyErr.cause?.data) console.error(`cause.data: ${JSON.stringify(anyErr.cause.data)}`)
}
}
}
async function main() {
while (true) {
await submitExecuteOnce()
await new Promise((r) => setTimeout(r, sleepTime))
}
}
main().catch((e) => {
console.error(e)
process.exit(1)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment