ryntra-solana-evidence
Enables users to inspect Solana token mint accounts, preflight transfer actions, and verify outcome receipts without holding any keys or signing transactions.
README
Ryntra Solana Evidence Kit
Read what a Solana asset can do to you, preview exactly what a transfer will do, and check a receipt without asking the party that wrote it.
Apache-2.0. Read-only by construction: no key, no signing path, no transaction
building, and one RPC method — getAccountInfo. A test enumerates every RPC
call and every signing-shaped identifier in the shipped sources on each run, so
that sentence is a gate rather than a promise.
npm ci
npm run verify # lint, typecheck, network-free tests, boundary gate
npm run cli -- inspect 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
That last command reads PayPal USD on mainnet through a public endpoint, with no account anywhere, and prints its eight token extensions with what each one means for somebody holding the asset.
Why
A Token Extensions mint can carry powers a balance does not show you. A permanent delegate lets the issuer move or burn tokens from any account. A transfer hook runs somebody else's program on every transfer. A transfer fee means the recipient gets less than was sent. A default-frozen account state means receiving a token is not the same as being able to move it.
None of that is hidden — it is on chain, in the mint account, decodable by anyone. It is just not read by most of the things people press buttons in.
This kit reads it, says what it means in a sentence a holder understands, and
refuses to compress any of it into a score. There is no rating here, and the
best verdict the policy engine can return is NO_KNOWN_BLOCKER.
The three tools
flowchart LR
RPC[("Solana JSON-RPC<br/>getAccountInfo")]
MINT["mint account bytes"]
RPC --> MINT
MINT --> P["<b>inspect_solana_mint</b><br/>Asset Passport<br/>identity · authorities<br/>extensions with provenance"]
P --> F["<b>preflight_solana_action</b><br/>exact preview<br/>fee math · resolved hook<br/>expected balance deltas"]
POL["owner policy<br/>13 declared dials"] --> V["policy verdict<br/>13 findings"]
F --> V
R[("Outcome Receipt<br/>JSON")] --> VR["<b>verify_solana_receipt</b><br/>schema · integrity<br/>issuer · binding"]
classDef tool fill:#101418,stroke:#4c8bf5,color:#e8eef6
classDef data fill:#0d1117,stroke:#3d444d,color:#c9d1d9
class P,F,V,VR tool
class RPC,MINT,POL,R data
| What it answers | Reaches the network | |
|---|---|---|
inspect_solana_mint |
What is this asset, and what can its issuer do to a holder | yes, one read |
preflight_solana_action |
What will this exact transfer do, and what does my policy make of it | yes, one read |
verify_solana_receipt |
Is this receipt intact, who signed it, and is it about Solana | no — entirely local |
Each is available three ways: as a typed SDK call, as an MCP tool, and from the CLI.
Layout
lib/solana/ the evidence core — decoding, passport, preflight, policy, receipt
lib/agent-control/ the frozen canonical hashing and the Solana registry adapter
lib/guard/ the one canonical JSON serializer both hashers use
packages/solana-evidence-sdk/ typed calls over the core
packages/solana-evidence-mcp/ local stdio MCP server
examples/solana-evidence-cli/ the runnable CLI
docs/solana/schemas/ published JSON Schemas for non-JS consumers
lib/ is not a copy. These are the same modules ryntra.io runs, extracted with
their paths intact — so a result from this kit and a result from the product
come from the same code, and an extraction that broke that fails its own tests.
lib/stellar/evidence.ts is here for the same reason and no other: the evidence
envelope is chain-neutral, and shipping the one implementation beats shipping a
copy that drifts. lib/solana/evidence.ts says so where you meet it.
Design rules, and what they cost
Every fact carries how it is known. ONCHAIN_VERIFIED, DECLARED,
DERIVED, CONFLICTING, UNKNOWN, UNSUPPORTED. A value with no source is
not a value here. The cost is verbosity, and it is worth it: an issuer's own
marketing and a ledger read must never wear the same badge.
A sentence describes the setting, not the slot. A mint carrying
TransferHook with the all-zero program id has no hook installed — the passport
says that, and says who can install one. The generic sentence would have been
false on the single most-inspected Token Extensions mint there is.
Amounts are raw base units as strings. A 64-bit amount does not survive a JavaScript number, and a lossy amount is a wrong amount. There is no decimal anywhere on the value path.
An extension nobody wrote semantics for still renders, flagged, with its raw kind. A decoded fact without a pretty sentence is still a fact; hiding it would be the lie.
Nothing throws. Refusals are values with a code and a reason —
ACCOUNT_NOT_FOUND, NOT_A_MINT, DECODE_FAILED. "No answer" and "this
answer" must not look alike.
Retries cover the transport and never the answer. A response that parses is returned as-is, including "no account", because re-asking does not change facts.
Receipts
A Ryntra Outcome Receipt is an observation of something that already happened —
never an instruction, and never proof that Ryntra did it. verify_solana_receipt
recomputes both hashes from the receipt's own bytes and checks the Ed25519
signature against the key the receipt carries. Four axes, reported separately:
- schema — is this the shape of a receipt at all;
- integrity — do both hashes recompute;
- issuer — is the signature sound; and, only if you pass
trustedPublicKeys, is the key one you trust; - binding — does the registry pin name the Solana adapter.
"Signed by someone" is not "signed by Ryntra", and collapsing the two is the
mistake that axis exists to prevent. lib/solana/fixtures/receipt-*.json are
real artifacts you can run this against, including one that is the signed one
with a single character edited.
Trust boundary
- Non-custodial and keyless. No key is held, read, derived or requested. There is no signing path, and the boundary gate fails the build if one appears.
- Nothing is executed. No transaction is built or submitted.
- A verdict is not a safety judgement. It reports the absence of known blockers under a policy the caller declared, and the verdict vocabulary has no word for safety.
- The endpoint is the operator's choice. No tool or SDK call takes a URL
from its caller; provider endpoints come from
RYNTRA_SOLANA_RPC_MAINNETandRYNTRA_SOLANA_RPC_DEVNET, and public defaults work with no account. - Source-distributed. The root package is
private, so an accidentalnpm publishrefuses. No npm package is claimed.
Links
- SDK:
packages/solana-evidence-sdk - MCP server:
packages/solana-evidence-mcp - CLI:
examples/solana-evidence-cli - Security: SECURITY.md · Contributing: CONTRIBUTING.md
- The workspace this came from: https://ryntra.io/solana
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。
mcp-server-qdrant
这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。