Matic Flows Between
matic_flows_betweenFLOWS 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
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | Window 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. | |
| mode | No | summary (default) = one row per direction, sender, receiver and token with totals; rows = the individual transfers, newest first, pageable with cursor. | summary |
| sort | No | summary 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 |
| limit | No | Max rows to return. At most 1000. | |
| cursor | No | rows mode paging: pass the Cursor value of the LAST row of the previous page, keeping every other argument the same. Empty = first page. | |
| format | No | 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. | rows |
| contract | No | 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. | |
| after_time | No | Only 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_type | No | all (default) = tokens and native POL; native = only POL itself; token = only tokens. | all |
| min_amount | No | Minimum 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_a | Yes | Set 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_b | No | Set 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_time | No | Only 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_direction | No | both (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_internal | No | 1 = 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. |