Credits: reserve live campaign budgets so purchased credits can't be over-committed; burner dry-runs and skips reverting burns; coaching flags directs not bound to you on-chain
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ const fs = require('fs');
|
||||
|
||||
let chain = null, ads = null;
|
||||
const ABI = ['function consume(uint32 memberId_, uint8 creditType, uint256 amount, bytes32 campaignRef)', 'function engineSigner() view returns (address)'];
|
||||
const state = { enabled: false, address: null, signer: null, balanceWei: '0', lastRun: 0, lastError: null, burned: 0, lastTx: null, mismatch: false };
|
||||
const state = { enabled: false, address: null, signer: null, balanceWei: '0', lastRun: 0, lastError: null, burned: 0, lastTx: null, mismatch: false, skipped: {} };
|
||||
let running = false;
|
||||
|
||||
function keyHex() {
|
||||
@@ -53,6 +53,10 @@ async function tick() {
|
||||
try {
|
||||
// Polygon nodes reject low priority fees and some public RPCs answer fee
|
||||
// queries with 500s: set the fees ourselves from the server's estimate
|
||||
// dry-run first: a revert here (usually "Insufficient credits", the member's on-chain
|
||||
// balance is below what the engine metered) costs no gas and is left for the admin
|
||||
try { await ctr.consume.staticCall(Number(b.memberId), 0, BigInt(b.amount), refToBytes32(b.ref)); }
|
||||
catch (e) { state.skipped[b.id] = String(e.reason || e.shortMessage || e.message).slice(0, 120); continue; }
|
||||
const g = await chain.suggestedFees();
|
||||
const overrides = { gasLimit: 120000n, maxPriorityFeePerGas: BigInt(g.maxPriorityFeePerGas), maxFeePerGas: BigInt(g.maxFeePerGas) };
|
||||
const tx = await ctr.consume(Number(b.memberId), 0, BigInt(b.amount), refToBytes32(b.ref), overrides);
|
||||
@@ -64,8 +68,8 @@ async function tick() {
|
||||
// a node error (500, timeout, rate limit): move to the next RPC for the next tick.
|
||||
// an "Insufficient credits" revert means the member's on-chain balance is
|
||||
// already lower than the engine thinks; leave it pending for the admin to review
|
||||
if (/server response|timeout|rate|429|503|502|500/i.test(String(e.message))) rotateRpc();
|
||||
break;
|
||||
if (/server response|timeout|rate|429|503|502|500/i.test(String(e.message))) { rotateRpc(); break; }
|
||||
state.skipped[b.id] = String(e.reason || e.shortMessage || e.message).slice(0, 120);
|
||||
}
|
||||
}
|
||||
} finally { running = false; }
|
||||
|
||||
Reference in New Issue
Block a user