<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Loai Qubti</title>
    <description>The latest articles on DEV Community by Loai Qubti (@loai17).</description>
    <link>https://dev.to/loai17</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4000084%2F06e6262c-b4dd-41a1-9993-b550419d6819.jpg</url>
      <title>DEV Community: Loai Qubti</title>
      <link>https://dev.to/loai17</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/loai17"/>
    <language>en</language>
    <item>
      <title>The $500K Hack Nobody Warned You About: When Your AI Middleware Goes Rogue</title>
      <dc:creator>Loai Qubti</dc:creator>
      <pubDate>Mon, 29 Jun 2026 13:19:08 +0000</pubDate>
      <link>https://dev.to/loai17/the-500k-hack-nobody-warned-you-about-when-your-ai-middleware-goes-rogue-45af</link>
      <guid>https://dev.to/loai17/the-500k-hack-nobody-warned-you-about-when-your-ai-middleware-goes-rogue-45af</guid>
      <description>&lt;p&gt;There's a version of AI agent security that everyone is talking about right now.&lt;/p&gt;

&lt;p&gt;Spend caps. Allow-lists. Trusted execution environments. Hardware-isolated key storage. MetaMask shipped an Agent Wallet with transaction simulation and threat scanning built in. Coinbase put private keys inside TEEs. Ledger is working on hardware-enforced agent policies.&lt;/p&gt;

&lt;p&gt;The infrastructure is genuinely improving. The conversation around wallet-layer security is maturing.&lt;/p&gt;

&lt;p&gt;Here's the problem: the attack that just drained a $500,000 wallet didn't touch any of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Attack Nobody Was Watching For
&lt;/h2&gt;

&lt;p&gt;In April 2026, a research team from UC Santa Barbara, UC San Diego, Fuzzland, and World Liberty Financial published findings that should have made significantly more noise than they did.&lt;/p&gt;

&lt;p&gt;They documented 26 LLM routers — services that sit between users and AI models, forwarding requests to providers like OpenAI or Anthropic — secretly injecting malicious tool calls into agent workflows. One of those routers drained a client's crypto wallet of $500,000. The team also demonstrated they could poison routers to forward traffic to attacker-controlled infrastructure, taking over approximately 400 hosts within hours.&lt;/p&gt;

&lt;p&gt;The wallet's spend cap was intact. The allow-list was intact. The keys were secure. The attack happened somewhere else entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  What an LLM Router Actually Does
&lt;/h2&gt;

&lt;p&gt;To understand why this matters, it helps to understand what sits between your agent's "brain" and its wallet.&lt;/p&gt;

&lt;p&gt;When an AI agent decides to make a transaction, that decision doesn't travel directly from the LLM to the signing step. It passes through infrastructure. Tool-call handlers, middleware, routing layers — services that interpret the model's output, format it into executable commands, and pass it to whatever action the agent is supposed to take.&lt;/p&gt;

&lt;p&gt;An LLM router is one of those services. It sits between your application and the model, ostensibly to manage traffic, reduce costs, or add latency optimizations. Sounds like plumbing. Feels like plumbing.&lt;/p&gt;

&lt;p&gt;But a router has full visibility into everything passing through it. Every prompt. Every tool call. Every output the model sends back. Including, if your agent is connected to a wallet, every instruction to move money.&lt;/p&gt;

&lt;p&gt;A malicious router doesn't need to compromise your wallet. It doesn't need your private keys. It just needs to intercept the instruction "send 0.1 ETH to address X" and replace it with "send 0.1 ETH to address Y." Or it can inject an entirely new tool call the model never generated — one the agent executes because it looks indistinguishable from a legitimate instruction.&lt;/p&gt;

&lt;p&gt;The wallet signs a valid transaction. The keys were never touched. The spend cap was never exceeded. Everything looks normal until you check the balance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Existing Guardrails Don't See This
&lt;/h2&gt;

&lt;p&gt;This is the part worth sitting with.&lt;/p&gt;

&lt;p&gt;Spend caps check the amount. Allow-lists check the destination. Transaction simulation checks whether the contract being called is malicious. TEE-based key protection ensures the keys don't leave secure hardware.&lt;/p&gt;

&lt;p&gt;None of these check whether the instruction itself was legitimate before it became a transaction.&lt;/p&gt;

&lt;p&gt;By the time a router-injected command reaches the wallet's signing layer, it looks exactly like every other transaction request. The amount might be within the cap. The destination might even be a real address that wasn't on the allow-list because the agent regularly sends to new addresses. The contract is fine. Nothing in the security stack that everyone is building right now can distinguish a legitimate agent instruction from one that was silently replaced three layers up the stack.&lt;/p&gt;

&lt;p&gt;This isn't a critique of the teams building wallet security. TEEs, simulation, and threat scanning are genuinely valuable. They solve real problems. The point is that they solve the problems &lt;em&gt;at the wallet layer&lt;/em&gt;, and this attack happens above the wallet layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Behavioral Monitoring Actually Catches
&lt;/h2&gt;

&lt;p&gt;Here's where the gap closes, partially.&lt;/p&gt;

&lt;p&gt;A compromised router still has to produce a transaction. That transaction still has to match — or not match — how the wallet has behaved in the past. And if an attacker is draining a wallet through router injection, the resulting transactions tend to share a set of characteristics that deviate from normal behavioral patterns.&lt;/p&gt;

&lt;p&gt;A recipient the wallet has never sent to. An amount outside the wallet's normal range. A transaction type the agent has never initiated. A velocity spike — multiple transfers in rapid succession that don't match how this agent normally operates.&lt;/p&gt;

&lt;p&gt;These signals don't tell you that the router was compromised. They tell you that &lt;em&gt;this transaction doesn't look like this wallet&lt;/em&gt;. That's a different and complementary form of protection — not "is this contract malicious" or "is this amount within the cap," but "is this how this agent normally behaves?"&lt;/p&gt;

&lt;p&gt;It doesn't catch everything. A sophisticated attacker who has studied a wallet's transaction history can try to mimic its behavioral patterns. But most attacks aren't that sophisticated, and the behavioral layer catches the lazy majority that the wallet-layer defenses miss.&lt;/p&gt;

&lt;p&gt;This is what WalletPrint scores before a transaction is signed — not whether the transaction is technically allowed, but whether it matches the behavioral fingerprint of the wallet attempting it. When a router-injected transaction deviates from that fingerprint, the score reflects it. Your system gets a signal before anything moves.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Broader Picture
&lt;/h2&gt;

&lt;p&gt;The $500K router attack is one data point in a pattern that's been building all year.&lt;/p&gt;

&lt;p&gt;AI trading agent vulnerabilities in 2026 exceeded $45 million in losses across multiple incidents. The consistent theme isn't smart contract bugs or phishing — it's the layer between the model and the action. Memory poisoning. Malicious plugins. Router injection. Attacks that don't compromise the wallet directly but compromise the decision-making that feeds into it.&lt;/p&gt;

&lt;p&gt;The wallet security conversation is necessary and the progress being made is real. But it's covering one layer of a multi-layer problem. The attacks are already moving to the layers above it.&lt;/p&gt;

&lt;p&gt;The only thing still being negotiated, as one analysis this week put it, is the trust model. That negotiation is happening fast — 480,000 active agents, 165 million transactions, a 265% increase in weekly volume since March. The infrastructure for what agents can do is scaling rapidly. The infrastructure for knowing whether what they're doing is actually what they intended to do is catching up.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;WalletPrint is a behavioral risk scoring layer for crypto agent wallets. It scores every proposed transaction against the wallet's own history before signing — flagging what looks off, in plain English, before anything moves. Open source SDK, free to start.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you're building agent wallet infrastructure and thinking about the trust layer, we'd like to talk: &lt;a href="https://walletprint.vercel.app/contact" rel="noopener noreferrer"&gt;walletprint.vercel.app/contact&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>wallet</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Building Human-in-the-Loop Approval for AI Agent Crypto Payments</title>
      <dc:creator>Loai Qubti</dc:creator>
      <pubDate>Wed, 24 Jun 2026 08:13:25 +0000</pubDate>
      <link>https://dev.to/loai17/building-human-in-the-loop-approval-for-ai-agent-crypto-payments-49jd</link>
      <guid>https://dev.to/loai17/building-human-in-the-loop-approval-for-ai-agent-crypto-payments-49jd</guid>
      <description>&lt;p&gt;AI agents can now spend crypto on their own. No human clicking approve. That's the point.&lt;/p&gt;

&lt;p&gt;But "autonomous" doesn't mean "unsupervised." The question isn't whether your agent can transact — it's whether you'll know when it's about to do something it's never done before, and whether a human can step in before it does.&lt;/p&gt;

&lt;p&gt;Spend caps and allow-lists don't answer that. They define what an agent can't do. Nothing watches for when it starts acting differently than it normally does — a transfer to a brand-new address, an amount ten times larger than usual, a contract it's never touched.&lt;/p&gt;

&lt;p&gt;This tutorial shows you how to build a human-in-the-loop approval layer for your AI agent wallet in about 15 minutes. When a transaction looks off, your system gets an alert — Slack, email, whatever you use — and a human decides whether it goes through. Built on &lt;a href="https://walletprint.vercel.app" rel="noopener noreferrer"&gt;WalletPrint&lt;/a&gt;, an open-source behavioral risk SDK for agent wallets.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;By the end of this tutorial, your agent will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Screen every proposed transaction against its own behavioral history before signing&lt;/li&gt;
&lt;li&gt;Get back a risk score and plain-English reasons when something looks off&lt;/li&gt;
&lt;li&gt;Fire a webhook alert to your team (Slack, email, or your own review flow) for medium and high risk transactions&lt;/li&gt;
&lt;li&gt;Give humans the ability to approve, hold, or escalate — before anything moves&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No spend cap changed. No allow-list modified. Just a behavioral signal layer sitting between "agent wants to pay" and "payment goes through."&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 18+&lt;/li&gt;
&lt;li&gt;An agent using ZeroDev session keys, LangChain tools, or any agent that signs transactions&lt;/li&gt;
&lt;li&gt;15 minutes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 — Install the SDK
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @walletprint/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2 — Set Up Your Environment
&lt;/h2&gt;

&lt;p&gt;Add these two lines to your &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;WALLETPRINT_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;walletprint-dev-key
&lt;span class="nv"&gt;WALLETPRINT_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://walletprint.up.railway.app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sandbox key (&lt;code&gt;walletprint-dev-key&lt;/code&gt;) works immediately with no signup. Scores are computed live and returned in full — sandbox requests are rate-limited and not persisted, which is fine for testing. When you're ready to build real behavioral baselines, request a production key at &lt;a href="https://walletprint.vercel.app" rel="noopener noreferrer"&gt;walletprint.vercel.app&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 — Score a Transaction
&lt;/h2&gt;

&lt;p&gt;Here's the most basic usage — no framework-specific wrapper needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WalletPrintClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@walletprint/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WalletPrintClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WALLETPRINT_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WALLETPRINT_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;score&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xYourAgentWallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xRecipient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value_usd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USDC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// 0-100&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;band&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// "low" | "medium" | "high"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason_codes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// plain-English reasons&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A response looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"band"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason_codes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NEW_RECIPIENT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New recipient"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Wallet has never sent to this address before."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"contribution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SIZE_EXTREME_OUTLIER"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unusual transaction size"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"detail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Transaction value is in the top 1% of this wallet's history."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"contribution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No black box. Every flag is explained in plain English, with a contribution score showing how much each reason affected the total.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 — Set Up Webhook Alerts
&lt;/h2&gt;

&lt;p&gt;Wire up a webhook so your system gets notified the moment a medium or high band transaction is scored. This is the human-in-the-loop layer — when WalletPrint flags something, your team gets an alert and decides what happens next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://walletprint.up.railway.app/v1/webhook &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"content-type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: YOUR_PRODUCTION_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "webhook_url": "https://your-app.com/walletprint/webhook",
    "webhook_bands": ["medium", "high"]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WalletPrint fires a POST to your URL the moment a flagged transaction is scored — with the full score, band, reason codes, and transaction details. Route it to Slack, email, a human review dashboard, whatever fits your stack. Full webhook payload schema is in the &lt;a href="https://github.com/Loai17/walletprint-sdk/blob/main/docs/approval-flow.md" rel="noopener noreferrer"&gt;approval flow docs&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5 — Integrate with ZeroDev
&lt;/h2&gt;

&lt;p&gt;If you're using ZeroDev session keys, wrap your &lt;code&gt;sendTransaction&lt;/code&gt; call so every transaction is screened before signing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WalletPrintClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wrapZeroDevSendTransaction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@walletprint/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WalletPrintClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WALLETPRINT_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WALLETPRINT_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;screenedSend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrapZeroDevSendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sessionKeyClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xYourAgentWallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;getValueUsd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Replace with your price oracle / token metadata lookup&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onScore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WalletPrint:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;band&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason_codes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Your app decides what to do — WalletPrint never blocks automatically&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;band&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// pause, alert a human, require manual approval&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Use screenedSend exactly like sessionKeyClient.sendTransaction&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;screenedSend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xRecipient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wrapper is advisory only — WalletPrint never blocks a transaction automatically. You get the signal. You decide what happens next.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6 — Integrate with LangChain
&lt;/h2&gt;

&lt;p&gt;If you're building a LangChain agent, add WalletPrint as a tool in your agent's tool list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WalletPrintClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createLangChainDynamicTool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@walletprint/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WalletPrintClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WALLETPRINT_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WALLETPRINT_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scoreTool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createLangChainDynamicTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xYourAgentWallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Add scoreTool to your agent's tool list before signing transactions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createReactAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;yourExistingTools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scoreTool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent can now call the score tool before committing to a transaction, and use the result to decide whether to proceed, pause, or escalate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7 (Optional) — Label Outcomes to Improve the Model
&lt;/h2&gt;

&lt;p&gt;If you know whether a flagged transaction turned out to be legitimate or actually wrong, submit a label. This is how the behavioral model gets better over time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submitFeedback&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;screened_transaction_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;screened_transaction_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;false_positive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or "confirmed_malicious" | "confirmed_benign"&lt;/span&gt;
  &lt;span class="na"&gt;label_source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;integrator_dashboard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Legitimate treasury transfer to a new partner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every label you submit makes the model more accurate — not just for your wallet, but across every wallet WalletPrint screens. This is how the cross-wallet clustering signal gets built over time.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Just Happened
&lt;/h2&gt;

&lt;p&gt;Your agent wallet now has a behavioral layer that didn't exist five minutes ago.&lt;/p&gt;

&lt;p&gt;Every transaction gets checked against how that wallet actually behaves — not just whether it's within the rules. First-time recipients get flagged. Unusual amounts get flagged. Velocity spikes get flagged. And when something comes back high band, your system knows about it before anything is signed.&lt;/p&gt;

&lt;p&gt;The pattern that drained $285M from Drift would have looked like a perfectly normal transaction to every existing guardrail. This is the layer that notices when something doesn't match the pattern — even when the rules say it's fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SDK: &lt;a href="https://github.com/Loai17/walletprint-sdk" rel="noopener noreferrer"&gt;github.com/Loai17/walletprint-sdk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@walletprint/sdk" rel="noopener noreferrer"&gt;@walletprint/sdk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://walletprint.vercel.app/docs" rel="noopener noreferrer"&gt;walletprint.vercel.app/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Approval flow: &lt;a href="https://github.com/Loai17/walletprint-sdk/blob/main/docs/approval-flow.md" rel="noopener noreferrer"&gt;approval-flow.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Compliance export: &lt;a href="https://github.com/Loai17/walletprint-sdk/blob/main/docs/compliance.md" rel="noopener noreferrer"&gt;compliance.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions or want a production key? &lt;a href="https://walletprint.vercel.app/contact" rel="noopener noreferrer"&gt;walletprint.vercel.app/contact&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
