{"id":17656014,"url":"https://github.com/ashucoder9/teleporter-devnet-faucet","last_synced_at":"2025-03-30T09:28:51.353Z","repository":{"id":219966321,"uuid":"750373020","full_name":"ashucoder9/teleporter-devnet-faucet","owner":"ashucoder9","description":null,"archived":false,"fork":false,"pushed_at":"2024-02-08T05:53:23.000Z","size":83893,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-05T11:38:01.046Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ashucoder9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-01-30T14:23:20.000Z","updated_at":"2024-05-13T09:47:50.000Z","dependencies_parsed_at":"2024-12-11T11:17:02.266Z","dependency_job_id":null,"html_url":"https://github.com/ashucoder9/teleporter-devnet-faucet","commit_stats":null,"previous_names":["ashucoder9/teleporter-devnet-faucet"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashucoder9%2Fteleporter-devnet-faucet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashucoder9%2Fteleporter-devnet-faucet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashucoder9%2Fteleporter-devnet-faucet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ashucoder9%2Fteleporter-devnet-faucet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ashucoder9","download_url":"https://codeload.github.com/ashucoder9/teleporter-devnet-faucet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246300836,"owners_count":20755437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-23T13:09:45.055Z","updated_at":"2025-03-30T09:28:46.344Z","avatar_url":"https://github.com/ashucoder9.png","language":"TypeScript","readme":"# Avalanche Subnet Faucet\n\nRight now there are thousands of networks and chains in the blockchain space, each with its capabilities and use-cases. And each network requires native coins to do any transaction on them, which can have a monetary value as well. These coins can be collected through centralized exchanges, token sales, etc in exchange for some monetary assets like USD.\n\nBut we cannot risk our funds on the network or on any applications hosted on that network, without testing them first. So, these networks often have test networks or testnets, where the native coins do not have any monetary value, and thus can be obtained freely through faucets. \n\nThese testnets are often the testbeds for any new native feature of the network itself, or any dApp or [Subnet](https://www.avax.network/subnets) that is going live on the main network (mainnet). For example, [Fuji](https://docs.avax.network/quickstart/fuji-workflow) network is the testnet for Avalanche's mainnet.\n\nBesides Fuji Testnet, [Avalanche Faucet](https://faucet.avax.network/) can be used to get free coins on these testnets Subnets like -\n* [WAGMI Testnet](https://faucet.avax.network?subnet=wagmi)\n* [DeFI Kingdoms Testnet](https://faucet.avax.network?subnet=dfk)\n* [Dexalot Testnet](https://faucet.avax.network?subnet=dexalot) and many more.\n\nYou can use this [repository](https://github.com/ava-labs/avalanche-faucet) to deploy your faucet or just make a PR with the [configurations](https://github.com/ava-labs/avalanche-faucet/blob/main/config.json) of the Subnet. This faucet comes with many features like multiple chain support, custom rate-limiting per Subnet, captcha verification, and concurrent transaction handling.\n\n## TL;DR\n\nA [Faucet](https://faucet.avax.network/) powered by Avalanche for Fuji Network and other Subnets. You can -\n\n* Request test coins for the supported Subnets\n* Integrate your EVM Subnet with the faucet by making a PR with the [chain configurations](https://github.com/ava-labs/avalanche-faucet/blob/main/config.json)\n* Fork the [repository](https://github.com/ava-labs/avalanche-faucet) to deploy your faucet for any EVM chain\n\n## Adding a New Subnet\n\nYou can also integrate a new Subnet on the live [faucet](https://faucet.avax.network) with just a few lines of configuration parameters. All you have to do is make a PR on the [Avalanche Faucet](https://github.com/ava-labs/avalanche-faucet) git repository with the Subnet's information. The following parameters are required.\n\n```json\n{\n    \"ID\": \"string\",\n    \"NAME\": \"string\",\n    \"TOKEN\": \"string\",\n    \"RPC\": \"string\",\n    \"CHAINID\": \"number\",\n    \"EXPLORER\": \"string\",\n    \"IMAGE\": \"string\",\n    \"MAX_PRIORITY_FEE\": \"string\",\n    \"MAX_FEE\": \"string\",\n    \"DRIP_AMOUNT\": \"number\",\n    \"RATELIMIT\": {\n        \"MAX_LIMIT\": \"number\",\n        \"WINDOW_SIZE\": \"number\"\n    }\n}\n```\n\n* **ID** - Each subnet chain should have a unique and relatable ID.\n* **NAME** - Name of the Subnet chain that will appear on the website.\n* **RPC** - A valid RPC URL for accessing the chain.\n* **CHAINID** - Chain ID of the chain\n* **EXPLORER** - Base URL of standard explorer's website.\n* **IMAGE** - URL of the icon of the chain that will be shown in the dropdown.\n* **MAX_PRIORITY_FEE** - Maximum tip per faucet drop in **wei** or **10\u003csup\u003e-18\u003c/sup\u003e** unit (for EIP1559 supported chains)\n* **MAX_FEE** - Maximum fee that can be paid for a faucet drop in **wei** or **10\u003csup\u003e-18\u003c/sup\u003e** unit\n* **DRIP_AMOUNT** - Amount of coins to send per request in **gwei** or **10\u003csup\u003e-9\u003c/sup\u003e** unit\n* **RECALIBRATE** *(optional)* - Number of seconds after which the nonce and balance will recalibrate\n* **RATELIMIT** - Number of times (MAX_LIMIT) to allow per user within the WINDOW_SIZE (in minutes)\n\nAdd the configuration in the array of `evmchains` inside the [config.json](https://github.com/ava-labs/avalanche-faucet/blob/main/config.json) file and make a PR.\n\n## Building and Deploying a Faucet\n\nYou can also deploy and build your faucet by using the [Avalanche Faucet](https://github.com/ava-labs/avalanche-faucet) repository.\n\n### Requirements\n\n* [Node](https://nodejs.org/en) \u003e= 17.0 and [npm](https://www.npmjs.com/) \u003e= 8.0\n* [Google's ReCaptcha](https://www.google.com/recaptcha/intro/v3.html) v3 keys\n* [Docker](https://www.docker.com/get-started/)\n\n### Installation\n\nClone this repository at your preferred location.\n\n```bash\ngit clone https://github.com/ava-labs/avalanche-faucet\n```\n\n### Client Side Configurations\n\nWe need to configure our application with the server API endpoints and Captcha site keys. All the client-side configurations are there in the `client/src/config.json` file. Since there are no secrets on the client-side, we do not need any environment variables. Update the config files according to your need.\n\n```json\n{\n    \"banner\": \"/banner.png\",\n    \"apiBaseEndpointProduction\": \"/api/\",\n    \"apiBaseEndpointDevelopment\": \"http://localhost:8000/api/\",\n    \"apiTimeout\": 10000,\n    \"CAPTCHA\": {\n        \"siteKey\": \"6LcNScYfAAAAAJH8fauA-okTZrmAxYqfF9gOmujf\",\n        \"action\": \"faucetdrip\"\n    }\n}\n```\n\nPut the Google's ReCaptcha site-key without which the faucet client can't send the necessary captcha response to the server. This key is not a secret and could be public.\n\nIn the above file, there are 2 base endpoints for the faucet server `apiBaseEndpointProduction` and `apiBaseEndpointDevelopment`.\n\nIn production mode, the client-side will be served as static content over the server's endpoint, and hence we do not have to provide the server's IP address or domain.\n\nThe URL path should be valid, where the server's APIs are hosted. If the endpoints for API have a leading `/v1/api` and the server is running on localhost at port 3000, then you should use `http://localhost:3000/v1/api` or `/v1/api/` depending on whether it is production or development.\n\n### Server-Side Configurations\n\nOn the server side, we need to configure 2 files - `.env` for secret keys and `config.json` for chain and API's rate limiting configurations.\n\n#### Setup Environment Variables\n\nSetup the environment variable with your private key and ReCaptcha secret. Make a `.env` file in your preferred location with the following credentials, as this file will not be committed to the repository. The faucet server can handle multiple EVM chains, and therefore requires private keys for addresses with funds on each of the chains.\n\nIf you have funds on the same address on every chain, then you can specify them with the single variable`PK`. But if you have funds on different addresses on different chains, then you can provide each of the private keys against the ID of the chain, as shown below.\n\n```env\nC=\"C chain private key\"\nWAGMI=\"Wagmi chain private key\"\nPK=\"Sender Private Key with Funds in it\"\nCAPTCHA_SECRET=\"Google ReCaptcha Secret\"\n```\n`PK` will act as a fallback private key, in case, the key for any chain is not provided.\n\n#### Setup EVM Chain Configurations\n\nYou can create a faucet server for any EVM chain by making changes in the `config.json` file. Add your chain configuration as shown below in the `evmchains` object. Configuration for Fuji's C-Chain and WAGMI chain is shown below for example.\n\n```json\n\"evmchains\": [\n    {\n        \"ID\": \"C\",\n        \"NAME\": \"Fuji (C-Chain)\",\n        \"TOKEN\": \"AVAX\",\n        \"RPC\": \"https://api.avax-test.network/ext/C/rpc\",\n        \"CHAINID\": 43113,\n        \"EXPLORER\": \"https://testnet.snowtrace.io\",\n        \"IMAGE\": \"/avaxred.png\",\n        \"MAX_PRIORITY_FEE\": \"2000000000\",\n        \"MAX_FEE\": \"100000000000\",\n        \"DRIP_AMOUNT\": 2000000000,\n        \"RECALIBRATE\": 30,\n        \"RATELIMIT\": {\n            \"MAX_LIMIT\": 1,\n            \"WINDOW_SIZE\": 1440\n        }\n    },\n    {\n        \"ID\": \"WAGMI\",\n        \"NAME\": \"WAGMI Testnet\",\n        \"TOKEN\": \"WGM\",\n        \"RPC\": \"https://subnets.avax.network/wagmi/wagmi-chain-testnet/rpc\",\n        \"CHAINID\": 11111,\n        \"EXPLORER\": \"https://subnets.avax.network/wagmi/wagmi-chain-testnet/explorer\",\n        \"IMAGE\": \"/wagmi.png\",\n        \"MAX_PRIORITY_FEE\": \"2000000000\",\n        \"MAX_FEE\": \"100000000000\",\n        \"DRIP_AMOUNT\": 2000000000,\n        \"RATELIMIT\": {\n            \"MAX_LIMIT\": 1,\n            \"WINDOW_SIZE\": 1440\n        }\n    }\n]\n```\nIn the above configuration drip amount is in `nAVAX` or `gwei`, whereas fees are in `wei`. For example, with the above configurations, the faucet will send `1 AVAX` with maximum fees per gas being `100 nAVAX` and priority fee as `2 nAVAX`.\n\nThe rate limiter for C Chain will only accept 1 request in 60 minutes for a particular API and 2 requests in 60 minutes for the WAGMI chain. Though it will skip any failed requests so that users can request tokens again, even if there is some internal error in the application. On the other hand, the global rate limiter will allow 15 requests per minute on every API. This time failed requests will also get counted so that no one can abuse the APIs.\n\n### API Endpoints\n\nThis server will expose the following APIs\n\n#### Health API\n\nThe `/health` API will always return a response with a `200` status code. This endpoint can be used to know the health of the server.\n\n```bash\ncurl http://localhost:8000/health\n```\n\nResponse\n\n```bash\nServer healthy\n```\n\n#### Get Faucet Address\n\nThis API will be used for fetching the faucet address.\n\n```bash\ncurl http://localhost:8000/api/faucetAddress?chain=C\n```\n\nIt will give the following response\n\n```bash\n0x3EA53fA26b41885cB9149B62f0b7c0BAf76C78D4\n```\n\n#### Get Faucet Balance\n\nThis API will be used for fetching the faucet address.\n\n```bash\ncurl http://localhost:8000/api/getBalance?chain=C\n```\n\nIt will give the following response\n\n```bash\n14282900936\n```\n\n#### Send Token\n\nThis API endpoint will handle token requests from users. It will return the transaction hash as a receipt of the faucet drip.\n\n```bash\ncurl -d '{\n        \"address\": \"0x3EA53fA26b41885cB9149B62f0b7c0BAf76C78D4\"\n        \"chain\": \"C\"\n}' -H 'Content-Type: application/json' http://localhost:8000/api/sendToken\n```\n\nSend token API requires a Captcha response token that is generated using the Captcha site key on the client-side. Since we can't generate and pass this token while making a curl request, we have to disable the captcha verification for testing purposes. You can find the steps to disable it in the next sections. The response is shown below\n\n```bash\n{\n    \"message\": \"Transaction successful on Avalanche C Chain!\",\n    \"txHash\": \"0x3d1f1c3facf59c5cd7d6937b3b727d047a1e664f52834daf20b0555e89fc8317\"\n}\n```\n\n### Rate Limiters (Important)\n\nThe rate limiters are applied on the global (all endpoints) as well as on the `/api/sendToken` API. These can be configured from the `config.json` file. Rate limiting parameters for chains are passed in the chain configuration as shown above. \n\n```json\n\"GLOBAL_RL\": {\n    \"ID\": \"GLOBAL\",\n    \"RATELIMIT\": {\n        \"REVERSE_PROXIES\": 4,\n        \"MAX_LIMIT\": 40,\n        \"WINDOW_SIZE\": 1,\n        \"PATH\": \"/\",\n        \"SKIP_FAILED_REQUESTS\": false\n    }\n}\n```\n\nThere could be multiple proxies between the server and the client. The server will see the IP address of the adjacent proxy connected with the server, and this may not be the client's actual IP.\n\nThe IPs of all the proxies that the request has hopped through are stuffed inside the header **x-forwarded-for** array. But the proxies in between can easily manipulate these headers to bypass rate limiters. So, we cannot trust all the proxies and hence all the IPs inside the header.\n\nThe proxies that are set up by the owner of the server (reverse-proxies) are the trusted proxies on which we can rely and know that they have stuffed the actual IP of the requesters in between. Any proxy that is not set up by the server, should be considered an untrusted proxy. So, we can jump to the IP address added by the last proxy that we trust. The number of jumps that we want can be configured in the `config.json` file inside the `GLOBAL_RL` object.\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-5.png)\n\n\n\n#### Clients Behind Same Proxy\n\nConsider the below diagram. The server is set up with 2 reverse proxies. If the client is behind proxies, then we cannot get the client's actual IP, and instead will consider the proxy's IP as the client's IP. And if some other client is behind the same proxy, then those clients will be considered as a single entity and might get rate-limited faster.\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-6.png)\n\n\nTherefore it is advised to the users, to avoid using any proxy for accessing applications that have critical rate limits, like this faucet.\n\n#### Wrong Number of Reverse Proxies\n\nSo, if you want to deploy this faucet, and have some reverse proxies in between, then you should configure this inside the `GLOBAL_RL` key of the `config.json` file. If this is not configured properly, then the users might get rate-limited very frequently, since the server-side proxy's IP addresses are being viewed as the client's IP. You can verify this in the code [here](https://github.com/ava-labs/avalanche-faucet/blob/23eb300635b64130bc9ce10d9e894f0a0b3d81ea/middlewares/rateLimiter.ts#L25).\n\n```json\n\"GLOBAL_RL\": {\n    \"ID\": \"GLOBAL\",\n    \"RATELIMIT\": {\n        \"REVERSE_PROXIES\": 4,\n        ...\n```\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-7.png)\n\n\nIt is also quite common to have Cloudflare as the last reverse proxy or the exposed server. Cloudflare provides a header **cf-connecting-ip** which is the IP of the client that requested the faucet and hence Cloudflare. We are using this as default.\n\n### Captcha Verification\n\nCaptcha is required to prove the user is a human and not a bot. For this purpose, we will use [Google's Recaptcha](https://www.google.com/recaptcha/intro/v3.html). The server side will require `CAPTCHA_SECRET` that should not be exposed. You can set the threshold score to pass the captcha test by the users [here](https://github.com/ava-labs/avalanche-faucet/blob/23eb300635b64130bc9ce10d9e894f0a0b3d81ea/middlewares/verifyCaptcha.ts#L20).\n\nYou can disable these Captcha verifications and rate limiters for testing the purpose, by tweaking in the `server.ts` file.\n\n### Disabling Rate Limiters\n\nComment or remove these 2 lines from the `server.ts` file\n\n```javascript\nnew RateLimiter(app, [GLOBAL_RL]);\nnew RateLimiter(app, evmchains);\n```\n\n### Disabling Captcha Verification\n\nRemove the  `captcha.middleware` from `sendToken` API.\n\n### Starting the Faucet\n\nFollow the below commands to start your local faucet.\n\n#### Installing Dependencies\n\nThis will concurrently install dependencies for both client and server.\n\n```bash\nnpm install\n```\n\nIf ports have a default configuration, then the client will start at port 3000 and the server will start at port 8000 while in development mode.\n\n#### Starting in Development Mode\n\nThis will concurrently start the server and client in development mode.\n\n```bash\nnpm run dev\n```\n\n#### Building for Production\n\nThe following command will build server and client at `build/` and `build/client` directories.\n\n```bash\nnpm run build\n```\n\n#### Starting in Production Mode\n\nThis command should only be run after successfully building the client and server-side code.\n\n```bash\nnpm start\n```\n\n### Setting up with Docker\n\nFollow the steps to run this application in a Docker container.\n\n#### Build Docker Image\n\nDocker images can be served as the built versions of our application, that can be used to deploy on Docker container.\n\n```bash\ndocker build . -t faucet-image\n```\n\n#### Starting Application inside Docker Container\n\nNow we can create any number of containers using the above `faucet` image. We also have to supply the `.env` file or the environment variables with the secret keys to create the container. Once the container is created, these variables and configurations will be persisted and can be easily started or stopped with a single command.\n\n```bash\ndocker run -p 3000:8000 --name faucet-container --env-file ../.env faucet-image\n```\n\nThe server will run on port 8000, and our Docker will also expose this port for the outer world to interact. We have exposed this port in the `Dockerfile`. But we cannot directly interact with the container port, so we had to bind this container port to our host port. For the host port, we have chosen 3000. This flag `-p 3000:8000` achieves the same.\n\nThis will start our faucet application in a Docker container at port 3000 (port 8000 on the container). You can interact with the application by visiting http://localhost:3000 in your browser.\n\n#### Stopping the Container\n\nYou can easily stop the container using the following command\n\n```bash\ndocker stop faucet-container\n```\n\n#### Restarting the Container\n\nTo restart the container, use the following command\n\n```bash\ndocker start faucet-container\n```\n\n## Using the Faucet\n\nUsing the faucet is quite straightforward, but for the sake of completeness, let's go through the steps, to collect your first test coins.\n\n### Visit Avalanche Faucet Website\n\nGo to https://faucet.avax.network. You will see various network parameters like network name, faucet balance, drop amount, drop limit, faucet address, etc.\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-1.jpeg)\n\n### Select Network\n\nYou can use the dropdown to select the network of your choice and get some free coins (each network may have a different drop amount).\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-2.png)\n\n### Put Address and Request Coins\n\nPut your wallet address where you want to get a drop, and click the **Request** button. Within a second, you will get a **transaction hash** for the processed transaction. The hash would be a hyperlink to Subnet's explorer. You can see the transaction status, by clicking on that hyperlink.\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-3.png)\n\n### More Interactions\n\nThis is not just it. Using the buttons shown below, you can go to the Subnet explorer or add the Subnet to your browser wallet extensions like Metamask with a single click.\n\n![](https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/static/img/faucet-4.png)\n\n### Probable Errors and Troubleshooting\n\nErrors are not expected, but if you are facing some of the errors shown, then you could try troubleshooting as shown below. If none of the troubleshooting works, reach us through [Discord](https://discord.com/channels/578992315641626624/).\n\n* **Too many requests. Please try again after X minutes**\nThis is a rate-limiting message. Every Subnet can set its drop limits. The above message suggests that you have reached your drop limit i.e. the number of times you could request coins within the window of X minutes. You should try requesting after X minutes. If you are facing this problem, even when you are requesting for the first time in the window, you may be behind some proxy, WiFi, or VPN service that is also being used by some other user.\n\n* **Captcha verification failed! Try refreshing**\nWe are using v3 of [Google's ReCaptcha](https://developers.google.com/recaptcha/docs/v3). This version uses scores between 0 and 1 to rate the interaction of humans with the website, with 0 being the most suspicious one. You do not have to solve any puzzle or mark the **I am not a Robot** checkbox. The score will be automatically calculated. We want our users to score at least 0.3 to use the faucet. This is configurable, and we will update the threshold after having broader data. But if you are facing this issue, then you can try refreshing your page, disabling ad-blockers, or switching off any VPN. You can follow this [guide](https://2captcha.com/blog/google-doesnt-accept-recaptcha-answers) to get rid of this issue.\n\n* **Internal RPC error! Please try after sometime**\nThis is an internal error in the Subnet's node, on which we are making an RPC for sending transactions. A regular check will update the RPC's health status every 30 seconds (default) or whatever is set in the configuration. This may happen only in rare scenarios and you cannot do much about it, rather than waiting.\n\n* **Timeout of 10000ms exceeded**\nThere could be many reasons for this message. It could be an internal server error, or the request didn't receive by the server, slow internet, etc. You could try again after some time, and if the problem persists, then you should raise this issue on our [Discord](https://discord.com/channels/578992315641626624/) server.\n\n* **Couldn't see any transaction status on explorer**\nThe transaction hash that you get for each drop is pre-computed using the expected nonce, amount, and receiver's address. Though transactions on Avalanche are near-instant, the explorer may take time to index those transactions. You should wait for a few more seconds, before raising any issue or reaching out to us.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashucoder9%2Fteleporter-devnet-faucet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fashucoder9%2Fteleporter-devnet-faucet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fashucoder9%2Fteleporter-devnet-faucet/lists"}