Skip to content

fix(tools): prevent import time crashes, correct result handling, and improve input validation#60

Closed
Div1912 wants to merge 4 commits into
Stellar-Tools:mainfrom
Div1912:main
Closed

fix(tools): prevent import time crashes, correct result handling, and improve input validation#60
Div1912 wants to merge 4 commits into
Stellar-Tools:mainfrom
Div1912:main

Conversation

@Div1912

@Div1912 Div1912 commented Apr 22, 2026

Copy link
Copy Markdown

What changed

Before:
Environment variables were read at module load time using const STELLAR_PUBLIC_KEY = process.env.STELLAR_PUBLIC_KEY!. This caused the entire module to crash on import in serverless/edge environments where env vars are not yet injected at parse time. The ! non-null assertion also suppressed TypeScript's safety check while a manual runtime guard was still needed, making the code contradictory.

deposit and swap used result ?? "success message" which meant the success string was only returned when the result was falsy — silently discarding actual transaction results on success.

buyA === undefined in the swap validation missed null, allowing invalid calls to pass through.

func was typed as any, defeating the Zod schema that was already defined on the tool.

contractAddress was always spread into config even when undefined, polluting the config object passed to contract functions.


After:
Environment variables are now read inside lazy getter functions (getStellarPublicKey, getStellarNetwork, getSorobanRpcUrl) that are called at invocation time, not import time. This makes the module safe to import in any environment.

deposit and swap now use a ternary to correctly return transaction results on success and a fallback message only when the result is empty.

buyA == null now correctly catches both undefined and null.

func is now typed as z.infer<typeof schema> for full type safety aligned with the Zod schema.

contractAddress is conditionally spread into config only when it has a value.


Why it was necessary:
The module-level env var crash was a production risk in any serverless deployment. The inverted result logic on deposit and swap meant successful transactions were returning no meaningful output to the agent, breaking observability. The remaining fixes close type safety gaps that could cause subtle runtime failures as the codebase scales.


Summary by cubic

Refactors env var handling to use lazy getters to avoid import-time crashes, fixes tool result handling and input typing, and makes transaction builders network-aware with safer defaults.

  • Refactors

    • Use lazy getters for STELLAR_PUBLIC_KEY, STELLAR_NETWORK, and SOROBAN_RPC_URL; centralize the Zod schema and type func with z.infer<typeof schema>; only include contractAddress when provided.
    • Make transaction builders network-aware and safer: require networkPassphrase (no hardcoded testnet), use ?? for fee defaults, guard memo for FeeBumpTransaction, add args-length check, narrow buildTransactionFromXDR config to { memo }, and throw on unhandled operation types.
  • Bug Fixes

    • Return actual results from deposit and swap (JSON stringified); show a simple fallback only when empty.
    • Validate buyA with == null to catch both undefined and null.

Written for commit 6f74633. Summary will update on new commits.

Interact with a Stellar Soroban liquidity pool smart contract. Supports the following actions:

- get_share_id: Retrieve the share token ID for the connected wallet.
- deposit: Add liquidity to the pool. Requires destination address (to), desired amounts for both tokens (desiredA, desiredB), and minimum acceptable amounts (minA, minB) to control slippage.
- swap: Exchange one token for another. Requires destination address (to), direction flag (buyA: true to buy token A, false to buy token B), exact output amount (out), and maximum input allowed (inMax) to cap slippage.
- withdraw: Remove liquidity from the pool. Requires destination address (to), share amount to burn (shareAmount), and minimum amounts to receive for both tokens (minA, minB).
- get_reserves: Fetch the current token reserve levels in the pool.

Defaults to testnet unless STELLAR_NETWORK is set to mainnet. Contract address can be overridden per-call via contractAddress for targeting specific pools.
@Div1912 Div1912 changed the title Refactor: lazy env getters, fix result handling and input typing fix(tools): prevent import time crashes, correct result handling, and improve input validation Apr 22, 2026

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 1 file

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/contract.ts">

<violation number="1" location="tools/contract.ts:23">
P2: `getSorobanRpcUrl` uses `??`, so an empty `SOROBAN_RPC_URL` is treated as valid and passed as `rpcUrl`, causing runtime connection failures instead of falling back to default.</violation>

<violation number="2" location="tools/contract.ts:81">
P2: Truthiness-based handling for deposit/swap misreports successful executions as no-value results because these helpers normally return undefined.</violation>
</file>

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

Comment thread tools/contract.ts
Comment thread tools/contract.ts Outdated
Div1912 and others added 2 commits April 22, 2026 19:05
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
- Add networkPassphrase as required field in BuildTransactionConfig
  to prevent silent TESTNET transactions on mainnet
- Replace hardcoded Networks.TESTNET with config.networkPassphrase
  in buildTransaction
- Fix fee defaulting: replace || with ?? (nullish coalescing) in
  buildTransaction and buildPathPaymentTransaction
- Add instanceof Transaction guard before memo mutation in
  buildTransactionFromXDR to safely handle FeeBumpTransaction
- Narrow buildTransactionFromXDR config to Pick<…, "memo"> since
  fee/timeout are already encoded in the XDR
- Add args.length > 0 guard to avoid spreading empty arrays
- Replace `return _exhaustive` with throw in getDefaultTimeout default
  branch for loud runtime failure on unhandled operation types
- Remove dead `rpc` import; add FeeBumpTransaction import
- Prefix unused operationType param with _ in buildTransactionFromXDR
- Fix return types: any → Transaction / Transaction | FeeBumpTransaction
@Div1912 Div1912 closed this Apr 22, 2026
@Div1912 Div1912 reopened this Apr 22, 2026
fix(core): make transaction builder network aware, improve type safety, and fix default handling
@daiwikmh

Copy link
Copy Markdown
Contributor

ci checks fail

@daiwikmh daiwikmh closed this Apr 30, 2026
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.

2 participants