Solana Stablecoin Payments in Real-time

Real-time streaming Solana SPL stablecoin transfers (USDT and USDC) over WebSocket from the Bitquery GraphQL API. Subscribes to Transfers filtered by USDT/US...

MIT-0 · Free to use, modify, and redistribute. No attribution required.
0 · 47 · 0 current installs · 0 all-time installs
byDivyasshree@divyn
MIT-0
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description, SKILL.md, and the included Python script consistently implement a WebSocket GraphQL subscription to Bitquery for USDC/USDT Solana transfers. The only required credential (BITQUERY_API_KEY) is appropriate for this integration and no unrelated services, binaries, or config paths are requested.
Instruction Scope
Runtime instructions only reference the Bitquery stream, the BITQUERY_API_KEY env var, and installing the 'gql[websockets]' dependency. The script reads only the declared env var, subscribes to the expected GraphQL fields, and prints formatted transfer records. The SKILL.md warns not to log the full WebSocket URL; the code follows that guidance (it does not print the URL).
Install Mechanism
There is no installation of third-party archives or downloads; dependency installation is via pip for 'gql[websockets]', a standard Python package. No extract-from-URL installs or unusual system changes are present.
Credentials
Only BITQUERY_API_KEY is required, which is proportionate. Minor packaging inconsistency: registry summary shows 'Required env vars: [object Object]' instead of enumerating BITQUERY_API_KEY — this is a metadata/packaging bug but not a functional security issue.
Persistence & Privilege
The skill does not request always:true and does not modify system or other skills' configs. It's instruction-only and runs when invoked; normal autonomous invocation settings remain default.
Assessment
This skill appears coherent and limited to connecting to Bitquery's streaming API for USDC/USDT transfers, but check the following before installing: 1) Keep your BITQUERY_API_KEY in an environment variable and do not print or commit it; Bitquery requires the token in the WebSocket URL which can leak in proxies/logs — rotate the key if exposed. 2) Run the script in a sandbox or container first and limit network exposure to trusted egress where possible. 3) Confirm the registry metadata lists BITQUERY_API_KEY correctly (the package summary shows '[object Object]' which is a minor packaging bug). 4) Ensure you trust Bitquery and are comfortable with streaming wallet addresses and transaction metadata being printed to your console or captured by any downstream logging/monitoring. 5) Consider using a restricted API token (if Bitquery supports token scopes) and rotate credentials periodically.

Like a lobster shell, security has layers — review code before you run it.

Current versionv1.0.1
Download zip
latestvk97dbahfzgymb8r9w8bbh56k7983k6ps

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

Runtime requirements

Env[object Object]

SKILL.md

Stablecoin payments — Solana USDC / USDT (Bitquery stream)

This 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

  • Stream USDC / USDT transfers on Solana in real time
  • Build dashboards or alerts for stablecoin payment flow
  • Audit sender, receiver, signature, and fees per transfer

What to consider before installing

This skill uses the Bitquery streaming API and one credential. Before installing:

  1. Registry metadata: Ensure BITQUERY_API_KEY is declared for installers when publishing to a registry.
  2. Token only via URL: Bitquery accepts the API token only in the WebSocket URL as ?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.
  3. Sandbox first: Run in a virtualenv or container first to confirm behavior.
  4. Schema drift: If the subscription fails validation, check Bitquery Solana docs and adjust the where clause only; keep the same mints and fields when possible.

Security Checklist

Before running this skill, confirm:

  • BITQUERY_API_KEY is set: export BITQUERY_API_KEY=your_token_here
  • You run in a sandboxed or isolated environment where feasible
  • You will not print, log, or commit the full WebSocket URL
  • You can rotate the key if it may have been exposed

Prerequisites

  • Environment: BITQUERY_API_KEY (required).
  • Runtime: Python 3.8+ and 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.


Use cases

  1. Treasury / ops monitoring — Watch USDC/USDT in and out of known wallets in real time.
  2. Large-transfer alerts — Filter on AmountInUSD or raw Amount in downstream code.
  3. Reconciliation — Match Transaction.Signature and Block.Time to internal ledgers.
  4. Program attribution — Use Instruction.Program.Method to see which program path initiated the transfer.

Step 1 — Check API Key

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.


Step 2 — Run the stream

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

Inline subscription (Python)

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())

Key fields

AreaFields
TransferAmount, AmountInUSD, Sender / Receiver (Address, Owner), Currency (Symbol, Name, MintAddress)
InstructionProgram.Method (subscription filter: notIncludesCaseInsensitive: "swap")
BlockTime, Height, Slot
TransactionSignature, Signer, Fee, FeeInUSD, FeePayer

Format output for users

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 / ...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Error handling

  • Missing BITQUERY_API_KEY: Tell the user to export it and exit.
  • WebSocket failed / 401: Invalid or expired token (auth is URL ?token= only).
  • Subscription errors in payload: Stop cleanly; do not log the full URL.
  • No events: Solana activity can be bursty; confirm token and network; wait for the next transfer.

Reference

Mint list, full subscription, and field notes: references/graphql-fields.md.

Files

5 total
Select a file
Select a file to preview.

Comments

Loading comments…