Generated Computers
Locals는 Apple Silicon 엔진으로 로컬 LLM을 최대 3배 빠르게 실행하는 Generated Computers 제품
Celo Sepolia에서 요청당 1 CELO, GitHub 로그인 시 3 CELO 제공하는 무료 테스트넷 파셋, HTTP API 지원
Get 1 CELO per request on Celo Sepolia, or 3 CELO signed in with GitHub. A free testnet faucet with an HTTP API for scripts and AI agents.
개발 도구TypeScript · JavaScriptGitHub @celo-org온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Celo Testnets Faucet
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗This Repo contains the code for the celo testnets faucet. This is contained in 2 apps.
The firebase app contains functions which do the actual fauceting.
The web app contains a UI for making requests.
The web app deploys automatically to vercel.
The deploy-chains gh actions deploys functions to staging and production environments from staging and master branches respectively
Note other branches are not deployed automatically but can be by manually triggering the flow
To set up the web app to run locally:
navigate to the apps/web folder
$ cd apps/web
link your local repository to the faucet project on Vercel
$ yarn dlx vercel@latest link
You'll be asked to authenticate with your Vercel account. Once you've done that, you'll be
guided through a series of prompts to link your local project to the faucet Vercel project.
? Set up “~/Documents/celo-org/faucet/apps/web”? [Y/n] y
? Which scope should contain your project? Celo Ecosystem Project Hosting
? Link to existing project? [y/N] y
? What’s the name of your existing project? faucet
✅ Linked to c-labs/faucet (created .vercel)
fetch environment variables from Vercel
$ yarn dlx vercel@latest env pull
If you get an error like Error! No project found, you may need to run vercel link again.
If everything worked, you should see a message like this:
> Downloading `development` Environment Variables for Project faucet
✅ Created .env.local file [249ms]
run the app locally
$ yarn dev
You should see a message like this:
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from /Users/arthur/Documents/celo-org/faucet/apps/web/.env.local
You can now view the app in your browser at http://localhost:3000.
To set up the firebase app to run locally:
apps/firebase folder
$ cd apps/firebase
$ yarn dlx firebase-tools@latest login
You'll be asked to authenticate with your Firebase account.$ yarn run preserve
engines.node in
firebase/package.json. Currently this is Node 24 at the time of writing.
$ nvm use <the-required-node-version>
$ yarn run serve
The browser flow is gated on reCAPTCHA v3, which scores headless callers badly and cannot be solved without driving a real browser. Scripts and AI agents use an API key instead.
This section used to be the only place the API was documented, which meant an agent had to fetch and parse a README on GitHub to learn how to behave. The same contract is now published on the faucet's own domain, in formats meant to be read by a machine:
| File | For |
|---|---|
/openapi.json | The schema. Endpoints, request and response shapes, every error code. |
/llms-full.txt | The full reference as prose, for assistants that read rather than call. |
/llms.txt | The short index. |
Keep this section and those files in agreement. apps/web/tests/geo-assets.test.ts
asserts the published limits and payout amounts still match the constants the
code enforces, but the prose is on you.
Sign in with GitHub at /keys and create one.
The key is shown once and only a hash of it is stored, so it cannot be
recovered — create a new one if you lose it. You may hold up to 2 keys and they
expire after 90 days.
A key minted the way above is a human's credential handed to an agent. The faucet cannot tell one agent from another, or an agent from the person running it, because its only notion of identity was a GitHub account — and an agent cannot hold one.
An agent registered under ERC-8004 has an identity of its own, so it can mint its own key. Two calls, no browser, no OAuth, no human:
# 1. Ask for a challenge.
curl -X POST https://faucet.celo.org/api/keys/challenge \
-H 'Content-Type: application/json' \
-d '{"agentId":"2"}'
# → {"message":"…","nonce":"…","expiresAt":…,"agentWallet":"0x…"}
# 2. Sign that message with the agent wallet, then exchange it.
curl -X POST https://faucet.celo.org/api/keys/agent \
-H 'Content-Type: application/json' \
-d '{"agentId":"2","nonce":"…","signature":"0x…"}'
# → 201 {"key":"cfk_prd_…","record":{…}}
The key is bound to the agent id rather than to a person, so it draws on the agent's own daily allowance. That allowance grows with the age of the registration: an agent registered less than 7 days ago gets 2 requests a day, and an established one gets 10, the same as a signed-in person. Registering an agent costs a fraction of a cent, so without this one wallet could mint twenty identities and fill the shared programmatic ceiling on its own. The tier is decided at request time from the registration timestamp recorded on the key, so an agent grows into the larger allowance without minting a new key.
To revoke, ask for a challenge with "action":"revoke" and send the proof to
DELETE /api/keys/agent with the keyId. Omit keyId to revoke every key the
agent holds, which is the recovery path after a signing-key compromise: the
attacker's keys were never shown to the rightful agent, so it cannot name them.
A challenge names its action in the signed text, so a mint signature cannot be
turned into a revoke or the other way round.
Design notes, since each of these is load-bearing:
0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 on
chain 42220. Registering on Celo Sepolia costs Sepolia gas, which is what this
faucet hands out — a testnet registry would let an attacker faucet its way to
as many identities as it wanted.ownerOf. An agent whose getAgentWallet is unset is
refused with agent_wallet_unset. ownerOf is whoever holds the NFT, often a
human or a multisig, so accepting it would authenticate the operator while
reporting that an agent had signed. Agent 1 on mainnet is in exactly this
state today, so this is the common case, not an edge one.Sybil resistance is unchanged and deliberately modest: mainnet registration costs only gas. What bounds exposure is the programmatic ceiling that already existed — 20 requests per 10 minutes and 200 per day across every key. See discussion #286 for the x402 and reputation phases that turn "capped" into "costly".
Verify the whole path against a deployment with no cookie jar at all. You need
the signing key of a registered agent's wallet. If you do not hold one, register
a throwaway agent first: every register() overload in the registry sets the
agent wallet to the calling address, so one transaction from any wallet you
control (a fraction of a cent of mainnet CELO) gives you an agent id whose key
you already have.
export AGENT_SIGNING_KEY=0x... # any wallet with a little mainnet CELO
yarn --cwd apps/web register:smoke-agent # prints the new agent id
yarn --cwd apps/web smoke:agent-key \
--url https://faucet.celo.org --agent-id <id> --beneficiary 0xYourAddress
Neither script prints the key, and neither falls back to any other wallet
variable: to sign with a key held under a different name, set
AGENT_SIGNING_KEY_ENV to that name. The smoke run revokes the key it minted at
the end, so it leaves the agent's two slots as it found them and exercises the
revoke path live.
Send the key as a bearer token and omit captchaToken:
curl -X POST https://faucet.celo.org/api/faucet \
-H "Authorization: Bearer cfk_prd_…" \
-H 'Content-Type: application/json' \
-d '{"beneficiary":"0xYourAddress","network":"celo-sepolia"}'
A successful call returns HTTP 200 with {"status":"Pending","key":"…"}. The
queueing is carried by the status field, not by the status code: the payout is
accepted but not yet settled. Poll for the outcome with that key:
curl "https://faucet.celo.org/api/status?key=<key>&network=celo-sepolia"
# {"status":"Done","beneficiary":"0x…","txHash":"0x…"}
Other responses carry a machine-readable error code so you can branch without
parsing prose:
| Status | error | Meaning |
|---|---|---|
400 | — | Invalid network or beneficiary address |
401 | invalid_api_key | Missing, malformed, unknown or expired key |
401 | api_key_disabled | Programmatic access is switched off |
429 | faucet_limit_exceeded | Rate limited; honour Retry-After |
503 | faucet_unavailable | A dependency is down; honour Retry-After |
405 | — | Wrong HTTP method |
The browser flow keeps its existing 403 for rate limits; 429 is used only on
the key path, matching the Coinbase CDP faucet.
Never commit a key. Keys found in public repositories are revoked without notice. If you are integrating a tool that others will install, read the key from the user's environment — do not ship a default.
Environment variables on the web app:
| Variable | Required | Purpose |
|---|---|---|
FAUCET_API_KEY_PEPPER | yes | Secret mixed into the HMAC of every stored key. Without it, key minting and verification both fail closed. Rotating it invalidates every existing key. |
FAUCET_API_KEY_NETWORKS | no | Comma-separated networks that accept key auth. Defaults to celo-sepolia. |
PROGRAMMATIC_GLOBAL_DAILY_LIMIT | no | Daily ceiling across all keys. Defaults to 200. |
PROGRAMMATIC_BURST_LIMIT | no | Keyed requests allowed per 10 minutes across all keys. Bounds arrival rate so the payout pool cannot be locked. Defaults to 20. |
To stop all programmatic traffic immediately without a deploy, set the
api-keys:disabled key in Upstash to any truthy value. The browser flow is
unaffected. Delete it to re-enable.
apps/web/scripts/smoke-api-key.mjs exercises the whole key path over HTTP —
rejection of unissued keys, address and method validation, a real payout, the
status poll, and the returned tx hash. It needs no repo credentials:
export FAUCET_API_KEY=cfk_... # minted at <deployment>/keys
yarn --cwd apps/web smoke:api-key \
--url https://<deployment> --beneficiary 0xYourAddress
It exits non-zero if any check fails and never prints the key.
Every other test mocks the sender, so nothing otherwise proves the hash written
to goldTxHash is a real transaction. apps/firebase/src/celo-adapter.onchain.test.ts
sends a real transfer on Celo Sepolia. It is skipped unless explicitly opted in,
because it spends gas:
RUN_ONCHAIN_TESTS=1 PRIVATE_KEY=<funded key> \
yarn --cwd apps/firebase test:ci onchain
The transfer is a self-send, so only the gas fee (~0.0011 CELO at the 50 gwei floor) is consumed, and the test asserts the balance falls by exactly that fee.
Keys are self-serve on purpose. Allowlisted keys need a human to triage each request and hand the secret over out of band, which does not scale and tends to leave secrets in chat logs. Tying keys to a GitHub account instead reuses an identity the faucet already understands, which is also what the Coinbase CDP, Circle, and Chainstack faucets do.
If you are testing contracts in CI you probably do not want the faucet at all.
anvil --fork-url https://forno.celo-sepolia.celo-testnet.org gives you
pre-funded accounts against forked state, with no rate limits and no network
flakiness. Reach for a key only when you need funds on the real testnet.
Add the chain config and token info to config/chains.ts.
Add chain name to the networks array, and ChainId and FaucetAddress to enums in types/index.ts.
Dispatch the deploy-chains workflow. ensure chain name is kebab case and matches a network in config/chains.ts.