Skip to content

feat: Add Spraay payment tools — batch payments, escrow, and balance#6609

Open
plagtech wants to merge 6 commits into
crewAIInc:mainfrom
plagtech:feat/add-spraay-payment-tools
Open

feat: Add Spraay payment tools — batch payments, escrow, and balance#6609
plagtech wants to merge 6 commits into
crewAIInc:mainfrom
plagtech:feat/add-spraay-payment-tools

Conversation

@plagtech

Copy link
Copy Markdown

Spraay Payment Tools

Adds three new tools for cryptocurrency payments via the Spraay x402 payment gateway.

Tools

  • SpraayBatchPaymentTool — Validate, estimate gas, and execute batch payments to up to 200 recipients in a single transaction (~80%% gas savings). Free validation/estimation endpoints + x402-paid execute endpoint.
  • SpraayEscrowTool — Create on-chain escrow contracts between two parties with programmable release conditions.
  • SpraayBalanceTool — Check token balances across 16 supported chains (free).

Why this belongs in crewai-tools

CrewAI has 80+ tools for web scraping, databases, search, file I/O, and vector stores — but currently no payment tool. This is the first tool that gives CrewAI agents the ability to handle real financial transactions. Agents can now:

  • Run payroll for DAOs and teams
  • Distribute grants and bounties
  • Create escrow-protected freelance contracts
  • Check balances before committing funds

No API key required

The gateway uses the x402 payment protocol. Free endpoints (validate, estimate, balance) just work with no auth. Paid endpoints (execute, escrow) are paid per-request via x402 micropayment — no signup, no API key, no dashboard.

Architecture

  • Follows the same BaseTool + Pydantic schema pattern as BrightDataTool, NL2SQLTool, etc.
  • Batch contract on Base: 0x1646452F98E36A3c9Cfc3eDD8868221E207B5eEC
  • Only dependency: requests

Ecosystem

Spraay is integrated into NVIDIA NeMo Agent Toolkit (PRs #20, #27 merged), Google ADK, and AWS Strands.

Docs: https://docs.spraay.app

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds CrewAI tools for Spraay batch payments, escrow creation, and wallet balance queries. Shared utilities convert chains and token amounts, while paid requests support x402 payment challenges. The package exports the tools and documents setup, endpoint behavior, and examples.

Changes

Spraay Tools

Layer / File(s) Summary
Gateway payload and payment foundations
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py, lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_x402.py
Adds chain/token conversion helpers, decimal amount validation, and x402 challenge handling for paid requests.
Batch payment flow
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py
Adds structured recipient validation and validate, estimate, and execute actions with gateway responses.
Escrow creation flow
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py
Adds escrow input handling, base-unit conversion, optional conditions, and x402 gateway submission.
Balance queries and package integration
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py, lib/crewai-tools/src/crewai_tools/tools/spraay_tool/__init__.py, lib/crewai-tools/src/crewai_tools/__init__.py, lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md
Adds balance queries, package-level exports, and documentation for installation and tool usage.

Sequence Diagram(s)

sequenceDiagram
  participant CrewAI
  participant SpraayTool
  participant SpraayGateway
  participant x402Client
  CrewAI->>SpraayTool: Submit tool inputs
  SpraayTool->>SpraayGateway: Send free or paid request
  SpraayGateway-->>SpraayTool: Return response or payment challenge
  SpraayTool->>x402Client: Sign payment requirements
  x402Client->>SpraayGateway: Retry paid request
  SpraayGateway-->>SpraayTool: Return gateway result
  SpraayTool-->>CrewAI: Return formatted JSON result
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding Spraay payment tools for batch payments, escrow, and balance checks.
Description check ✅ Passed The description is directly related to the changeset and accurately explains the new Spraay payment tools and gateway behavior.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py`:
- Around line 75-79: The Spraay balance tool must use the paid balance API
instead of the free route. In
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py:75-79,
update the request in the balance lookup method to use the documented
/api/v1/balances endpoint and its x402 payment flow. In
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md:11 and :119,
remove or revise claims that the balance endpoint is free.

In
`@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py`:
- Around line 34-40: Replace the recipients type in the payment tool’s input
model with a nested Pydantic model that requires both address and amount fields,
then type recipients as a list of that model. Update _run to access the
validated model fields while preserving the existing payment behavior and
description.
- Around line 164-172: Update _execute_batch in
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py
(lines 164-172) and the corresponding paid request flow in
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py (lines
103-109) to handle the initial HTTP 402 challenge before calling
raise_for_status: construct the required payment payload from the challenge,
retry the request with the PAYMENT-SIGNATURE header, then validate the final
response.
- Around line 146-150: Update the request in the batch payment estimation flow
to use GET for the `/free/estimate-batch` endpoint instead of POST, and pass the
existing payload parameters using the query-parameter shape expected by that
endpoint rather than a JSON body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 13b0a54b-8daa-4649-81a9-eead76f7ef53

📥 Commits

Reviewing files that changed from the base of the PR and between 6d496f7 and 46bca5b.

📒 Files selected for processing (5)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py

Comment on lines +75 to +79
response = requests.get(
f"{self.gateway_url}/free/balance",
params=params,
timeout=30,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files 'lib/crewai-tools/src/crewai_tools/tools/spraay_tool/*' | sed 's#^`#-` #'

echo
echo "== spraay_balance_tool.py (relevant slice) =="
sed -n '1,220p' lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py

echo
echo "== README.md (relevant slices) =="
sed -n '1,180p' lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md

echo
echo "== search for balance endpoints / x402 / free-balance =="
rg -n "free/balance|/api/v1/balances|balance|x402|free endpoints|paid endpoints" lib/crewai-tools/src/crewai_tools/tools/spraay_tool -S

Repository: crewAIInc/crewAI

Length of output: 13330


🌐 Web query:

Spraay gateway balance endpoint free/balance api/v1/balances x402 docs

💡 Result:

The Spraay gateway provides a balance lookup endpoint at /api/v1/balances [1][2]. This endpoint is a paid service, typically requiring a small USDC payment (e.g., $0.002 to $0.005) via the x402 protocol [1][2][3]. When you call this endpoint without prior payment, the gateway returns a 402 Payment Required status code, indicating that x402 payment is necessary to access the resource [4][5][6]. The x402 protocol allows agents to pay for API access per request using USDC (e.g., via EIP-3009 on Base) without needing traditional API keys or accounts [5][7][6]. For developers and agents: - Base URL: https://gateway.spraay.app [8][5][6] - Endpoint: GET /api/v1/balances [1][2] - Documentation & Catalog: The official endpoint catalog and pricing are available at https://docs.spraay.app and via the machine-readable manifest at https://gateway.spraay.app/.well-known/x402.json [1][2][6]. - Integration: Tools like the Spraay MCP server automate the handling of 402 responses, enabling seamless balance checks within agent workflows [9][6]. Note that while some utility endpoints (such as /api/health, /api/chains, and token prices) may be free or have different pricing, the /api/v1/balances endpoint is specifically listed as a paid data primitive [8][2][3].

Citations:


Use the paid /api/v1/balances endpoint here. spraay_balance_tool.py still calls GET /free/balance, but the published gateway catalog lists balance lookup as GET /api/v1/balances and treats it as an x402-paid route. Update the tool to use the documented balance API/payment flow, and remove the README claims that balance is free.

📍 Affects 2 files
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py#L75-L79 (this comment)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md#L11-L11
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md#L119-L119
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py`
around lines 75 - 79, The Spraay balance tool must use the paid balance API
instead of the free route. In
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py:75-79,
update the request in the balance lookup method to use the documented
/api/v1/balances endpoint and its x402 payment flow. In
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md:11 and :119,
remove or revise claims that the balance endpoint is free.

Source: MCP tools

Comment thread lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py Outdated
Comment thread lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py Outdated
Comment thread lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py Outdated

@coderabbitai coderabbitai 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.

♻️ Duplicate comments (1)
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py (1)

77-83: 🎯 Functional Correctness | 🟠 Major

Complete the x402 payment flow for the paid balance endpoint.

Changing the URL to /api/v1/balances is correct, but this remains a plain unauthenticated GET. A paid gateway response of 402 is converted by raise_for_status() into an error, so balance checks cannot succeed unless x402 settlement is implemented elsewhere. Reuse the paid-tool flow or confirm this endpoint is free and update the contract accordingly.

#!/bin/bash
set -euo pipefail

rg -n -C 8 '402|x402|payment|requests\.(get|post)' \
  lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py \
  lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py`
around lines 77 - 83, Update the balance request flow in SpraayBalanceTool to
support x402 payment settlement for a 402 response, reusing the existing
paid-tool implementation from SpraayBatchPaymentTool or SpraayEscrowTool before
retrying the request. Preserve normal successful responses and ensure paid
balance checks no longer fail solely because raise_for_status() receives an
initial 402.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py`:
- Around line 77-83: Update the balance request flow in SpraayBalanceTool to
support x402 payment settlement for a 402 response, reusing the existing
paid-tool implementation from SpraayBatchPaymentTool or SpraayEscrowTool before
retrying the request. Preserve normal successful responses and ensure paid
balance checks no longer fail solely because raise_for_status() receives an
initial 402.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d75c67f3-5c6b-42e8-b209-1786bf3dc7d4

📥 Commits

Reviewing files that changed from the base of the PR and between 46bca5b and 665aca4.

📒 Files selected for processing (2)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py

plagtech added 2 commits July 21, 2026 15:39
- Replace recipients list[dict] with nested SpraayRecipient Pydantic
  model (required address and amount fields) in the batch payment tool
- Add x402 payment challenge handling to paid endpoints (batch execute,
  escrow create) via the official x402 package: on HTTP 402, sign the
  payment requirements with SPRAAY_WALLET_PRIVATE_KEY and retry with
  the payment header attached; without the key, return the parsed
  payment requirements as structured JSON instead of raising
- Document wallet requirement for paid endpoints in the README
- Verified endpoints against the live gateway discovery doc
  (/.well-known/x402.json): batch execute $0.02, escrow create $0.10,
  x402 v2 on Base/USDC
- Register SpraayBatchPaymentTool, SpraayEscrowTool, SpraayBalanceTool,
  and SpraayRecipient in crewai_tools __init__ so top-level imports work
- Align request bodies with the gateway (verified against openapi.json,
  the BPA 1.0 spec/schema, and live probes of the free endpoints):
  - POST /api/v1/batch/execute: {token, recipients[], amounts[], sender}
    with flat parallel arrays and base-unit amount strings
  - POST /free/validate-batch: {chain, token, recipients: [{to, amount}]}
    with chain slugs (base, ethereum, ...) not chain IDs
  - GET /free/estimate-batch: ?recipients=<count>&chain=<slug>
  - POST /api/v1/escrow/create: {depositor, beneficiary, token, amount}
- Add spraay_payload module: chain-ID-to-slug map, known token decimals,
  and Decimal-based decimal-to-base-unit conversion at the request
  boundary; public input schemas (SpraayRecipient address/amount decimal
  strings) unchanged
- Free endpoints verified live: validate-batch returns valid:true with
  the new shape; estimate-batch returns per-chain estimates
@plagtech

Copy link
Copy Markdown
Author

Addressed the review in 97d3dd9 and b54fea2:

Recipients schema — now a nested SpraayRecipient Pydantic model with required address and amount fields.
x402 payment flow on paid endpoints — execute and escrow now catch the initial 402, sign, and retry using the official x402 package. One note: the gateway implements x402 v2, where the payment header is X-PAYMENT (live manifest: gateway.spraay.app/.well-known/x402.json). Using the official package keeps header handling correct as the protocol evolves. If no wallet key is set, the tools return the parsed payment requirements as structured JSON instead of raising.
Balance endpoint — corrected to GET /api/v1/balances; README no longer claims it's free.
estimate-batch — corrected to GET with query params.

Also verified all request body shapes against the gateway's openapi spec rather than assuming — this caught additional fixes (chain slugs instead of chain IDs, base-unit amounts, to vs address in validate-batch).

Tested end-to-end against the live gateway: free endpoints with real calls, and the paid execute path with a funded wallet completing the full 402 → payment → retry flow successfully.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🧹 Nitpick comments (1)
lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py (1)

106-147: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

_run lacks a docstring despite nontrivial dispatch/validation logic.

As per coding guidelines, "Document public APIs and complex logic in Python code." _run validates action/recipients/sender, converts amounts, and dispatches to three different handlers — worth a short docstring summarizing the flow (this mirrors the same gap in spraay_escrow_tool.py's _run).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py`
around lines 106 - 147, Add a concise docstring to SpraayBatchPaymentTool._run
describing its validation and normalization of inputs, amount conversion, and
dispatch to validate, estimate, or execute handlers. Keep the existing control
flow and behavior unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py`:
- Around line 18-28: Update the descriptions and docstrings in
spraay_batch_payment_tool.py and spraay_escrow_tool.py to accurately state
support for the nine EVM chains represented by CHAIN_SLUGS, removing Solana and
the overstated “13+”/“14+” claims. Keep chain validation behavior unchanged
unless broader support is intentionally implemented by extending CHAIN_SLUGS.
- Around line 30-54: The token_decimals logic must not assume 18 decimals for
arbitrary contract addresses on the supported non-Base/Ethereum chains. Update
TOKEN_DECIMALS and the surrounding token-decimal resolution used by
token_decimals to cover the supported chain deployments, or resolve ERC-20
decimals dynamically through the gateway/RPC; preserve known native-symbol
handling and ensure supported tokens such as USDC and USDT produce their actual
base-unit amounts.
- Around line 81-99: Update to_base_units to reject non-finite Decimal values
using an is_finite() check immediately after scaling and before comparisons or
conversion. Raise the same ValueError-style invalid-amount error used for
malformed values, ensuring NaN and Infinity are handled consistently by batch
and escrow callers.

In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_x402.py`:
- Around line 76-81: Update post_with_x402 around Account.from_key and
register_exact_evm_client to catch wallet-signing/setup exceptions, including
malformed private keys. Return the same structured payment_required response
used by the missing-key and missing-package branches, preserving the existing
request and successful response flow when setup succeeds.

---

Nitpick comments:
In
`@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py`:
- Around line 106-147: Add a concise docstring to SpraayBatchPaymentTool._run
describing its validation and normalization of inputs, amount conversion, and
dispatch to validate, estimate, or execute handlers. Keep the existing control
flow and behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a89e15d-8c9f-416b-b26c-113fa8513e1b

📥 Commits

Reviewing files that changed from the base of the PR and between 665aca4 and b54fea2.

📒 Files selected for processing (8)
  • lib/crewai-tools/src/crewai_tools/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/__init__.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_x402.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/init.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_balance_tool.py

Comment on lines +18 to +28
CHAIN_SLUGS: dict[int, str] = {
1: "ethereum",
56: "bnb",
130: "unichain",
137: "polygon",
8453: "base",
9745: "plasma",
42161: "arbitrum",
43114: "avalanche",
60808: "bob",
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Chain support is overstated in the batch/escrow tool docs.

CHAIN_SLUGS supports 9 EVM chains total (including Base/Ethereum), yet spraay_batch_payment_tool.py's docstring/description claim "Base, Ethereum, Solana, and 13+ other chains" and spraay_escrow_tool.py claims "Base, Ethereum, and 14+ other chains." Solana isn't representable at all here since chain_id is an EVM integer and chain_slug only maps EVM IDs — any Solana input will simply fail with "Unsupported chain_id." Agents relying on the tool description to pick a chain will be misled into round-tripping on unsupported chains.

Update the tool descriptions to match the actual supported set (or expand CHAIN_SLUGS if broader support is intended).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py` around
lines 18 - 28, Update the descriptions and docstrings in
spraay_batch_payment_tool.py and spraay_escrow_tool.py to accurately state
support for the nine EVM chains represented by CHAIN_SLUGS, removing Solana and
the overstated “13+”/“14+” claims. Keep chain validation behavior unchanged
unless broader support is intentionally implemented by extending CHAIN_SLUGS.

Comment thread lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py Outdated
Comment thread lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_x402.py Outdated
plagtech added 2 commits July 21, 2026 16:58
- Resolve token decimals dynamically per (chain, token) instead of
  silently defaulting unknown tokens to 18: static known-token table ->
  gateway token directory (/api/v1/tokens, Base) -> the token contract's
  decimals() via public JSON-RPC eth_call, with results cached. If none
  resolve, return a clear error rather than guessing (e.g. USDC on
  Polygon is 6 decimals and now resolves correctly via RPC; previously
  it was mis-scaled by 10^12). Symbol shortcuts are now Base-only since
  the same symbol can use different decimals on other chains.
- Reject non-finite amounts in to_base_units: Decimal('NaN')/'Infinity'
  previously escaped as InvalidOperation/OverflowError past the
  ValueError handlers; now guarded with is_finite() (and scaleb overflow
  is mapped to ValueError too).
- Wrap x402 signer initialization (Account.from_key +
  register_exact_evm_client) in try/except so a malformed
  SPRAAY_WALLET_PRIVATE_KEY returns a structured payment_required
  response instead of crashing, matching the sibling failure branches.
- Correct chain claims in docstrings/descriptions: the gateway supports
  exactly 9 EVM chains (Base, Ethereum, BNB Chain, Unichain, Polygon,
  Plasma, Arbitrum, Avalanche, BOB); removed inaccurate Solana and
  13+/14+/15+ chain references in the batch, escrow, and README docs.

Smoke-tested against the live gateway and public RPCs: unknown token on
Polygon errors instead of guessing, USDC on Polygon resolves to 6 via
RPC, NaN/Infinity amounts raise ValueError, malformed wallet key returns
structured JSON, and the existing validate/estimate/execute/escrow
payload shapes are unchanged.
@plagtech

Copy link
Copy Markdown
Author

Round two addressed in ee3bdfc:

Token decimals — removed the static fallback entirely. Decimals now resolve dynamically: known-token table → gateway token directory → on-chain decimals() via RPC, cached per chain+token. Unknown tokens that can't be resolved return a clear error instead of guessing — for a payment tool, refusing to guess beats silently sending 10^12x the wrong amount. Verified live that USDC on Polygon resolves to 6 decimals (the exact case flagged).

Chain claims — corrected all docstrings to the 9 EVM chains this tool's interface can actually reach (chain_id is an EVM integer). The Spraay gateway itself serves 15 chains including Solana, Stellar, XRP, and Bitcoin; non-EVM paths are documented at docs.spraay.app. A follow-up could extend the tool to accept chain slugs directly for non-EVM support.

Non-finite amounts — to_base_units now rejects NaN/sNaN/±Infinity via is_finite() with a ValueError, and maps scaleb overflow to ValueError as well.

Malformed wallet key — key parsing and client registration are wrapped; a bad SPRAAY_WALLET_PRIVATE_KEY now returns the same structured payment_required-style response as the other failure branches instead of raising.

Re-verified end-to-end after the changes: live paid execute against the gateway completed the full 402 → payment → retry flow.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py`:
- Around line 184-195: Update the token handling in the decimals-resolution
logic to remove the token.upper() == "ETH" shortcut from the native-token
condition. Keep NATIVE_ADDRESS mapped to NATIVE_DECIMALS, and allow Base ETH
resolution through BASE_SYMBOL_DECIMALS while requiring NATIVE_ADDRESS on other
chains.
- Around line 236-239: Update the exception handling around Decimal.scaleb in
the amount-scaling logic to catch decimal.Overflow alongside InvalidOperation
and convert both to the existing ValueError with the same structured
invalid-amount message. Ensure Overflow is imported or referenced from the
decimal module, while preserving the existing finite-value guard and exception
chaining.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6fce6d9d-98d4-4905-b87a-bb957244055f

📥 Commits

Reviewing files that changed from the base of the PR and between b54fea2 and ee3bdfc.

📒 Files selected for processing (5)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_x402.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/README.md
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_x402.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_escrow_tool.py
  • lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_batch_payment_tool.py

Comment on lines +184 to +195
if token == NATIVE_ADDRESS or token.upper() == "ETH":
return NATIVE_DECIMALS

if not _ADDRESS_RE.fullmatch(token):
symbol = token.upper()
if chain_id == BASE_CHAIN_ID and symbol in BASE_SYMBOL_DECIMALS:
return BASE_SYMBOL_DECIMALS[symbol]
raise ValueError(
f"Unknown token symbol {token!r} on chain {chain_id}. Symbol "
"shortcuts are only supported on Base (8453); pass the token's "
"contract address (0x...) instead."
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restrict the ETH symbol shortcut to Base.

ETH returns 18 decimals before the Base-only symbol check, so it is accepted on BNB Chain, Polygon, Avalanche, etc. Both supplied payment callers then forward that raw token value unchanged. Remove the or token.upper() == "ETH" special case; Base already resolves ETH through BASE_SYMBOL_DECIMALS, while other chains can use NATIVE_ADDRESS.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py` around
lines 184 - 195, Update the token handling in the decimals-resolution logic to
remove the token.upper() == "ETH" shortcut from the native-token condition. Keep
NATIVE_ADDRESS mapped to NATIVE_DECIMALS, and allow Base ETH resolution through
BASE_SYMBOL_DECIMALS while requiring NATIVE_ADDRESS on other chains.

Comment on lines +236 to +239
try:
scaled = value.scaleb(decimals)
except InvalidOperation as e:
raise ValueError(f"Invalid amount {amount!r}: out of range.") from e

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
from decimal import Decimal, InvalidOperation, Overflow, localcontext

with localcontext() as context:
    context.Emax = 9
    try:
        Decimal("1e9").scaleb(1)
    except Overflow:
        print("Confirmed: scaleb() raises decimal.Overflow.")
    except InvalidOperation:
        raise SystemExit("Unexpected InvalidOperation")
PY

Repository: crewAIInc/crewAI

Length of output: 199


Map decimal overflow to ValueError. Decimal.scaleb() can raise decimal.Overflow for finite values with extreme exponents, so that path bypasses the structured input error handling. Catch Overflow here as well; the is_finite() guard only covers non-finite return values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai-tools/src/crewai_tools/tools/spraay_tool/spraay_payload.py` around
lines 236 - 239, Update the exception handling around Decimal.scaleb in the
amount-scaling logic to catch decimal.Overflow alongside InvalidOperation and
convert both to the existing ValueError with the same structured invalid-amount
message. Ensure Overflow is imported or referenced from the decimal module,
while preserving the existing finite-value guard and exception chaining.

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