# Wallet & Address Sanctions + Risk Screener (`uxus.finance/wallet-sanctions-risk-screener`) Actor

- **URL**: https://apify.com/uxus.finance/wallet-sanctions-risk-screener.md
- **Developed by:** [UXUS FINANCE](https://apify.com/uxus.finance) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $25.00 / 1,000 address screeneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Wallet & Address Sanctions + Risk Screener

Give it an EVM address. It checks the **OFAC SDN list**, **community scam/phishing registries**, **live on-chain contract control reads** (owner, pause, upgradeable proxy), and **wallet age + transaction history** — and resolves all four into one scored verdict. Not a single-list lookup wearing a scanner's name.

### Why this one, not the others

There are a handful of OFAC/crypto-sanctions actors on the Store already. Look at what they actually do: submit an address, get back `sanctioned: true/false` against one static list. That's it — one signal, one lookup.

This actor runs the same production scoring engine behind [uxus.finance](https://uxus.finance), and it checks four things, not one:

- **OFAC SDN list** — the real US Treasury sanctions list, refreshed daily
- **Community scam/phishing registries** — addresses reported malicious outside of OFAC (a different, and differently-labeled, risk)
- **Live on-chain contract reads** — `eth_call`/`eth_getStorageAt` against the address right now: is it a contract, is ownership renounced, can the owner pause transfers, is it an upgradeable proxy that could swap its own logic in one transaction
- **Wallet age and transaction history** — a wallet a few days old with high transaction velocity reads differently than one with years of history

A single-signal OFAC checker tells you "not on the list." This tells you "not on the list, *and* here's what its owner could still do to you, *and* whether the read that would tell us otherwise actually succeeded."

### What you get back, per address

```json
{
  "address": "0x0330070fd38ec3bb94f58fa55d40368271e9e54a",
  "chain": "ethereum",
  "valid": true,
  "degraded": false,
  "sanctions_verdict": "BLOCK",
  "sanctions_risk_score": 100,
  "sanctions_flags": ["SANCTIONED"],
  "sanctions_reasons": [
    {
      "code": "SANCTIONED",
      "severity": 10,
      "detail": "Address is on the OFAC SDN sanctions list",
      "source": "ofac"
    }
  ],
  "sanctions_source": "ofac",
  "wallet_signals": {
    "wallet_age_days": 1246,
    "tx_count": 4,
    "first_seen": "2023-04-21T12:13:59.000Z",
    "last_seen": "2024-12-04T05:51:11.000Z",
    "signals_ok": true
  },
  "lists_consulted": ["mew", "ofac", "scamsniffer"],
  "lists_matched": ["ofac"],
  "is_contract": false,
  "mutable_verdict": "SAFE_TO_HOLD",
  "mutable_risk_score": 0,
  "can_turn_hostile": false,
  "time_to_rug": "impossible",
  "owner_powers": ["NOT_A_CONTRACT"],
  "controls": { "owner": null, "ownership_renounced": true, "is_upgradeable_proxy": false, "proxy_admin": null, "implementation": null, "has_pause": false, "is_paused": null, "pending_owner": null },
  "rpc_ok": true,
  "disclaimer": "Automated screening from public data (OFAC SDN list, community scam/phishing registries, on-chain reads). Developer-grade signal, not legal, financial, or compliance advice and not a substitute for a compliance program. Lists refresh daily and can lag a real-world designation; verify against the official source before you act. No warranty.",
  "checked_at": "2026-09-19T02:46:20.514Z"
}
```

That's a real, live run against an address actually on the current OFAC SDN list — not a mocked example. Here's a clean address, same run, same code:

```json
{
  "address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
  "chain": "ethereum",
  "valid": true,
  "degraded": false,
  "sanctions_verdict": "PROCEED",
  "sanctions_risk_score": 0,
  "sanctions_flags": ["CLEAN"],
  "sanctions_source": null,
  "wallet_signals": { "wallet_age_days": 4008, "tx_count": 10000, "signals_ok": true },
  "lists_consulted": ["mew", "ofac", "scamsniffer"],
  "lists_matched": [],
  "is_contract": true,
  "mutable_verdict": "SAFE_TO_HOLD",
  "mutable_risk_score": 0,
  "can_turn_hostile": false,
  "time_to_rug": "impossible",
  "owner_powers": ["CONTROLS_LOCKED"],
  "rpc_ok": true
}
```

### When a source can't be reached, you're told — never a silent "clean"

If the block-explorer history lookup fails, or an on-chain read doesn't land on any node, that's not treated as "no findings." It's treated as **unknown**. The sanctions verdict is floored so it can never read as safe, and every on-chain field we couldn't read is `null` — never a default that looks like an observation:

```json
{
  "degraded": true,
  "sanctions_verdict": "CAUTION",
  "sanctions_flags": ["HISTORY_UNAVAILABLE"],
  "sanctions_reasons": [{
    "code": "HISTORY_UNAVAILABLE",
    "detail": "Block-explorer history lookup failed (rate-limited or unavailable). No sanctions or scam-list match was found, but wallet-behavior signals were NOT checked — treat this as unassessed, not clean."
  }],
  "wallet_signals": { "wallet_age_days": null, "tx_count": null, "signals_ok": false },
  "lists_consulted": ["mew", "ofac", "scamsniffer"],
  "lists_matched": [],
  "is_contract": null,
  "mutable_verdict": "MONITOR",
  "mutable_risk_score": null,
  "can_turn_hostile": null,
  "time_to_rug": null,
  "owner_powers": ["RPC_UNAVAILABLE_RESULT_UNKNOWN"],
  "controls": { "owner": null, "ownership_renounced": null, "is_upgradeable_proxy": null, "proxy_admin": null, "implementation": null, "has_pause": null, "is_paused": null, "pending_owner": null },
  "rpc_ok": false
}
```

When `rpc_ok` is `false`:

- `is_contract`, `mutable_risk_score`, `can_turn_hostile`, `time_to_rug` and **every key of `controls`** are `null`. `null` means "we couldn't read this" — not `false`, not `0`. A `false` from this actor is always something we observed.
- It's all-or-nothing. If any read that feeds the verdict fails, the whole on-chain block is `null`, even a read that did land (`eth_getCode` succeeding doesn't make `is_contract` trustworthy when the owner and proxy reads didn't).
- `mutable_verdict` is the fixed floor `MONITOR` — "could not assess," never `SAFE_TO_HOLD` — the on-chain counterpart of `CAUTION`. `owner_powers` names why: `RPC_UNAVAILABLE_RESULT_UNKNOWN` (no node answered) or `PARTIAL_READ_RESULT_UNKNOWN` (some reads landed, some didn't).

An address that's on a list still returns that hit when the sources are down — a degraded run never downgrades a `BLOCK`.

#### Which lists were checked vs. which matched

- **`lists_consulted`** — every list the address was checked against, hit or not (currently `mew`, `ofac`, `scamsniffer`). It's the same on every record in a run, so a clean address shows what "clean" was checked against. If no lists are loaded the run fails rather than return unsupported "clean" results.
- **`lists_matched`** — only the lists that matched this address. `[]` on a clean address means checked, no hit.
- **`sanctions_source`** — the list behind a `SANCTIONED` finding: `"ofac"` for an actual SDN hit, never `"ofac"` for anything else. It is `null` when the address is only on a scam/phishing registry — those come back as a `SCAM_LIST_MATCH` reason (with the registry as its `source`), `BLOCK`, and an entry in `lists_matched`.

### Input

| Field | Type | Required | Notes |
|---|---|---|---|
| `addresses` | array of strings | yes | EVM addresses, `0x` + 40 hex chars. Up to 1,000 per run. |
| `chain` | `"ethereum"` | `"base"` | `"arc"` | no (default `ethereum`) | Which chain to read on-chain signals from. |

An address that isn't valid EVM format gets back `{ "valid": false, "error": "invalid_address", ... }` instead of failing the run — and isn't charged.

### Pricing

**$0.03 per address screened — $30 per 1,000.** Invalid-format addresses aren't charged — no work was done. Pay-per-event, no subscription.

### What this is not

Developer-grade signal, not a compliance program and not legal advice. Sanctions and scam lists refresh daily and can lag a real, current designation — verify against the official OFAC source before you act on a match. This actor does not check for token clawback or freeze functions; the live contract-control checks cover ownership, pause, and upgradeable-proxy admin — nothing more.

# Actor input Schema

## `addresses` (type: `array`):

EVM addresses to screen (0x..., 40 hex chars). Up to 1000 per run. An invalid entry returns an explanatory record instead of failing the run — you are not charged for it.

## `chain` (type: `string`):

Which chain to read on-chain signals (contract reads, wallet tx history) from. OFAC/scam-list matching is address-based and applies regardless of chain.

## Actor input object example

```json
{
  "chain": "ethereum"
}
```

# Actor output Schema

## `screenedAddresses` (type: `string`):

One record per address: OFAC/scam-list sanctions verdict, wallet age/tx signals, and live on-chain contract-control reads (owner, pause, upgradeable proxy).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("uxus.finance/wallet-sanctions-risk-screener").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("uxus.finance/wallet-sanctions-risk-screener").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call uxus.finance/wallet-sanctions-risk-screener --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,uxus.finance/wallet-sanctions-risk-screener"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/b36awfSu3uasVccLR/builds/7HjtQbYzXvgqnv23G/openapi.json
