Install
openclaw skills install solana-stablecoin-payments-trackingReal-time streaming Solana SPL stablecoin transfers (USDT and USDC) over WebSocket from the Bitquery GraphQL API. Subscribes to Transfers filtered by USDT/US...
openclaw skills install solana-stablecoin-payments-trackingThis skill provides a real-time WebSocket subscription to Solana token transfers where the mint is USDT (Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB) or USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v), and Instruction.Program.Method excludes "swap" to cut DEX swap noise. Each event includes transfer amounts (and USD where available), parties, transaction metadata, and the instruction program method.
When to use this skill
This skill uses the Bitquery streaming API and one credential. Before installing:
BITQUERY_API_KEY is declared for installers when publishing to a registry.?token=.... The URL can leak via logs, shell history, or proxies. Do not print or log the full URL; store the key in an environment variable; rotate if exposed.where clause only; keep the same mints and fields when possible.Before running this skill, confirm:
BITQUERY_API_KEY is set: export BITQUERY_API_KEY=your_token_hereBITQUERY_API_KEY (required).pip. Install: pip install 'gql[websockets]' (see requirements.txt).URL-only auth: Construct the WebSocket URL from the env var and pass it only to the transport. Never emit the full URL in output or logs.
AmountInUSD or raw Amount in downstream code.Transaction.Signature and Block.Time to internal ledgers.Instruction.Program.Method to see which program path initiated the transfer.import os
api_key = os.getenv("BITQUERY_API_KEY")
if not api_key:
print("ERROR: BITQUERY_API_KEY environment variable is not set.")
print("Run: export BITQUERY_API_KEY=your_token")
exit(1)
If the key is missing, tell the user and stop.
pip install 'gql[websockets]'
python ~/.openclaw/skills/stablecoin-payments/scripts/stream_stablecoin_payments.py
Optional timeout:
python ~/.openclaw/skills/stablecoin-payments/scripts/stream_stablecoin_payments.py --timeout 60
import asyncio, os
from gql import Client, gql
from gql.transport.websockets import WebsocketsTransport
async def main():
token = os.environ["BITQUERY_API_KEY"]
url = f"wss://streaming.bitquery.io/graphql?token={token}"
transport = WebsocketsTransport(
url=url,
headers={"Sec-WebSocket-Protocol": "graphql-ws"},
)
async with Client(transport=transport) as session:
sub = gql("""
subscription {
Solana {
Transfers(
where: {
Transfer: {
Currency: {
MintAddress: {
in: [
"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
]
}
}
}
Instruction: {
Program: {
Method: { notIncludesCaseInsensitive: "swap" }
}
}
}
) {
Transfer {
Amount
AmountInUSD
Sender { Address Owner }
Receiver { Address Owner }
Currency { Symbol Name MintAddress }
}
Instruction { Program { Method } }
Block { Time Height Slot }
Transaction {
Signature
Signer
Fee
FeeInUSD
FeePayer
}
}
}
}
""")
async for result in session.subscribe(sub):
for row in (result.get("Solana") or {}).get("Transfers") or []:
print(row)
asyncio.run(main())
| Area | Fields |
|---|---|
| Transfer | Amount, AmountInUSD, Sender / Receiver (Address, Owner), Currency (Symbol, Name, MintAddress) |
| Instruction | Program.Method (subscription filter: notIncludesCaseInsensitive: "swap") |
| Block | Time, Height, Slot |
| Transaction | Signature, Signer, Fee, FeeInUSD, FeePayer |
When summarizing a transfer, use a clear block like:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Solana stablecoin transfer @ 2025-03-25T14:00:00Z Slot 123456789
USDC (EPjF...Dt1v) Amount: 1,000.50 (~$1,000.50 USD)
From: SenderAddr... (owner: ...) → To: ReceiverAddr...
Tx: 5xYz...abc | Fee: 0.000005 SOL (~$0.00 USD) | Fee payer: ...
Program method: transfer / ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
BITQUERY_API_KEY: Tell the user to export it and exit.?token= only).Mint list, full subscription, and field notes: references/graphql-fields.md.