TriportRPC

Wallet identity filters

POSThttps://triport.io/v1/wallet/identity/batch

The predicate language shared by the batch endpoint and wallet-watch subscriptions: JSON predicates over the profile, combined with all / any / not, evaluated cheapest-first so the expensive deployer scan only runs for addresses that survive the cheap checks.

Cross-chain — Ethereum, Base, Polygon, BNB Smart Chain, Robinhood Chain, Tron— (tier-gated with the carrying endpoint)Business — 30 rps (wallet_identity); Enterprise — 150 rps

A filter is a JSON object with exactly one key: a combinator (all, any, not) or a leaf predicate. An object with several keys is an implicit all. Every leaf reads one group of the profile (names, balances / activity, labels, deployer); the evaluator orders leaves by the cost of the group they need, short-circuits all on the first false and any on the first true, and computes the deployer group only when the cheap leaves could not decide.

Limits: 64 leaf predicates, nesting depth 8. An unknown predicate name, a wrong value type, or a range with no operator is rejected with 400 invalid_filter and a message naming the offending key.

Response

The filter itself has no response; the carrying endpoint reports matched / total and, with return: all, a per-profile matched flag. meta.filter_fields lists the profile groups the filter read:

matchedboolean (per result) / integer (top level)
Whether the profile passed the filter / how many did.
meta.filter_fieldsstring
Comma-separated groups the filter read: names, balances, deployer, labels, activity.

Predicates

Combinators

KeyValueMeaning
allarray of filtersEvery child must be true ({"all": []} is true).
anyarray of filtersAt least one child true ({"any": []} is false).
notfilterNegation.

Leaf predicates

PredicateValueReadsExample
has_nametrue / false / list of sourcesverified names{"has_name": ["ens", "basenames"]}
name_matchesglob (case-insensitive)verified names{"name_matches": "*.eth"}
is_deployerbooleandeployer{"is_deployer": true}
tokens_createdint rangedeployer{"tokens_created": {"gte": 1}}
deployed_symbolglob (case-insensitive)deployer{"deployed_symbol": "PEPE*"}
balance{chain, gte|gt|lte|lt|eq} in coin unitsbalances{"balance": {"chain": "eth", "gte": "0.5"}}
balance_anydecimal rangebalances{"balance_any": {"gte": "1"}} — on at least one network
nonce / tx_count{chain?, int range}balances{"nonce": {"chain": "base", "gte": 10}}; without chain — the max across networks
active_onlist of networksbalances{"active_on": ["robinhood"]} — nonce > 0 on every listed network
is_contractboolean or {chain, value}balances{"is_contract": false} — no network reports code
has_labeltrue / false / list of categorieslabels{"has_label": ["cex", "bridge"]}
fresh_walletbooleanevent (monitoring only){"fresh_wallet": true} — rejected in batch

Ranges accept any subset of gte, gt, lte, lt, eq (at least one); decimal ranges take strings or numbers and are compared exactly (no float rounding). Sources: ens, basenames, unstoppable, spaceid. Label categories: cex, bridge, solver, dex, mixer, fund, other. Only verified names and labels count.

Errors

CodeMeaningWhen it happens
400invalid_filterUnknown predicate, wrong value type, empty range, glob syntax error, more than 64 leaves, nesting deeper than 8, or fresh_wallet outside a subscription. The message names the key.

Other codes come from the carrying endpoint — see batch errors.

Examples

Named deployer of at least one token with money on Ethereum

{"all": [
  {"has_name": true},
  {"is_deployer": true},
  {"tokens_created": {"gte": 1}},
  {"balance": {"chain": "eth", "gte": "0.3"}}
]}

Fresh-looking wallets that are not exchanges or bridges

{"all": [
  {"nonce": {"lte": 3}},
  {"balance_any": {"gt": "0"}},
  {"not": {"has_label": ["cex", "bridge", "solver"]}}
]}

Active on Robinhood Chain with a Base name or an ENS name

{"all": [
  {"active_on": ["robinhood"]},
  {"any": [{"has_name": ["basenames"]}, {"name_matches": "*.eth"}]}
]}

Contracts only, that created a PEPE-like token

{"all": [
  {"is_contract": {"chain": "eth", "value": true}},
  {"deployed_symbol": "PEPE*"}
]}

Notes

  • Cost ordering: balances / activity / labels come from the same per-network state batch (cheapest), names cost one contract call per source, deployer costs ⌈nonce / 500⌉ calls per network — write all filters with the cheap predicates first in spirit; the evaluator reorders them anyway, but any filters short-circuit on the first true child, so the cheapest true branch saves the most.
  • Missing networks are zero: a network that is not requested, not mounted on the PoP, or failed is treated as balance 0, nonce 0, not a contract for the purpose of predicates; check chains.<net>.error in the profile when a non-match is surprising.
  • Names and labels are verified-only: a reverse record whose forward resolution points elsewhere, or a behaviourally inferred label without a source, never satisfies has_name / has_label.
  • Related: batch endpoint, single-address profile.