
Copy one snippet, run it on testnet in 5 minutes, earn a 3D badge. Free, no funds needed.
10K+ package downloads on npm and PyPI · 2 SCF Instawards · Open source
No cash prizes. The Champion gets a hoodie.
English voiceover with captions.
Everything runs on testnet. Your key, your receipt.

npm i nirium @stellar/stellar-sdk@16import { Agent } from 'nirium';
import { Keypair } from '@stellar/stellar-sdk';
import { createHash } from 'node:crypto';
const kp = Keypair.random(); // a new testnet key, no funds needed. Save kp.secret() to reuse it
const sha = createHash('sha256').update('my first Niriumtober receipt').digest('hex');
const signature = Buffer.from(kp.sign(Buffer.from(`nirium-audit-v1:${sha}`))).toString('base64');
const agent = new Agent({ baseUrl: 'https://nirium-agent.fly.dev' });
const { cid } = await agent.anchorAuditRecord({ hash: sha, tag: 'niriumtober', agent: { key: kp.publicKey(), signature } });
console.log('CID:', cid);
console.log('Your public key:', kp.publicKey());Save it as receipt.mjs and run node receipt.mjs. It prints your CID and your public key. No account and no funds needed.
Using Claude or Cursor? Give it the Nirium skill and let it build this for youOpen the form, paste your CID and your public key. It is public, so never paste your secret key.A repo is optional for Builder. Mainnet Builder and Champion need a public repo.
Send your proofThat's it: you just earned Builder 🔨




The recognition for the best project or contribution of all Niriumtober. One only.
The Nirium team picks it at the close, on Nov 2, among every project and contribution with valid evidence. If none deserves it, it is not awarded.

🎃 An official Niriumtober hoodie, shipped to you.
One hoodie, for the Champion only. Chosen by the Nirium team on Nov 2 on the public criteria above. No chance involved, and no purchase or payment of any kind is needed to compete: Audit Trail on testnet is free.
Free shipping within Mexico. Outside Mexico, the Champion chooses: cover international shipping, or get a one-of-one 3D Champion badge with their project's name, made by the team.
Champion adds no points: it is awarded apart from the points table. Its badge uses the same issuer key and tag niriumtober-2026, with badge: "champion".

agent signed by your key. Free during the beta.Optional, with your own funds and at your own risk. We never fund or refund mainnet transactions.
Use your own mainnet key in STELLAR_SECRET. Never paste your secret key anywhere.
import { Agent } from 'nirium';
import { Keypair } from '@stellar/stellar-sdk';
import { createHash } from 'node:crypto';
const kp = Keypair.fromSecret(process.env.STELLAR_SECRET); // your own key
const sha = createHash('sha256').update('my evidence').digest('hex');
const signature = Buffer.from(kp.sign(Buffer.from(`nirium-audit-v1:${sha}`))).toString('base64');
const agent = new Agent({ baseUrl: 'https://nirium-agent-mainnet.fly.dev' });
const { cid } = await agent.anchorAuditRecord({ hash: sha, tag: 'niriumtober', agent: { key: kp.publicKey(), signature } });
console.log('CID:', cid);Use your own mainnet key in STELLAR_SECRET. Never paste your secret key anywhere. Your account needs a USDC trustline and a USDC balance on mainnet.
import { Agent } from 'nirium';
const agent = new Agent({ baseUrl: 'https://nirium-agent-mainnet.fly.dev' });
agent.initX402({ secretKey: process.env.STELLAR_SECRET, network: 'stellar:pubnet' }); // your own key, with USDC
const res = await agent.x402Fetch('https://nirium-agent-mainnet.fly.dev/api/v1/premium/market'); // 0.05 USDC
console.log(res.status, JSON.parse(atob(res.headers.get('payment-response'))).transaction); // tx hashMainnet Builder needs a public repo.
Anchor again on mainnet on a second day: +2 points.
Priorities, not promises.
Testnet tokens are free and have no real value. This page only ever asks for your public key, never your secret key.
CETES has no faucet: it comes from the DEX, in the script.
One run: it creates a key, funds it with Friendbot, adds the USDC and CETES trustlines and swaps 20 XLM into each on the testnet DEX. If the DEX has no USDC route, it adds the trustline and sends you to the Circle faucet.
import { Keypair, Horizon, TransactionBuilder, Operation, Asset, Networks } from '@stellar/stellar-sdk';
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
const FILE = 'niriumtober-testnet.key';
const horizon = new Horizon.Server('https://horizon-testnet.stellar.org');
const USDC = new Asset('USDC', 'GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5'); // Circle
const CETES = new Asset('CETES', 'GC3CW7EDYRTWQ635VDIGY6S4ZUF5L6TQ7AA4MWS7LEQDBLUSZXV7UPS4');
// 1. A new testnet key, saved next to this script (run it again and it reuses the same key)
if (!existsSync(FILE)) writeFileSync(FILE, Keypair.random().secret(), { mode: 0o600 });
const kp = Keypair.fromSecret(readFileSync(FILE, 'utf8').trim());
// 2. Testnet XLM from Friendbot
const funded = await horizon.loadAccount(kp.publicKey()).then(() => true, () => false);
if (!funded) await fetch(`https://friendbot.stellar.org?addr=${kp.publicKey()}`);
// 3. Trustlines for USDC and CETES, and 4. swap 20 XLM into each on the testnet DEX
const tx = new TransactionBuilder(await horizon.loadAccount(kp.publicKey()), { fee: '1000', networkPassphrase: Networks.TESTNET })
.addOperation(Operation.changeTrust({ asset: USDC }))
.addOperation(Operation.changeTrust({ asset: CETES }));
const toAsset = (a) => (a.asset_type === 'native' ? Asset.native() : new Asset(a.asset_code, a.asset_issuer));
for (const asset of [USDC, CETES]) {
const [route] = (await horizon.strictSendPaths(Asset.native(), '20', [asset]).call()).records;
if (!route) {
console.log(asset === USDC ? 'No DEX route to USDC: now ask for USDC at https://faucet.circle.com' : 'No DEX route to CETES right now, try again later');
continue;
}
tx.addOperation(Operation.pathPaymentStrictSend({
sendAsset: Asset.native(), sendAmount: '20', destination: kp.publicKey(), destAsset: asset,
destMin: (Number(route.destination_amount) * 0.9).toFixed(7), path: route.path.map(toAsset),
}));
}
const built = tx.setTimeout(60).build();
built.sign(kp);
console.log('Transaction:', (await horizon.submitTransaction(built)).hash);
// 5. What you have now
console.log('Public key:', kp.publicKey());
for (const b of (await horizon.loadAccount(kp.publicKey())).balances) console.log(` ${b.asset_code ?? 'XLM'}: ${b.balance}`);
console.log(`Secret key saved in ./${FILE}. Keep it out of git and never share it.`);Save it as setup.mjs and run node setup.mjs (same install as step 1). It prints your public key and balances, and keeps the secret key in niriumtober-testnet.key, out of git.
Any node on testnet earns you Builder. Use several: Champion is decided by real use.
Same install as step 1: npm i nirium @stellar/stellar-sdk@16. Every snippet below was run on testnet.
Anchor a signed receipt of anything your agent did. Anyone can verify it.
import { Agent } from 'nirium';
import { Keypair } from '@stellar/stellar-sdk';
import { createHash } from 'node:crypto';
const kp = Keypair.random(); // a new testnet key, no funds needed. Save kp.secret() to reuse it
const sha = createHash('sha256').update('my first Niriumtober receipt').digest('hex');
const signature = Buffer.from(kp.sign(Buffer.from(`nirium-audit-v1:${sha}`))).toString('base64');
const agent = new Agent({ baseUrl: 'https://nirium-agent.fly.dev' });
const { cid } = await agent.anchorAuditRecord({ hash: sha, tag: 'niriumtober', agent: { key: kp.publicKey(), signature } });
console.log('CID:', cid);
console.log('Your public key:', kp.publicKey());node receipt.mjs
Pay per request for market data, from your own key.
import { Agent } from 'nirium';
const agent = new Agent({ baseUrl: 'https://nirium-agent.fly.dev' });
agent.initX402({ secretKey: process.env.STELLAR_SECRET, network: 'stellar:testnet' }); // a testnet key holding testnet USDC
const res = await agent.x402Fetch('https://nirium-agent.fly.dev/api/v1/premium/market'); // 0.05 testnet USDC
console.log(res.status, JSON.parse(atob(res.headers.get('payment-response'))).transaction); // tx hashSTELLAR_SECRET=S... node pay.mjs
Pay several people in one run. You sign it, Nirium never does.
import { Agent } from 'nirium';
import { Keypair, TransactionBuilder, Networks } from '@stellar/stellar-sdk';
const kp = Keypair.fromSecret(process.env.STELLAR_SECRET); // pays: needs testnet USDC
const agent = new Agent({ apiKey: process.env.NIRIUM_API_KEY, baseUrl: 'https://nirium-agent.fly.dev' }); // free key: nirium.xyz/keys
const run = await agent.createPayoutRun({ treasury: kp.publicKey(), acknowledgeTerms: true,
recipients: [{ wallet: process.env.TO_1, amount: '0.5' }, { wallet: process.env.TO_2, amount: '0.5' }] }); // each needs a USDC trustline
const tx = TransactionBuilder.fromXDR(run.xdr, Networks.TESTNET); tx.sign(kp); // you sign, Nirium never does
const done = await agent.submitPayout(run.runId, tx.toXDR());
console.log(done.txHash, done.cid);STELLAR_SECRET=S... NIRIUM_API_KEY=sk_... TO_1=G... TO_2=G... node payouts.mjs
Add payments, receipts and payouts to your app or agent in TypeScript.
npm i nirium @stellar/stellar-sdk@16Let Claude, Cursor or any MCP assistant use Nirium for you.
npx nirium-mcpSet the environment variables from its README. The free tools work without them.
Give it to Claude, Cursor or your AI assistant and it builds a paid x402 API for you, in one command.
mkdir -p ~/.claude/skills/nirium-agentic-payments && curl -fsSL https://raw.githubusercontent.com/nirium-protocol/nirium/main/skills/nirium-agentic-payments/SKILL.md -o ~/.claude/skills/nirium-agentic-payments/SKILL.mdThe command above installs it for Claude Code. With other assistants, paste the link to the skill.
Pay and anchor receipts with a wallet created through Pollar.
npm i nirium-pollar-adapterHow to claim an issue: comment with a plan for that specific issue, the files you will touch and how you will test it. A bare “I'll take it” or a generic template does not count. The first valid plan gets it, one active issue per person. If there is no draft PR within 48 hours of assignment, the issue goes back to the pool. A merged PR earns Contributor.
Halloween edition: a short, original horror story about an AI agent, a payment or a Stellar transaction that goes wrong. The key that signed at midnight, the receipt that was never anchored, the facilitator that answered 402 forever. Add community/horror-stories/<your-github-handle>.md. English or Spanish.
Done when: One file, 100 to 300 words, your name or handle at the end. Fictional characters only, never a real person or project.
Add community/ascii/<your-github-handle>-<name>.txt with one piece: a jack-o'-lantern, the Nirium mark, a ghost, a bat, a haunted node. Plain ASCII characters only.
Done when: One file, at most 80 columns and 40 lines, and the PR pastes what cat prints in a terminal.
It is the shortest README under examples/. Add examples/go-x402/README.es.md and a one-line link to it at the top of the English README.
Done when: Commands, code blocks and header names like PAYMENT-SIGNATURE are unchanged, and nothing is added that the English text does not say.
anchor_audit_record() exists in the Python package, but examples/ has no Python example for Audit Trail. Add examples/python-audit-anchor: hash a file, anchor it on testnet, fetch the CID back and check the hash.
Done when: README with exact commands, and the PR shows a real testnet CID produced by running it.
packages/sdk-python/tests/ only covers the LangChain tool and the WebSocket client. Add tests for anchor_audit_record(): payload shape, hash vs record, and the error when neither is given. Mock HTTP, no network.
Done when: pytest passes locally and the PR pastes the output.
The verification model is only written up in the GitHub Action's README. Add docs/verify-audit-cid.md: fetch the document, recompute sha-256 over record, rebuild nirium-audit-v1:<sha256> and check the ed25519 signature against agent.key.
Done when: Every step is a copy-paste command, and it is checked against a real testnet CID cited in the doc.
There is no Spanish file in the repo. Translate docs/quickstart-x402.md to docs/es/quickstart-x402.md and link both ways.
Done when: Commands and code blocks are unchanged, and you ran the quickstart on testnet while translating it (hash in the PR).
Add packages/sdk-python/README.es.md with a link at the top of the English README. Keep the known limits it states (for example, MPP Charge in Python) exactly as written.
Done when: Same sections as the English README, nothing added that the English one does not say.
examples/express-x402 wires @x402/express by hand; only the Vercel example uses x402Serve(). Add a minimal Express server that charges for one route with x402Serve() on stellar:testnet.
Done when: A paid request settles on testnet and the PR includes the settlement tx hash.
The Python README says init_mpp()/mpp_fetch() cannot pay an MPP Charge server today. Fix it for testnet only, matching what the TypeScript client already does.
Done when: A real payment to the hosted testnet /api/v1/mpp/signals with its tx hash, plus a test. The README note is updated in the same PR.
No example covers Payouts. Add one that builds a two-recipient run on testnet with acknowledgeTerms, signs it with a throwaway testnet key and submits it.
Done when: Testnet tx hash in the PR. The example never asks for a mainnet key.
get_reporting_summary() and get_reporting_export() have no example. Add a short script that prints the testnet summary and saves the export to a file.
Done when: Runs against testnet; the PR pastes the command and the first lines of output.
examples/ has twelve folders and no index. Add examples/README.md with one line per example: what it shows, language, and network.
Done when: Every folder is listed and every link resolves.
The pre-sign policy hook decides one payment at a time. Write a design note on spending caps per time window, per destination and per asset, built on top of it. Related: #127.
Done when: docs/research/aggregate-spending-caps.md with at least 3 designs compared, a policy in pseudocode and the edge cases: retries, concurrent payments, a restart mid-window.
Can one DeFindex vault on testnet hold USDC, XLM and CETES at once? Find out, with sources.
Done when: docs/research/defindex-multi-asset-testnet.md with a table of testnet contract ids, each with a stellar.expert link or a read-only call, and a clear yes or no with what is missing.
Compare an Audit Trail receipt (a signed hash on IPFS) with W3C Verifiable Credentials and C2PA.
Done when: docs/research/audit-receipts-vs-vc-c2pa.md with a comparison table, one real testnet CID mapped field by field to a credential, and the gaps on each side.
Port the TypeScript pre-sign policy hook to the Python package: ALLOW, DENY or WAIT, with contextHash and expiresAt. Anything but a valid ALLOW signs nothing.
Done when: pytest passes for each verdict, a wrong contextHash and an expired expiresAt, plus a testnet tx hash of a payment allowed by the policy.
The Action fetches from one IPFS gateway, and today its default answers 429. Try several gateways in order and report which one answered. Related: #135.
Done when: Tests for a downed first gateway and for a real testnet CID pass, and dist/index.js is rebuilt.
GET /api/v1/premium/market0.05 USDC per call, paid from your account
POST /api/audit/logFree during beta. Counts when the anchor carries agent signed with your key
GET /api/reporting/summaryLive on mainnet, but read-only: it returns Nirium's own totals and leaves no record tied to your key, so it adds no points alone
GET /api/v1/mpp/signalsVerified on testnet. Never tested on mainnet
POST /api/payroll/runTestnet only for Niriumtober
POST /api/treasury/rebalance/proposeTestnet only for Niriumtober
Testnet points (2) are earned once, whatever nodes you use. Mainnet points are per node.
| Accepted PR from the list (technical or fun) | 1 |
| Any node on testnet, from your own project | 2 |
| Audit Trail or x402 Market on mainnet, with your key | +3 per node |
| Mainnet use on 2 or more different days (UTC) | +2 |
Points only set the order of the perks. There is no public leaderboard. Champion is awarded apart.
Everything in the form is public, so never paste a secret key.
How to claim an issue: comment with a plan for that specific issue, the files you will touch and how you will test it. A bare “I'll take it” or a generic template does not count. The first valid plan gets it, one active issue per person. If there is no draft PR within 48 hours of assignment, the issue goes back to the pool. A merged PR earns Contributor.
AI is welcome, unreviewed AI is not. Use any tool you like, but your PR must show you understood and ran it:
For the fun issues, testing means showing the result: the file renders, the story reads well, the translation matches. No hash or CID needed.
Each badge is a receipt Nirium signs and anchors in Audit Trail on mainnet, at our cost. It cites your evidence. Badge anchors are ours: we never count them as user activity.
| event | "niriumtober-2026" |
| badge | "contributor" | "builder" | "mainnet-builder" | "champion" |
| github | "@handle" |
| project | repo URL |
| nodes | ["audit", "x402-market"] |
| network | "testnet" | "mainnet" |
| evidence | your CIDs, tx hashes or PR URL |
| participant_key | your G... address |
| issued_at | ISO-8601 |
record and compare it with content_sha256.nirium-audit-v1:<sha256> and check the ed25519 signature against agent.key, which must be the issuer key below.agent.key, or their tx on Horizon.niriumtober-2026, and badge: "champion" in the record.Niriumtober issuer key: GBPDN4LQFQ4YJMP3Y43ZQ5PABLAMRID6IF52PGYILLHECC2ZDKH2NNY5. Steps 1-3 are what the verify-audit-cid GitHub Action already does.