Private send for the wallet you already have.
β Live on Ethereum Sepolia β confidential transfers, claim-links & auditor grants proven on-chain. 148 tests green. Not a mock.
Etherscan sees 32 bytes. Your landlord sees nothing.
The problem. Every ERC-20 transfer is a public payslip β salary, rent, settlements, donations, naked forever. The usual "privacy" answers force a new chain, a mixer with regulatory stigma, or a new wallet. Normal people won't switch wallets to get what banks give them by default.
The approach. NoxSend adds a private-send flow to the wallet you already use, on the token you
already hold β without modifying either. Wrap USDC into confidential cUSD (ERC-7984, 1:1,
redeemable), send with the amount encrypted end-to-end inside Intel TDX via iExec Nox, and reveal
it to exactly whom you choose: the recipient (viewer ACL), an auditor if you say so (addViewer),
and no one else. Wallet-less recipients get a claim link β private Venmo, self-custodial.
The one flow, with depth: wrap β private send β recipient decrypt β (unwrap | claim-link | auditor-grant)
β live on Sepolia, zero mock data.
Every step below was executed on-chain against the live Nox Handle Gateway (no mocks, no local stub). Deployed contracts:
| Contract | Address | |
|---|---|---|
| ConfidentialUSD (cUSD) wrapper | 0x82C281D7403e44d61968c2F49751a56877468991 |
ERC20ToERC7984Wrapper |
| SendLinkEscrow | 0xF1Df763b425e20c16c039d80Ef1309c5a4A47f62 |
claim-link escrow |
| DemoUSD (underlying, faucet) | 0x486c4B8009ACf0BfE26268512F27200e48BD735C |
6-decimals, mirrors USDC |
| Nox protocol (NoxCompute) | 0x24ef36ec5b626d7dcd09a98f3083c2758f0f77bf |
ACL + proof validation |
Proof transactions β one unified npm run e2e run (all steps, single pass; full log in
docs/proof/e2e.log):
| Step | Tx |
|---|---|
| Wrap 5,000 dUSD β cUSD | 0x83e5e9dbβ¦ |
| Private send 1,850 cUSD (calldata = a 32-byte handle, no amount) | 0xb03d69a2β¦ |
Auditor grant (addViewer) β isViewer auditor=true / stranger=false |
0x387fdc2f⦠|
| Claim-link create (operator-pull) | 0x93d639c9β¦ |
| Claim (Bob, wallet-less recipient) | 0x18cfc9fa⦠|
| Reclaim (post-expiry refund) | 0x110b56c6β¦ |
| Unwrap burn β | 0xe5645f66β¦ |
| β finalizeUnwrap (proof-gated) | 0x205905ecβ¦ |
git clone <this-repo> noxsend && cd noxsend
npm install
cp .env.example .env
# set DEPLOYER_PRIVATE_KEY to a throwaway key funded with ~0.03 Sepolia ETH.
# (SEPOLIA_RPC_URL defaults to a public node; ETHERSCAN_API_KEY is optional.)
npm run compile # solc 0.8.35 (auto-downloaded)
npm run gateway-smoke # proves the Nox gateway works with just your key (no signup)
npm run deploy # DemoUSD + cUSD + SendLinkEscrow -> Sepolia; writes deployments.json
npm run e2e # full wrapβsendβdecryptβauditorβclaimβreclaimβunwrap, live, zero mock
npm test # 122 @noxsend/core unit tests (all green)
npm run test:contracts # 26 Hardhat contract tests (DemoUSD + ConfidentialUSD + SendLinkEscrow)
npm run coverage:check # solidity-coverage + gate: 100% on all metrics for own contracts/
# frontend
cd web && npm run dev # http://localhost:3000 (connect MetaMask/Rabby on Sepolia)No Nox account or API key is required. The Handle Gateway is self-serve;
encryptInputworks with only a funded EOA (seefeedback.md#1). Real Circle Sepolia USDC is the documented primary asset; the demo uses the deployedDemoUSDfaucet so a dry Circle faucet never blocks you.
Copy the template and fill it in (.env is gitignored β never commit real keys; use throwaway keys, Sepolia only):
cp .env.example .env| Variable | What it is | How to obtain |
|---|---|---|
DEPLOYER_ADDRESS, DEPLOYER_PRIVATE_KEY, PRIVATE_KEY |
Throwaway EOA that deploys the contracts and signs demo txs (PRIVATE_KEY mirrors the deployer key). |
Generate a key: openssl rand -hex 32 (prefix 0x). Derive its address: node -e "console.log(new (require('ethers').Wallet)('0x<hex>').address)". Fund ~0.03 Sepolia ETH from sepoliafaucet.com or the Alchemy faucet. |
SEPOLIA_RPC_URL |
Sepolia JSON-RPC endpoint. | Default public node needs no signup (rate-limited). For reliable e2e, get a free key at Alchemy or Infura β Ethereum β Sepolia. |
CHAIN_ID |
Fixed 11155111 (Sepolia). |
Do not change. |
NOX_PROTOCOL_ADDRESS |
iExec Nox protocol contract (NoxCompute β TEE ACL + proof validation). | Fixed 0x24efβ¦77bf; re-verify from the Nox docs /networks page if it redeploys. No Nox account or API key is required β the Handle Gateway is self-serve. |
DEMO_MNEMONIC |
Throwaway BIP-39 phrase the e2e derives its demo actors (Alice/Landlord/Auditor/Bob) from. | Generate your own: node -e "console.log(require('ethers').Wallet.createRandom().mnemonic.phrase)". |
ETHERSCAN_API_KEY |
Optional β only for npm run verify:contracts (publishes contract source). |
Free, ~1 min at etherscan.io/myapikey β Add β copy the ~34-char key (no 0x). |
External services (all free, testnet-only):
- iExec Nox Handle Gateway β encrypts/decrypts amounts inside Intel TDX; self-serve, no signup. Prove it with just your key:
npm run gateway-smoke. - Ethereum Sepolia β the chain everything deploys to.
- Etherscan (Sepolia) β contract source verification only.
Deployed contract addresses for this app (cUSD wrapper, SendLinkEscrow, DemoUSD faucet, Nox protocol) are in the Deployed contracts table under This is real above.
- 148 tests, all green β 122
@noxsend/coreunit tests (amounts Β· handle decoding Β· claim-link secrets Β· the full ACL role matrix Β· config) vianpm test, plus 26 Hardhat contract tests (npm run test:contracts) covering DemoUSD, ConfidentialUSD, and the full SendLinkEscrow state machine (create Β· claim Β· reclaim + every revert path). - Contract coverage β 100% on every metric (
npm run coverage:check, solidity-coverage + a gate that fails below 100%): 100% statements / branches / functions / lines across the project's owncontracts/(SendLinkEscrow, ConfidentialUSD, DemoUSD). - Live e2e (
npm run e2e) exercises the whole flow on Sepolia against the real gateway. - Latency (
npm run bench, live Sepolia):encryptInputp50 522ms / p95 1287ms Β·decryptp50 821ms / p95 1301ms Β· full send (encrypt+confirm) p50 ~14s (Sepolia block time).
Beyond the live proof, NoxSend ships a full engineering harness so judges can see this is a real product, not a weekend toy.
# ββ Quality βββββββββββββββββββββββββββββββββ
npm run lint # next lint (web/)
npm run typecheck # tsc --noEmit (web/)
npm test # 122 @noxsend/core unit tests (vitest)
npm run test:contracts # 26 Hardhat contract tests
npm run coverage:check # solidity-coverage + 100%-or-fail gate on own contracts/
npm run ci # lint + typecheck + all tests
# ββ Advanced testing ββββββββββββββββββββββββ
npm run e2e # LIVE on-chain proof: wrapβsendββ¦βunwrap on Sepolia (zero mock)
npm run e2e:web # Playwright UI E2E (demo mode β no wallet, no env)
npm run lighthouse # Lighthouse CI (perf/a11y/SEO)
# ββ Security ββββββββββββββββββββββββββββββββ
make security-scan # npm audit + license check| Layer | Tool | Status |
|---|---|---|
| Code Quality | ESLint (next lint) + TypeScript strict |
β |
| Unit Testing | Vitest β 122 @noxsend/core tests |
β |
| Contract Testing | Hardhat β 26 tests, 100% coverage all metrics (solidity-coverage, gated) | β |
| Live E2E (on-chain) | npm run e2e β full flow on Sepolia |
β |
| UI E2E | Playwright β 3 suites (demo mode), npm run e2e:web |
β |
| Security (SAST) | CodeQL | β |
| Security (SCA) | Dependabot + npm audit |
β |
| Secret Scanning | TruffleHog | β |
| Performance | Lighthouse CI | β |
CI runs a 7-stage pipeline (.github/workflows/ci.yml): Quality (frontend +
contracts, in parallel) β Security β Build β E2E β Performance β Deploy Gate β Semantic Release.
- Contracts (
contracts/) β thin, protocol unmodified:ConfidentialUSDis a 4-lineERC20ToERC7984Wrapper;SendLinkEscrowis an operator-pull claim escrow. @noxsend/core(packages/core/) β add private-send to any dApp in ~10 lines, a typed layer over@iexec-nox/handle+ ERC-7984. Pure helpers are fully unit-tested;NoxSendClientis the Node/CLI surface.web/β Next.js 14 App Router, wagmi injected connector (MetaMask/Rabby untouched), styled to the synthwave theme./verifystreams live Sepolia events + a live ACL inspector β zero mock.
import { NoxSendClient } from '@noxsend/core';
const nox = new NoxSendClient(signer, handleClient, config);
await nox.wrap('5000'); // USDC -> cUSD
await nox.sendPrivate('0xLandlord', '1850'); // encrypted amount; calldata = a 32-byte handle
await nox.decryptBalance(); // only the owner/viewers canSee ARCHITECTURE.md for the full system diagram and invariants.
ERC-7984 confidential balances + the allowThis / allow / addViewer / viewACL ACL make selective
disclosure a one-call primitive (ZK hides but cannot governed-reveal); fromExternal proof
validation keeps inputs out of calldata; the wrapper's proof-gated unwrap β finalizeUnwrap binds
redemption to a TEE decryption proof. Remove Nox and you need an FHE coprocessor, a KMS, a relayer,
and a disclosure registry β four systems, none composable with the USDC already in your wallet.
- Amount privacy only β sender/recipient addresses stay public, and wrap/unwrap amounts are visible at the wrapper boundary. Privacy lives inside cUSD.
- Beta SDK (
@iexec-nox/handle@0.1.0-beta.13) β pinned; every friction is logged infeedback.md(15 findings; the one that changed our architecture is #2). - TEE trust β Intel TDX + iExec gateway liveness (status.noxprotocol.io).
- Claim links take a time-bound operator grant to the escrow (auto-revoked right after funding); direct sends take zero operator authority.
The shipped scope is the core flow with depth + the reusable @noxsend/core + CLI + dApp.
Designed and specced but intentionally not in this build (each additive, none blocking the
zero-mock core): ENS send/request Β· confidential batch send Β· a ProofOfReceipt "received β₯ $X"
receipt (Nox.le + select + allowPublicDecryption) Β· opt-in time-bound standing orders
(setOperator) Β· a The Graph subgraph for the feed. These exercise more of the Nox arithmetic
surface and are the natural next increments.
MIT Β© 2026 Edy Cu
100% built during the WTF!! Hackathon (iExec Nox). A shared Nox-integration core (@noxsend/core) is
designed to be reused by sibling entries. Nothing reused from the Vibe Coding edition. Throwaway keys
only, Sepolia only, never mainnet.