subscribe_wallet - a wallet's tokens, live
Name a wallet and you get every trade of every token it has traded, by anyone, the wallet's own trades included. When the wallet trades a new token while you listen, that token joins the stream at once, with the trades right behind the wallet's. Server emits wallet_trade for trades and wallet_token when a token joins or leaves.
| Channel | Socket.IO event |
| Auth | none needed; your plan's key raises the limits |
| Emits | wallet_trade, wallet_token |
| Cost | Free |
Example
- JavaScript
- Python
import { io } from "socket.io-client";
const socket = io("https://sol.shrine.trade"); // no key needed
socket.on("wallet_trade", (t) => {
const who = t.isTarget ? "WALLET" : t.wallet.slice(0, 4) + "…";
const side = t.is_buy ? "BUY " : "SELL";
console.log(`${who} ${side} ${t.sol_amount?.toFixed(3)} SOL of ${t.mint}`);
});
socket.on("wallet_token", (e) => console.log(e.status, e.mint, e.reason ?? ""));
socket.emit(
"subscribe_wallet",
{
wallet: "9AiXyDfy6cKieVPgwyfsNS37HypoS8k7ju2CV3WnyvZG",
minSol: 0.5, // other wallets' trades of at least 0.5 SOL
minWalletSol: 1, // tokens the wallet put at least 1 SOL through
lookbackHours: 24, // "has traded" = in the last 24 hours
},
(ack) => console.log(ack.history.status, ack.tokens.length, "tokens"),
);
// later, to stop: socket.emit("unsubscribe_wallet", { wallet: "9AiX…" });
import socketio
sio = socketio.Client()
@sio.on("wallet_trade")
def on_trade(t):
who = "WALLET" if t["isTarget"] else t["wallet"][:4] + "…"
side = "BUY " if t["is_buy"] else "SELL"
print(f"{who} {side} {t['sol_amount']} SOL of {t['mint']}")
@sio.on("wallet_token")
def on_token(e):
print(e["status"], e["mint"], e.get("reason", ""))
def on_ack(ack):
print(ack["history"]["status"], len(ack["tokens"]), "tokens")
sio.connect("https://sol.shrine.trade") # no key needed
sio.emit("subscribe_wallet", {
"wallet": "9AiXyDfy6cKieVPgwyfsNS37HypoS8k7ju2CV3WnyvZG",
"minSol": 0.5,
"minWalletSol": 1,
"lookbackHours": 24,
}, callback=on_ack)
sio.wait()
# later, to stop: sio.emit("unsubscribe_wallet", {"wallet": "9AiX…"})
Options
| Option | Default | |
|---|---|---|
wallet | required | The wallet to follow. |
minSol | 0 | Only other wallets' trades worth at least this many SOL. The followed wallet's own trades always come through, whatever their size. |
minWalletSol | 0 | Follow a token only once the wallet has put at least this many SOL through it, buys and sells together: within lookbackHours, plus what it trades while you listen. Its own trades of a token below the mark still come through; the token joins when the mark is reached. |
lookbackHours | 24 | How far back "has traded" reaches. 0 is live only: tokens join as the wallet trades them. Up to 24 on Free, 72 on Lite, 168 on Developer. |
maxTokens | your plan's | How many tokens to follow at once: up to 20 on Free, 100 on Lite, 500 on Developer. When the list is full and the wallet trades a new token, the token it traded least recently makes room. |
mints | [] | Tokens to follow from the start, whatever the history says. They count toward maxTokens and are never dropped to make room. |
A value above your plan's is lowered to it; the ack's options shows what applies. A token is followed on all its pools: a pump.fun coin's curve, and its PumpSwap pool once it migrates.
Ack
{
"ok": true,
"wallet": "9AiXyDfy6cKieVPgwyfsNS37HypoS8k7ju2CV3WnyvZG",
"options": { "minSol": 0.5, "minWalletSol": 1, "lookbackHours": 24, "maxTokens": 20 },
"history": { "status": "ok", "hours": 24, "scannedHours": 24 },
"tokens": [
{
"mint": "Gc6rNxGnoQt6vCfhNzn5iJnPBu1V38GZfdYERfnXpump",
"pools": ["4mBLRPUyfE7CvxmXiGJx5WA51isanbxpdbdPjFuuBzmY"],
"walletSol": 3.42,
"lastTradeAt": 1779812627,
"source": "history"
}
]
}
tokens- what is followed now, the most recently traded first.walletSolis the wallet's volume in the token;sourceishistory,liveorclient(frommints).history.status:ok- the whole lookback was read;partial- the read ran out of time afterscannedHours; the tokens found so far are followed;unavailable- history could not be read just now; the stream runs live only;skipped-lookbackHourswas0.
Subscribing again to a wallet you already follow on the socket answers existing: true with the current state. To change the options, unsubscribe and subscribe again.
Response - wallet_trade
{
"protocol": "PUMPSWAP",
"pool": "4mBLRPUyfE7CvxmXiGJx5WA51isanbxpdbdPjFuuBzmY",
"mint": "Gc6rNxGnoQt6vCfhNzn5iJnPBu1V38GZfdYERfnXpump",
"signature": "c9asMSPXxiEYC4RQpLBFUAASCL63TXZpPgSPgivDcJxsNoNc7ptrh6DfJy67NS2p7nEQBbVR45ZuPhyBqectR76",
"is_buy": true,
"token_amount": 153285714.285714,
"quote_amount": 5.0,
"quote": "So11111111111111111111111111111111111111112",
"sol_amount": 5.0,
"price": 0.0000000326,
"wallet": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
"timestamp": 1779812627,
"target": "9AiXyDfy6cKieVPgwyfsNS37HypoS8k7ju2CV3WnyvZG",
"isTarget": false
}
wallet- who made this trade, as ontrade.target- the wallet you follow;isTargetistruewhen it made this trade itself.quote/quote_amount- the pool's quote token and how much of it moved.sol_amount- the trade's value in SOL: the quote amount on a SOL pool, converted at the live SOL/USD price on a USDC, USDT or USD1 pool,nullon a pool quoted in anything else. Anulltrade does not passminSoland does not count towardminWalletSol.price- the trade's own price,quote_amount / token_amount.timestamp- the chain's time for the trade's slot, in seconds.
A trade of a token two of your followed wallets traded arrives once for each, with its own target.
Response - wallet_token
{ "wallet": "9AiX…", "status": "added", "mint": "Gc6r…pump", "pools": ["4mBL…"], "walletSol": 1.2, "lastTradeAt": 1779812627, "source": "live" }
{ "wallet": "9AiX…", "status": "removed", "reason": "max_tokens", "mint": "Bk3q…pump", "pools": ["8nQe…"], "walletSol": 0.4, "lastTradeAt": 1779809000, "source": "history" }
{ "wallet": "9AiX…", "status": "skipped", "reason": "max_tokens", "mint": "Hz7w…pump", "pools": ["2mFs…"] }
added- the wallet traded a token (and reachedminWalletSol): its trades follow from here.removed- it made room for a newer one.skipped- the list is full of tokens frommints, so the new one was not added. Sent once per token.
The tokens in the ack are not announced again.
Unsubscribe
socket.emit("unsubscribe_wallet", { wallet: "9AiX…" }, (ack) => console.log(ack.wallets));
socket.emit("unsubscribe_wallet", {}); // every wallet on this socket
Errors
error | When |
|---|---|
invalid_request | No wallet, or one that is not a Solana address; an option out of range (message says which). |
limit_exceeded | Your plan's wallets are all followed already, across your sockets (plan, message, upgrade). Unsubscribe one first. |
rate_limited | Too many history lookups (2 a minute on Free, 10 on Lite, 30 on Developer). retryAfterMs says when; lookbackHours: 0 is never limited. |
If you do not pass an ack callback, the error is emitted as a subscription_error event instead. See when you reach a limit for the shape.
Try it
Notes
- Free and keyless:
wallet_tradeandwallet_tokenare never billed. - Wallets per plan, counted across all your sockets (per key, or per address without one): 1 on Free, 3 on Lite, 20 on Developer.
- History is every trade our feed recorded, across every launchpad and DEX we index.
- Only tokens someone follows are published, so following a quiet wallet costs nothing while it sleeps.
- Following one token rather than a wallet? Use
subscribe_trades. The whole market: the Advanced Data Stream.
LimitsFree 1 wallet · 20 tokens each · 24 h backLite 3 wallets · 100 tokens each · 72 h backDeveloper 20 wallets · 500 tokens each · 168 h backSee plans →