Skip to main content
Glama

Bitquery: Crypto & Blockchain Data

Matic Flows Between

matic_flows_between
Read-only

FLOWS BETWEEN TWO ADDRESS SETS on Polygon (matic, POL, MATIC, PoS): every successful transfer (tokens and native POL) from any address of set A to any address of set B, and back, in ONE call - "did these wallets ever pay those wallets", "how much moved between my suspects and the exchange wallets", "which of these deposit addresses sent to that hot wallet". Pass up to 50 addresses per set separated by "|" (0xabc…|0xdef…). A longer list is not an error: the first 50 distinct addresses of each set are used and the rest are ignored - every row reports A_Addresses_Requested / A_Addresses_Used and B_Addresses_Requested / B_Addresses_Used, so compare them and split a longer set into several calls. Leave addresses_b EMPTY to get every counterparty of the A set, both directions, grouped per A address - the multi-address form of matic_flow_edges. mode="summary" (default) returns one row per (Direction, Sender, Receiver, token) with Transfers, total Amount, First_Time, Last_Time and the latest Tx, ordered by sort. mode="rows" returns the individual transfers newest first; page with cursor: pass the Cursor value of the LAST row, with all other arguments unchanged, to get the next page (a summary row carries no Cursor). A rows-mode row is a LEDGER LINE: besides the amount it carries Amount_Raw (the exact integer amount in the token's smallest unit) with Decimals, Block and Tx_Index, and Price_Usd (the token's USD price at the time of the transfer), Value_Usd = Amount x Price_Usd and Price_Status - "ok"; "no_price" = no price is known for this token at that time, so Price_Usd and Value_Usd are empty (never read that as zero); "suspect" = the stored price is more than twice the price one day earlier AND one day later, or less than half of both - a likely data glitch - so Value_Usd is left empty - check it with price_at. POL and the major tokens are priced to 5 minutes, every other token has ONE price per day, so the value of a small token is approximate. On a summary row those seven columns are empty: a total over a period has no single price. Self = 1 (both modes) marks a movement whose counterparty is another address of set A - a move inside the set, not income and not spending. Direction A_TO_B = sent by an A address to a B address, B_TO_A = sent by a B address to an A address; an address listed in both sets appears in both directions. With addresses_b empty the same holds for a transfer between two A addresses: it is listed as A_TO_B for its sender AND as B_TO_A for its receiver, so never add rows of both directions together. WINDOW: the last days days (default 30, at most 366) ending at before_time, or now; after_time sets the start instead, within the same 366-day limit. Window_From / Window_To on every row show the range searched; for an older period set before_time. An empty result means no transfer between the sets in that window. COST: the search is keyed on set A, so put the SMALLER and less busy set in addresses_a - individual wallets, not exchange hot wallets, bridges or token contracts. If the call fails with a row-limit error ("Limit for rows ... exceeded"), swap the two sets, shorten days, or split set A. Cost also grows with the number of addresses in set A times the window. Each row carries the token Contract (empty for native POL); a symbol alone can match look-alike clones, so pin one token with contract, or restrict to native or tokens with asset_type. Amount is in TOKEN UNITS: totals of different tokens must not be compared or added together, there is no usd filter (min_amount is in token units), and sort="amount" is only meaningful with one token pinned. To identify the addresses, pass them to labels_for_addresses. For the full labelled list in USD, totals by label type, or a set of addresses → counterparties.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "addresses_a": "<addresses_a>"
    },
    "name": "matic_flows_between"
  }
}

Input Schema

NameRequiredDescriptionDefault
daysNoWindow length in days ending at before_time (or now), 1-366. Ignored when after_time is set. Cost grows with the window, so widen it step by step; for older periods set before_time.
modeNosummary (default) = one row per direction, sender, receiver and token with totals; rows = the individual transfers, newest first, pageable with cursor.summary
sortNosummary mode only: count (default) = most transfers first; recent = latest activity first; amount = largest total first (meaningful only with one token pinned via contract). rows mode is always newest first.count
limitNoMax rows to return. At most 1000.
cursorNorows mode paging: pass the Cursor value of the LAST row of the previous page, keeping every other argument the same. Empty = first page.
formatNoShape of the returned data. "rows" (the default) returns one item per row. "columnar" returns a single item, {"columns":[...],"rows":[[value,...],...]}, naming the columns once and listing each row's values in that order; it is more compact for large results and carries the same values.rows
contractNoRestrict to ONE exact token by its contract address (0x-hex (case-insensitive)) - the reliable way to pin a token, since a symbol also matches clone tokens. Pass "native" for POL itself - the same as asset_type=native. Empty = every token and native POL.
after_timeNoOnly transfers at/after this UTC time (e.g. "2026-06-01" or "2026-06-01 12:00:00"). Overrides days. Empty = the last `days` days.
asset_typeNoall (default) = tokens and native POL; native = only POL itself; token = only tokens.all
min_amountNoMinimum amount of each transfer, in that token's own units. 0 (default) = all, including zero-value transfers (address-poisoning spam sends 0 of a token); set 1 or more to drop them.
addresses_aYesSet A: one or more addresses, 0x-hex (case-insensitive), separated by "|" - up to 50; addresses after the 50th distinct one are ignored (compare A_Addresses_Requested with A_Addresses_Used). The search is keyed on this set, so put the smaller and less busy set here.
addresses_bNoSet B: addresses, 0x-hex (case-insensitive), separated by "|" - up to 50; addresses after the 50th distinct one are ignored (compare B_Addresses_Requested with B_Addresses_Used). Empty (default) = any counterparty of set A.
before_timeNoOnly transfers strictly before this UTC time. Empty = up to now. Format: YYYY-MM-DD, YYYY-MM-DD HH:MM[:SS], ISO-8601 like 2026-09-20T00:00:00Z (fraction or +02:00 offset allowed) or 10-digit unix seconds.
flow_directionNoboth (default) = A to B and B to A; a_to_b = only transfers sent by set A to set B; b_to_a = only transfers sent by set B to set A. One direction halves the cost.both
include_internalNo1 = also count POL sent by contract code inside a transaction (internal transfers, e.g. through a batch-sending or exchange contract); 0 (default) = top-level POL transfers and token transfers only, like the other transfer tools. A transaction's own transfer is top-level, not internal, and is counted either way. Only 0 or 1.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / format
      Added value: +{
      +  "default": "rows",
      +  "description": "Shape of the returned data. \"rows\" (the default) returns one item per row. \"columnar\" returns a single item, {\"columns\":[...],\"rows\":[[value,...],...]}, naming the columns once and listing each row's values in that order; it is more compact for large results and carries the same values.",
      +  "type": "string"
      +}
  2. Changed1 schema field changed
    • changedInput schema / properties / contract / description
      Previous value: -"Restrict to ONE exact token by its contract address (0x-hex (case-insensitive)) - the reliable way to pin a token, since a symbol also matches clone tokens. Empty = every token and native POL."New value: +"Restrict to ONE exact token by its contract address (0x-hex (case-insensitive)) - the reliable way to pin a token, since a symbol also matches clone tokens. Pass \"native\" for POL itself - the same as asset_type=native. Empty = every token and native POL."
  3. First observed

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered by structured data. The description adds substantial behavior beyond that: the silent 50-address truncation with the Requested/Used counters, the cost model keyed on set A, the direction double-counting warning, and the Price_Status='suspect'/'no_price' semantics. However, it doesn't describe the return envelope (row fields, columnar format, error shape) in full, so it is valuable but not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The scoping and cost guidance is front-loaded and every section (window, cost, row shape, direction) earns its place for a 15-parameter tool. The text is dense and somewhat run-on (mixed indentations, long parenthetical asides), which costs readability but not correctness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter, no-output-schema tool this is close to complete: row fields, direction semantics, the Self flag, window boundaries, empty-result meaning, and the pagination contract are all spelled out. An agent could call it correctly and interpret the results without further documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents every parameter including defaults and formats. The description does add cross-parameter meaning beyond the schema: sort='amount' is only meaningful with one token pinned, min_amount is in token units with no USD filter, summary rows carry no Cursor, and totals of different tokens must not be added. That is real added value, but much of it is already restated in the per-parameter schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb and resource: every successful token and native POL transfer from any address of set A to any address of set B, and back, in one call. It also names its nearest sibling ('the multi-address form of matic_flow_edges') and the complementary tools (labels_for_addresses, price_at), so an agent can place it precisely in the tool set.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states when to use the tool with concrete user phrasings ('did these wallets ever pay those wallets'), when to leave addresses_b empty (to get every counterparty of A), and what to do on failure (swap the sets, shorten days, split set A). It also directs the agent to labels_for_addresses for identification and price_at for suspect prices, which is exactly the routing an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.