> ## Documentation Index
> Fetch the complete documentation index at: https://docs.range.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallet & dApp Integration

> Add real-time risk protection to Solana wallets and dApps with address screening and transaction simulation.

This guide shows how to integrate Risk API into a Solana wallet or dApp to
protect users from malicious addresses and risky transactions. The flow screens
recipients before sending and simulates transactions before signing.

<Info>
  **Prerequisites:** You need a [Risk API key](/introduction/getting-started)
  and familiarity with the [Address Risk
  Score](/risk-api/risk/get-address-risk-score) and [Transaction
  Simulator](/risk-api/simulator/simulate-solana-transaction) endpoints.
</Info>

***

## Integration Flow

A typical wallet integration adds two risk gates to the send flow:

```
User enters recipient + amount
      │
      ▼
┌─────────────────────────┐
│  Screen recipient       │──── High risk? → Show warning
│  (Address Risk Score)   │
└─────────────────────────┘
      │
      ▼
  User constructs transaction
      │
      ▼
┌─────────────────────────┐
│  Simulate transaction   │──── Risky accounts? → Show warning
│  (Transaction Simulator)│     Failure? → Show error
└─────────────────────────┘
      │
      ▼
  User reviews risk info → Confirm or Cancel
      │
      ▼
  Sign and broadcast
```

***

## Step 1: Screen the Recipient

Before the user constructs a transaction, check the recipient address for
connections to known malicious actors.

```typescript theme={null}
async function screenRecipient(address: string, network: string = 'solana') {
  const params = new URLSearchParams({ address, network });
  const response = await fetch(
    `https://api.range.org/v1/risk/address?${params}`,
    { headers: { Authorization: `Bearer ${API_KEY}` } },
  );
  const data = await response.json();

  return {
    score: data.riskScore,
    level: data.riskLevel,
    reasoning: data.reasoning,
    isSafe: data.riskScore <= 3,
    isAttributed: data.attribution !== null,
    attribution: data.attribution,
  };
}
```

### What to Show the User

|    Score | UI Treatment                                                                                                                      |
| -------: | --------------------------------------------------------------------------------------------------------------------------------- |
|  **1–3** | Green indicator. Proceed normally. If `attribution` is present, optionally show the entity name (e.g., "Token Program - Solana"). |
|  **4–5** | Yellow warning. Show `reasoning` and let the user decide.                                                                         |
|  **6–7** | Orange warning. Recommend against proceeding. Show `reasoning` and the number of hops to malicious addresses.                     |
| **8–10** | Red block. Strongly warn. Show `reasoning` and `maliciousAddressesFound` details. Require explicit confirmation.                  |

<Tip>
  Check the `attribution` field - when present, it means the address is a
  verified non-malicious entity (like a system program or major exchange). You
  can display the entity name to reassure the user.
</Tip>

***

## Step 2: Simulate the Transaction

After the user constructs but before they sign the transaction, simulate it to
preview the effects and check for exploit risks.

```typescript theme={null}
async function simulateTransaction(encodedTransaction: string) {
  const response = await fetch(
    'https://api.range.org/v1/simulate/solana/transaction',
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        payload: encodedTransaction,
        encoding_type: 'base64',
      }),
    },
  );
  return response.json();
}
```

### Key Response Fields to Display

| Field                    | What to Show                                                     |
| ------------------------ | ---------------------------------------------------------------- |
| `error`                  | If present, the transaction would fail - show the error message  |
| `asset_transfers`        | Token and SOL movements with `amount`, `mint`, and `change_type` |
| `expected_state_changes` | Human-readable diffs via `humanReadableDiff` for each account    |
| `transaction_summary`    | Fee breakdown via `expected_fee` and compute units consumed      |
| `transaction_risk`       | Exploit warnings and account risk scores                         |

<Tip>
  For detailed response parsing with code examples, see the [Transaction
  Simulation
  Guide](/risk-api/guides/transaction-simulation#step-3-analyze-the-response).
</Tip>

### Exploit Risk Warnings

The simulator detects exploit patterns like address poisoning. If
`exploit_risks_detected` is non-empty, display a warning:

```typescript theme={null}
function checkExploitRisks(simulationResult: SimulationResult) {
  const exploits =
    simulationResult.transaction_risk?.exploit_risks_detected || [];

  if (exploits.length > 0) {
    return {
      hasExploitRisk: true,
      warnings: exploits.map(
        e => e.description || 'Potential exploit detected',
      ),
    };
  }

  return { hasExploitRisk: false, warnings: [] };
}
```

***

## Step 3: Display Risk Information

Combine the address screening and simulation results into a confirmation screen.
The goal is to give users enough information to make an informed decision
without overwhelming them.

### Recommended UI Pattern

```
┌─────────────────────────────────────────┐
│  Transaction Preview                    │
│                                         │
│  Sending: 100 USDC                      │
│  To: 7xKX...3mN2                        │
│  Fee: ~0.00025 SOL                      │
│                                         │
│  ┌─────────────────────────────────┐    │
│  │ ⚠ Recipient Risk: Medium (5/10) │    │
│  │ 3 hops from flagged address     │    │
│  └─────────────────────────────────┘    │
│                                         │
│  Balance Changes:                       │
│  · USDC: -100.00                        │
│  · SOL:  -0.00025 (fee)                 │
│                                         │
│  [Cancel]              [Send Anyway]    │
└─────────────────────────────────────────┘
```

### Best Practices

* **Don't block silently.** Always explain why a transaction is flagged. Show
  the `reasoning` field.
* **Let users override with warning.** Even high-risk transactions should be
  possible to send if the user explicitly confirms - they may know something the
  scoring doesn't.
* **Show entity attribution.** If the recipient is a known entity (exchange,
  protocol), display its name.
* **Cache address risk cautiously.** Risk scores change as new intelligence is
  incorporated. For high-value transfers, always query fresh.

***

## Step 4: Handle Edge Cases

### Network Errors and Timeouts

```typescript theme={null}
async function screenWithFallback(address: string, network: string) {
  try {
    const result = await Promise.race([
      screenRecipient(address, network),
      new Promise((_, reject) =>
        setTimeout(() => reject(new Error('timeout')), 5000),
      ),
    ]);
    return result;
  } catch (error) {
    // If the risk check fails, inform the user but don't block
    return {
      score: null,
      level: 'unknown',
      reasoning: 'Risk check unavailable - proceed with caution',
      isSafe: null,
    };
  }
}
```

### Rate Limits

If you hit rate limits (`429` responses), show a degraded state rather than
blocking the user. See [Rate Limits & Plans](/risk-api/product-info/rate-limits)
for retry strategies.

### Unsupported Networks

Address Risk Score returns results for
[18+ supported networks](/risk-api/product-info/supported-chains). For
unsupported networks, partial results may be available through direct
attribution or cross-chain propagation.

***

## Complete Send Flow

```typescript theme={null}
async function protectedSend(
  recipient: string,
  amount: number,
  network: string,
) {
  // Screen the recipient
  const risk = await screenWithFallback(recipient, network);

  if (risk.score >= 8) {
    // Require explicit user confirmation for high-risk
    const confirmed = await showHighRiskWarning(risk);
    if (!confirmed) return { status: 'cancelled' };
  } else if (risk.score >= 4) {
    // Show warning for medium-risk
    const confirmed = await showMediumRiskWarning(risk);
    if (!confirmed) return { status: 'cancelled' };
  }

  // Build and encode the transaction (see Transaction Simulation guide for SDK examples)
  const transaction = await buildTransaction(recipient, amount);
  const encoded = encodeTransactionBase64(transaction);

  // Simulate before signing
  const simulation = await simulateTransaction(encoded);

  if (simulation.error) {
    return { status: 'error', reason: simulation.error };
  }

  const exploits = checkExploitRisks(simulation);
  if (exploits.hasExploitRisk) {
    const confirmed = await showExploitWarning(exploits.warnings);
    if (!confirmed) return { status: 'cancelled' };
  }

  // Show confirmation with all risk data
  const confirmed = await showConfirmation({ risk, simulation });
  if (!confirmed) return { status: 'cancelled' };

  // Sign and send
  return await signAndSend(transaction);
}
```

<Tip>
  For SDK-specific transaction building and encoding examples using
  `@solana/kit` or `@solana/web3.js`, see the [Transaction Simulation
  Guide](/risk-api/guides/transaction-simulation#step-1-prepare-and-encode-the-transaction).
</Tip>

***

## What's Next

<CardGroup cols={2}>
  <Card title="Transaction Simulation Guide" icon="flask" href="/risk-api/guides/transaction-simulation">
    Deep dive into simulation response interpretation and debugging.
  </Card>

  <Card title="Compliance Pipeline" icon="gavel" href="/risk-api/guides/compliance-screening-pipeline">
    Add sanctions screening and payment risk for full compliance coverage.
  </Card>
</CardGroup>
