Stellaroid Earn
MCP serverDev toolsOnce added, your AI can verify credentials and browse escrows on the Stellaroid Earn contract, which runs on the Stellar testnet. The integration is read-only, so your AI can look up this information but cannot create or change anything on the contract. It is built for developers working with Stellaroid Earn.
Use Stellaroid Earn in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add Stellaroid Earn and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use Stellaroid Earn to verify credential
No key or account is asked for. Not verified by us yet: Ahel has not run a call through it.
Details
Available today. Use it from your connected AI after setup.
No key or account is asked for. Not verified by us yet: Ahel has not run a call through it.
After adding it, ask your AI to verify a credential or browse the escrows on the Stellar testnet contract.
What your AI can do with it
- Verify credentials on the Stellaroid Earn testnet contract
- Browse escrows recorded on the contract
- Look up escrow details on the Stellar testnet
- Check credential records without making changes to the contract
Install Stellaroid Earn
The server’s own address, for the clients that take one directly. Or connect Ahel once and every client you use reads it from one address, with the account kept on Ahel rather than in each client’s config.
Claude Code
claude mcp add --transport http --scope user stellaroid-earn 'https://stellaroid.tech/api/mcp'Run it once in your project, then open /mcp to approve any sign-in the server asks for.
Claude Desktop
https://stellaroid.tech/api/mcpAdd a custom connector in Settings, paste this address, and approve the sign-in.
Cursor
cursor://anysphere.cursor-deeplink/mcp/install?name=stellaroid-earn&config=eyJ1cmwiOiJodHRwczovL3N0ZWxsYXJvaWQudGVjaC9hcGkvbWNwIn0=Open the link and Cursor adds the server at that address.
ChatGPT
https://stellaroid.tech/api/mcpIn Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.
Codex
codex mcp add stellaroid-earn --url 'https://stellaroid.tech/api/mcp'Run it once, then sign in with codex mcp login stellaroid-earn if the server asks for an account.
From the project's README
As published by iron-mark/hackathon-stellaroid_earn in README.md.
A reusable prove, verify, pay primitive for on-chain credentials, built for Stellar PH Bootcamp 2026
Issue, verify, and pay graduates on Stellar testnet: Soroban smart contract, 8 supported wallets plus WalletConnect for mobile (Freighter, Albedo, LOBSTR, xBull & more), installable PWA, end-to-end.
| Live demo | stellaroid.tech |
| Contract (current) | CAD6C24POQGRYXMBNBEGVDHUROF5ZC37XRDC6NCVILTXWMYJIBMISZCV |
| Tx evidence | init · register · verify |
| Source verification | Deployed WASM hash 1b7479f1ca0f12846bbfdd8f0681670692e29e1f20618150912f010b7caf4b9f. Rebuilding the v3.0.0 release tag reproduces it byte for byte, and the deployed bytecode records its own build toolchain (rsver 1.95.0, rssdkver 26.1.0, cliver 27.0.0) so you can check it without trusting this README. Verified weekly by contract-verification.yml. Runbook: docs/operations/contract-verification.md. |
| Submission | Rise In · Stellar Smart Contract Bootcamp · Stellar PH Bootcamp 2026 |
| Result | Top 5 / 105 participants · Score: 75.00 · full journey |
Project Status
The bootcamp/event submission is complete. Stellaroid Earn is now maintained as a living Stellar credential proof project.
- Roadmap:
ROADMAP.md - Maintenance checks:
MAINTENANCE.md - Docs index:
docs/README.md - Release and deployment:
docs/operations/release-and-deployment.md - Pro-research intake:
docs/planning/research-intake-status.md - Demo checklist:
docs/operations/demo-checklist.md - Canonical live URL:
stellaroid.tech - Operational status route:
/status - Pilot intake route:
/pilot - Case study (how it was built and verified):
/case-study - Handoff (repo state, invariants, what remains):
HANDOFF.md - Campaign and launch graphics:
assets/campaign/, including the 2-minute promotional walkthroughstellaroid-promotional-demo.mp4
www.stellaroid.tech and earn.stellaroid.tech redirect to the canonical apex URL.
Version archive
Each monthly build cycle is preserved as a frozen snapshot at a pinned subdomain, independent of the live site:
| Version | Cycle | Snapshot |
|---|---|---|
| v1 | April | v1.stellaroid.tech |
| v2 | June | v2.stellaroid.tech |
| v3 | July | v3.stellaroid.tech |
| v4 | August (current) | v4.stellaroid.tech |
stellaroid.tech always serves the latest production build (main). The April source lives on the april-bootcamp-and-monthly-builder branch; June, July, and August on june-monthly-builder, july-monthly-builder, and august-monthly-builder. July is a read-only archive. August is the live monthly-builder branch, and v4.stellaroid.tech serves its Vercel deployment.
July v3.2 product surface
- Wallet-less guided demo -
/demo: the full register → verify → escrow → payout story on real seeded testnet data (a released 25 XLM escrow and a live funded one), with per-step stellar.expert audit links. No wallet, no extension, works on a phone. - Opportunity directory -
/opportunity: every live escrowed paid trial on the contract, with wallet-scoped filters (for you / created by you) and deep links into the milestone console. - Live escrow evidence - the status page and activity feeds now decode all escrow events (create/fund/submit/approve/release/refund) alongside credential events, deduplicated across the RPC and the Stellar Expert indexer;
/appshows the events involving your connected wallet. - On-site pilot intake -
/pilothas a real lead-capture form (rate-limited, honeypot-guarded, delivered by email) instead of a link-out, plus/contact, an honest privacy & terms page, and an RFC 9116security.txt. - Performance pass - the multi-megabyte stellar-sdk is lazy-loaded out of every route's First Load JS (
/appdropped 483 → ~260 KB gzipped), the brand typefaces (Orbitron/Exo 2) are self-hosted vianext/font, and first-party client-error telemetry reports runtime failures to server logs with no third-party service. - Installable PWA - manifest with maskable icons, service worker (network-first pages, offline fallback, per-deploy cache versioning; verification pages are never served from cache), iOS splash screens. Add it to a phone home screen from the live site.
- Mobile-first redesign - app-style bottom navigation with a More sheet, auto-hiding header, bottom-sheet dialogs, full safe-area/notch handling.
- Developer docs hub -
/docs: contract reference (live tag v3.0.0: 19 functions, 17 error codes; source adds refresh/expiry writes), integration, architecture, and security posture. - Content engine - audience landing pages for bootcamps, employers, and graduate payouts, plus a guides library and a verifiable-credentials glossary - all with FAQPage/HowTo/DefinedTermSet structured data and an
llms.txt. - Multi-wallet signing - Freighter and Albedo natively, WalletConnect for mobile wallets (LOBSTR, xBull, Hana, Freighter mobile), and on desktop xBull, Rabet, LOBSTR, Hana, Klever, and Bitget via Stellar Wallets Kit - all behind one provider interface, lazy-loaded on first use. WalletConnect activates when a Reown project id is configured.
The public entry flow is organized around three personas: Issue, Verify, and Hire. Verified proof pages now hand employers into /employer with the proof hash and candidate wallet preloaded, then require a review checklist before escrow creation. They also hand recruiters into /talent/<address>?proof=<hash> so the candidate passport can show a known proof without pretending wallet-wide credential discovery exists yet. Issuer registration now explains approval readiness before signing, and /pilot keeps the first rollout bounded to a small testnet issuer pilot. Employer proof packs include a recruiter-safe summary plus an unsigned standards-alignment preview for W3C VC 2.0 and Open Badges 3.0 mapping. That preview is not a signed standards credential yet.
30-Second Pitch
Problem: Bootcamp certificates are PDFs that anyone can fake and no one can independently verify. Employers skip verification or pay for a background check service.
Solution: Stellaroid Earn anchors credential hashes on a Soroban smart contract where approved issuers register and verify certificates, anyone checks proof at a public URL with no login, and employers pay graduates in XLM on Stellar testnet, all on-chain.
Why Stellar: Sub-cent fees and 5-second finality make issuing credentials cheap enough that skipping it makes no sense. simulateTransaction lets anyone verify with zero wallet setup. Native XLM via SAC closes the loop from proof to payout on one chain.
Feature Gallery
Live Trust Artifact
Every credential produces a public Verified Badge URL - no wallet, no login, no API key. Green means verified on-chain. Amber means issued but not yet verified.
Contract on Stellar Expert: CAD6C24P…ISZCV
Architecture
Full architecture document:
docs/reference/architecture.md
sequenceDiagram
autonumber
actor Issuer as Approved Issuer
actor Student
actor Employer
participant FE as Stellaroid Earn (Next.js)
participant FR as Freighter
participant SC as Soroban contract<br/>(stellaroid_earn)
participant XLM as Stellar testnet
Issuer->>FE: Open /app, paste student wallet + cert hash
FE->>FR: requestAccess + signTransaction(register_certificate)
FR->>XLM: Submit tx
XLM->>SC: register_certificate(issuer, student, hash, title, cohort, uri)
SC-->>XLM: cert_reg event
Issuer->>FE: Click "Approve credential"
FE->>FR: signTransaction(verify_certificate)
FR->>XLM: Submit tx
XLM->>SC: verify_certificate(verifier, hash)
SC-->>XLM: cert_ver event
Student->>FE: Share /proof/<hash> (QR or link)
Note over FE,SC: Read-only get_certificate via simulateTransaction
Employer->>FE: Open /app as Employer, paste hash + amount
FE->>FR: signTransaction(link_payment)
FR->>XLM: Submit tx (XLM transfer + payment event)
Design decisions:
- soroban-sdk 26.1 with typed
#[contracterror]enum (17 variants), persistent + instance storage, TTL 518k/1.04M ledgers - Issuer trust layer: self-register → admin approve → issue credentials. Suspended issuers are blocked on-chain
- Two read paths: server-side RSC with
revalidate=60(CDN-cached proof pages) + client-sidesimulateTransaction(dashboard state) - One write path: Freighter signs →
sendTransaction→ poll for result - CSP locks
connect-srcto*.stellar.organd the WalletConnect relay - no other third-party origins
Contract Integration (Frontend to Soroban)
The frontend talks to the deployed stellaroid_earn contract with @stellar/stellar-sdk. The client lives in frontend/src/lib/contract-client.ts (writes + client-side reads) and frontend/src/lib/contract-read-server.ts (server-rendered proof pages). The SDK is lazy-loaded so its multi-megabyte bundle stays out of every route's first load.
// frontend/src/lib/contract-client.ts
import type * as StellarSdk from "@stellar/stellar-sdk";
// Lazy-load the SDK once, on the first contract read or wallet action.
const getSdk = () => import("@stellar/stellar-sdk");
// READ (no wallet): simulate an invocation against Soroban RPC.
const server = new sdk.rpc.Server(appConfig.rpcUrl);
const sim = await server.simulateTransaction(tx);
const value = sdk.scValToNative(sim.result.retval);
// WRITE: build with TransactionBuilder, wallet signs, submit + poll.
const tx = new sdk.TransactionBuilder(account, {
fee: sdk.BASE_FEE,
networkPassphrase: getExpectedNetworkPassphrase(),
})
.addOperation(
sdk.Operation.invokeContractFunction({
contract: appConfig.contractId, // NEXT_PUBLIC_SOROBAN_CONTRACT_ID
function: method, // e.g. "verify_certificate"
args, // sdk.nativeToScVal(...) per argument
}),
)
.setTimeout(30)
.build();
const signedXdr = await wallet.sign(tx.toXdr()); // Freighter / Albedo / Stellar Wallets Kit
const sent = await server.sendTransaction(sdk.TransactionBuilder.fromXdr(signedXdr, passphrase));
const result = await server.pollTransaction(sent.hash);
Every public contract function has a matching typed wrapper in the client. The wrapper passes the exact contract function name to Operation.invokeContractFunction:
Contract function (contracts/stellaroid_earn/src/lib.rs) | Frontend wrapper (contract-client.ts) |
|---|---|
register_issuer | registerIssuer() |
approve_issuer | approveIssuer() |
suspend_issuer | suspendIssuer() |
get_issuer | getIssuer() (read / simulateTransaction) |
register_certificate | registerCertificate() |
verify_certificate | verifyCertificate() |
get_certificate | getCertificate() (read / simulateTransaction) |
revoke_certificate | revokeCertificate() |
suspend_certificate | suspendCertificate() |
reward_student | rewardStudent() |
link_payment | linkPayment() |
create_opportunity | createOpportunity() |
fund_opportunity | fundOpportunity() |
submit_milestone | submitMilestone() |
approve_milestone | approveMilestone() |
release_payment | releasePayment() |
refund_opportunity | refundOpportunity() |
get_opportunity | getOpportunity() (read / simulateTransaction) |
The network passphrase in NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE must match the network the contract is deployed on (testnet), or the wallet rejects the signature.
Quick Start
Prerequisites
- Rust (stable) +
wasm32v1-nonetarget - Stellar CLI v26+
- Node.js 20+ and npm
- Freighter browser extension set to Testnet
Full setup guide: docs/reference/pre-workshop-setup-guide.pdf
Smart Contract
cd contracts/stellaroid_earn
make test # cargo test (contract suite)
make build # builds wasm32v1-none target
# Deploy to testnet
stellar keys generate my-key --network testnet --fund
stellar contract deploy \
--wasm target/wasm32v1-none/release/stellaroid_earn.wasm \
--source my-key --network testnet
CI runs the contract gate with cargo test -p stellaroid_earn --locked and cargo build -p stellaroid_earn --target wasm32v1-none --release --locked in Contract CI.
Frontend
cd frontend
cp .env.example .env.local # fill in contract ID + read address
npm install
npm run dev # http://localhost:3000
Environment variables (.env.local):
NEXT_PUBLIC_STELLAR_RPC_URL=https://soroban-testnet.stellar.org
NEXT_PUBLIC_STELLAR_NETWORK=TESTNET
NEXT_PUBLIC_STELLAR_NETWORK_PASSPHRASE=Test SDF Network ; September 2015
NEXT_PUBLIC_SOROBAN_CONTRACT_ID=<your deployed contract ID>
NEXT_PUBLIC_STELLAR_ADMIN_ADDRESS=<your admin G... address>
NEXT_PUBLIC_STELLAR_READ_ADDRESS=<any funded testnet address for read-only calls>
NEXT_PUBLIC_SOROBAN_ASSET_ADDRESS=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC
NEXT_PUBLIC_SOROBAN_ASSET_CODE=XLM
NEXT_PUBLIC_SOROBAN_ASSET_DECIMALS=7
NEXT_PUBLIC_STELLAR_EXPLORER_URL=https://stellar.expert/explorer/testnet
NEXT_PUBLIC_CANONICAL_URL=https://stellaroid.tech
Verifiable On-Chain
Every action in the demo flow is a real transaction on Stellar testnet. Click any hash to verify on Stellar Expert.
| Action | Tx Hash | Result |
|---|---|---|
init | faf278d7…85e6 | Contract initialized with admin + XLM token |
register_certificate | 8c20a944…a0e8 | Demo credential hash registered for student |
verify_certificate | 67137aa8…2cb9 | Status changed to Verified |
Live certificates (testnet, contract CAD6C24P…):
| Hash | Cohort | Status |
|---|---|---|
c02ce160…aea3 | Stellar PH Bootcamp 2026 | Verified |
Live testnet contract CAD6C24P… is tag v3.0.0 (19 functions). The three refresh and expiry writes exist in this source tree and stay unused against that WASM until a new deploy.
Contract Functions
| Function | Caller | Description |
|---|---|---|
init(admin, token) | Deployer | Initialize contract with admin address and XLM token |
register_issuer(address, name, website, category) | Anyone | Submit issuer application (Pending status) |
approve_issuer(admin, issuer) | Admin | Approve an issuer to register credentials |
suspend_issuer(admin, issuer) | Admin | Suspend a misbehaving issuer |
refresh_issuer(actor, issuer) | Issuer or admin | Store a refresh date and extend issuer TTL (source only until a new deploy) |
get_issuer(issuer) | Anyone | Read issuer record and status |
register_certificate(issuer, student, cert_hash, title, cohort, metadata_uri) | Approved issuer | Register a credential hash for a graduate |
verify_certificate(issuer, cert_hash) | Admin or issuer | Mark a credential Verified |
revoke_certificate(issuer, cert_hash) | Admin or issuer | Permanently revoke a credential |
suspend_certificate(issuer, cert_hash) | Admin or issuer | Temporarily suspend a credential |
set_credential_expiry(actor, cert_hash, expires_at) | Issuer or admin | Set or clear a validity window (source only until a new deploy) |
renew_certificate(actor, cert_hash, expires_at) | Issuer or admin | Renew an elapsed window and restore Issued or Verified (source only until a new deploy) |
reward_student(student, cert_hash, amount) | Admin | Admin-initiated XLM payment to a graduate |
link_payment(employer, student, cert_hash, amount) | Employer | Employer pays graduate in XLM, linked to credential |
get_certificate(cert_hash) | Anyone | Read full credential record and status |
create_opportunity(employer, candidate, cert_hash, title, amount, milestone_count) | Employer | Open a paid-trial escrow against a verified credential |
fund_opportunity(employer, opp_id) | Employer | Escrow the full trial amount into the contract |
submit_milestone(candidate, opp_id) | Candidate | Mark the next milestone as delivered |
approve_milestone(employer, opp_id) | Employer | Approve the submitted milestone |
release_payment(employer, opp_id) | Employer | Release the approved milestone share to the candidate |
refund_opportunity(employer, opp_id) | Employer | Return remaining escrowed funds to the employer |
get_opportunity(opp_id) | Anyone | Read a paid-trial opportunity record |
Credential Status Lifecycle
Issued --> Verified (issuer or admin calls verify_certificate)
--> Revoked (issuer or admin calls revoke_certificate)
--> Suspended (issuer or admin calls suspend_certificate)
--> Expired (past a nonzero expires_at window; renew_certificate restores Issued or Verified)
Tests
Contract tests cover the trust layer, access control, revocation, opportunity escrow, milestone caps, issuer refresh dates, credential expiry, and events:
running 15 tests
test test::t1_happy_path_with_approved_issuer ... ok
test test::t2_unapproved_issuer_cannot_issue ... ok
test test::t3_suspended_issuer_cannot_issue ... ok
test test::t4_wrong_approved_issuer_cannot_verify ... ok
test test::t5_revoked_credential_blocks_payment ... ok
test test::t6_issuer_events_emit ... ok
test result: ok. 15 passed; 0 failed; 0 ignored
| Test | What it verifies |
|---|---|
| t1 | Happy path: approved issuer registers + verifies credential, admin rewards student |
| t2 | Pending (unapproved) issuer cannot register a credential |
| t3 | Suspended issuer cannot register a credential |
| t4 | Approved issuer A cannot verify issuer B's credential |
| t5 | Revoked credential blocks downstream payments |
| t6 | Events emitted correctly for init, register_issuer, approve_issuer |
| t7-t10 | Opportunity create, fund, submit, approve, release, refund, and invalid transition behavior |
| t11 | Opportunity milestone count is capped to prevent unbounded work/rendering |
| t12 | Employer can refund after candidate submission to avoid escrow lock |
| t13 | Issuer records carry register and refresh dates; only issuer or admin can refresh |
| t14 | Credential expiry blocks payment after the window; renew restores Verified access |
| t15 | Revoked credentials cannot have expiry set or be renewed |
Security
Shortened here. Read the whole README on GitHub.
Tools it offers (6)
What this server listed when Ahel dialed its public endpoint in Sep 2026, with no key and no account of yours. The names are the server’s own.
verify_credentialget_issuerlist_opportunitiesget_opportunityrecent_eventsget_contract_info
Signals
- GitHub stars
- 6
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Delivery
- stellaroid-earn MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
- Item type
- mcp-server
- Key
io-github-iron-mark-stellaroid-earn- Source
- github.com/iron-mark/hackathon-stellaroid_earn
- Hosted endpoint
https://stellaroid.tech/api/mcp
github.com/iron-mark/hackathon-stellaroid_earn