Skip to content

feat: add pre-flight tools — get_account_info, simulate_transaction,get_order_book, find_payment_paths#34

Open
rue19 wants to merge 1 commit intoStellar-Tools:mainfrom
rue19:feat/preflight-tools
Open

feat: add pre-flight tools — get_account_info, simulate_transaction,get_order_book, find_payment_paths#34
rue19 wants to merge 1 commit intoStellar-Tools:mainfrom
rue19:feat/preflight-tools

Conversation

@rue19
Copy link
Copy Markdown

@rue19 rue19 commented Mar 24, 2026

feat: add pre-flight tools — get_account_info, simulate_transaction, get_order_book, find_payment_paths

Summary

This PR adds four new LangChain DynamicStructuredTool implementations to fill a critical gap in the agent's pre-flight reasoning capability. Currently the SDK focuses on execution (swap, bridge, LP deposit) but lacks read-only inspection tools that an agent must use before committing to any transaction. Without these, the agent cannot reason about whether an account exists, whether it has the right trustlines, what the current market price is, or whether a contract call will succeed — so it flies blind into every operation.

These four tools solve exactly that.


Files Changed

File Description
tools/getAccountInfo.ts New tool: load on-chain account state
tools/simulateTransaction.ts New tool: dry-run via Soroban RPC
tools/getOrderBook.ts New tool: DEX order book query
tools/findPaymentPaths.ts New tool: Horizon path-finding (strict send/receive)
tools/index.ts Updated barrel export
tests/tools.test.ts Jest unit tests for all four tools

Tool Details

1. get_account_info

File: tools/getAccountInfo.ts

Wraps Horizon.Server.loadAccount() into an agent-friendly tool. Returns:

  • All balances (native XLM, issued tokens, LP shares) with liabilities
  • Sequence number (needed for building transactions)
  • Subentry count, sponsors, signers, thresholds, flags
  • home_domain and last_modified_ledger

Why it matters: Before any swap or payment, the agent needs to confirm the account is funded, has the right trustlines, and isn't at its subentry limit. This makes that check explicit and automatic.

Input validation: Validates the public key via StellarSdk.Keypair.fromPublicKey before any network call, returning a clean error message for bad keys instead of an unhandled HTTP 400.


2. simulate_transaction

File: tools/simulateTransaction.ts

Wraps SorobanRpc.Server.simulateTransaction() — the Soroban dry-run endpoint. Returns:

  • Estimated fee breakdown (minResourceFee + base fee = recommended total)
  • Resource usage: CPU instructions, read/write bytes, footprint entry counts
  • Auth entries required (as base64 XDR) and count
  • Return value from contract invocation
  • Emitted contract events
  • Restore preamble if ledger entries are archived (instead of cryptically failing)

Why it matters: Every Soroban operation (contract invoke, LP interaction) should be simulated before submission. Without simulation, the agent wastes sequence numbers on transactions that fail at the network level, and has no way to know the correct fee. This tool makes simulation a first-class operation in the agent loop.

Error handling covers:

  • XDR parse failure (bad input)
  • isSimulationError — surfaces the contract error string
  • isSimulationRestore — explains the archived entry problem and returns the restore preamble XDR
  • RPC network errors

3. get_order_book

File: tools/getOrderBook.ts

Queries the Stellar DEX order book via Horizon.Server.orderbook(). Returns:

  • Top N bids and asks (configurable, 1–20 levels)
  • Mid-price, absolute spread, and spread in basis points
  • Total bid-side and ask-side liquidity depth

Why it matters: Before a swap, the agent needs market context. Without knowing the current price and spread, it cannot reason about slippage, set a sensible minimum output, or decide whether the market has enough depth. This gives the agent that context in a single structured call.


4. find_payment_paths

File: tools/findPaymentPaths.ts

Wraps Horizon's strictSendPaths / strictReceivePaths endpoints. Returns:

  • All available DEX paths ranked by best rate
  • Source amount, destination amount, and intermediate asset hops for each path
  • Whether each path is direct or multi-hop
  • The best path highlighted at the top level

Why it matters: Stellar's path-payment operations are one of its most powerful primitives — they allow atomic multi-hop conversions. But the agent can only use them effectively if it knows which paths exist and what rate to expect. This tool exposes that data in a structured, agent-readable format and validates both strict-send and strict-receive modes.


Design Decisions

All tools return structured JSON strings. LangChain's DynamicStructuredTool passes tool outputs back to the LLM as strings, so every return value is JSON.stringify-ed. This makes parsing unambiguous and keeps the agent's reasoning grounded in structured data.

Input validation before network calls. Each tool validates its inputs (key format, asset codes, amounts, XDR parseability) before making any outbound request. This surfaces bad inputs as clean error objects rather than raw SDK exceptions.

Both networks supported. All tools accept network: "testnet" | "mainnet" with testnet as the default, matching the existing convention in the codebase.

No execution side effects. All four tools are strictly read-only. They do not build, sign, or submit any transaction. This makes them safe to call in any order and at any point in the agent loop.


Testing

npx jest --testPathPattern=tools.test.ts

Tests cover:

  • Tool name assertions (contract for the agent's tool registry)
  • Zod schema defaults and boundary validation (limit > 20, negative amounts)
  • Input validation paths that do not require network access (bad public key, invalid XDR, missing required field for strict_receive)

Network-dependent paths (actual Horizon/RPC responses) are left for integration tests to avoid flakiness in CI.


Checklist

  • All tools use DynamicStructuredTool with a full Zod schema
  • Supports testnet and mainnet
  • Input validation before network calls
  • Structured JSON return values
  • No side effects (read-only tools)
  • Exported from tools/index.ts
  • Unit tests added
  • TypeScript strict-mode compatible (no implicit any)

Summary by cubic

Add four read‑only preflight tools for Stellar agents: account inspection, transaction simulation, order book lookup, and payment path finding. These give the agent the data it needs to validate accounts, estimate fees, and choose safe routes before executing any transaction.

  • New Features
    • get_account_info: Fetch detailed account state (balances, sequence, signers, thresholds). Validates the G-address. Works on testnet and mainnet.
    • simulate_transaction: Dry-run a base64 XDR via Soroban RPC. Returns fee estimates, resource usage, auth entries, return value, and events. Handles simulation errors and restore preamble.
    • get_order_book: Query Horizon for a trading pair’s top N bids/asks (1–20). Returns mid-price, spread (bps), and side liquidity depth.
    • find_payment_paths: Discover strict-send/strict-receive DEX routes. Ranked paths with source/destination amounts and hops. Validates positive amounts and requires destinationAccount for strict_receive.

Exports added to stellarTools. All tools return structured JSON strings and have unit tests for schemas and input validation.

Written for commit 049f1cf. Summary will update on new commits.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="tools/findPaymentPaths.ts">

<violation number="1" location="tools/findPaymentPaths.ts:123">
P2: Amount pre-validation is too permissive (`parseFloat`), allowing malformed numeric strings to pass and reach Horizon calls.</violation>
</file>

<file name="tools/simulateTransaction.ts">

<violation number="1" location="tools/simulateTransaction.ts:89">
P2: Simulation-error branch returns raw event objects instead of serialized event strings, causing inconsistent `events` output shape versus success responses.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread tools/findPaymentPaths.ts
}

// Validate amount is a positive decimal
const parsedAmount = parseFloat(amount);
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Amount pre-validation is too permissive (parseFloat), allowing malformed numeric strings to pass and reach Horizon calls.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/findPaymentPaths.ts, line 123:

<comment>Amount pre-validation is too permissive (`parseFloat`), allowing malformed numeric strings to pass and reach Horizon calls.</comment>

<file context>
@@ -0,0 +1,212 @@
+    }
+
+    // Validate amount is a positive decimal
+    const parsedAmount = parseFloat(amount);
+    if (isNaN(parsedAmount) || parsedAmount <= 0) {
+      return JSON.stringify({
</file context>
Fix with Cubic

simulationFailed: true,
error: simResult.error,
// Attempt to extract a readable diagnostics message if present
events: simResult.events ?? [],
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Simulation-error branch returns raw event objects instead of serialized event strings, causing inconsistent events output shape versus success responses.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tools/simulateTransaction.ts, line 89:

<comment>Simulation-error branch returns raw event objects instead of serialized event strings, causing inconsistent `events` output shape versus success responses.</comment>

<file context>
@@ -0,0 +1,167 @@
+          simulationFailed: true,
+          error: simResult.error,
+          // Attempt to extract a readable diagnostics message if present
+          events: simResult.events ?? [],
+        });
+      }
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant