Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions sovereign-transaction-guard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

const { ethers } = require('ethers');

/**
* SovereignTransactionGuard
*
* Implements a Transactional State Machine to prevent nonce collisions
* and gas-limit hallucinations in high-concurrency AI agent environments.
*
* Part of the Sovereign Settlement architecture.
*/
class SovereignTransactionGuard {
constructor(provider, wallet) {
this.provider = provider;
this.wallet = wallet;
this.pendingNonces = new Map(); // nonce -> { tx, timestamp, status }
this.lock = false;
}

async acquireLock() {
while (this.lock) {
await new Promise(resolve => setTimeout(resolve, 100));
}
this.lock = true;
}

releaseLock() {
this.lock = false;
}

/**
* synchronizedSubmit
* Ensures atomic nonce increment and gas verification.
*/
async synchronizedSubmit(txRequest) {
await this.acquireLock();
try {
// 1. Nonce Synchronization
// Use the max of (on-chain nonce, local tracking nonce) to prevent collisions
const onChainNonce = await this.wallet.getNonce();
const trackedNonce = this.getLatestTrackedNonce();
const nonce = onChainNonce > trackedNonce ? onChainNonce : trackedNonce + 1;

// 2. Gas Hallucination Guard
// Agents often estimate gas poorly. We perform a strict dry-run and add a 20% safety buffer.
const estimatedGas = await this.provider.estimateGas({
...txRequest,
nonce: nonce
});

const gasLimit = (estimatedGas * 120n) / 100n; // 20% buffer

// 3. Transaction Construction
const tx = {
...txRequest,
nonce: nonce,
gasLimit: gasLimit
};

// 4. State Update
this.pendingNonces.set(nonce, {
tx,
timestamp: Date.now(),
status: 'pending'
});

// 5. Execution
const response = await this.wallet.sendTransaction(tx);

// Update status to confirmed
this.pendingNonces.set(nonce, { ...this.pendingNonces.get(nonce), status: 'confirmed' });

return response;
} catch (error) {
console.error('[SovereignGuard] Transaction Failure:', error);
throw error;
} finally {
this.releaseLock();
}
}

getLatestTrackedNonce() {
if (this.pendingNonces.size === 0) return -1;
return Math.max(...this.pendingNonces.keys());
}

/**
* recoverStaleNonces
* Cleans up nonces that never confirmed or were skipped.
*/
async recoverStaleNonces() {
await this.acquireLock();
const currentNonce = await this.wallet.getNonce();
for (const [nonce, data] of this.pendingNonces) {
if (nonce < currentNonce && data.status === 'pending') {
this.pendingNonces.delete(nonce);
}
}
this.releaseLock();
}
}

module.exports = { SovereignTransactionGuard };
Loading