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.
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.
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.
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.
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.
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.
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 errorIf present, the transaction would fail - show the error message asset_transfersToken and SOL movements with amount, mint, and change_type expected_state_changesHuman-readable diffs via humanReadableDiff for each account transaction_summaryFee breakdown via expected_fee and compute units consumed transaction_riskExploit warnings and account risk scores
Exploit Risk Warnings
The simulator detects exploit patterns like address poisoning. If
exploit_risks_detected is non-empty, display a warning:
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: [] };
}
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
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
for retry strategies.
Unsupported Networks
Address Risk Score returns results for
18+ supported networks . For
unsupported networks, partial results may be available through direct
attribution or cross-chain propagation.
Complete Send Flow
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 );
}
What’s Next
Transaction Simulation Guide Deep dive into simulation response interpretation and debugging.
Compliance Pipeline Add sanctions screening and payment risk for full compliance coverage.