├── .eslintignore ├── src ├── index.ts ├── data │ ├── networks.ts │ ├── constants.ts │ ├── questions.ts │ └── solQuestions.ts ├── utils │ ├── getAddressFromConfigFile.ts │ ├── ratelimit.ts │ └── createOrUpdateConfigFile.ts ├── commands │ ├── networks.ts │ ├── funding.ts │ ├── solana.ts │ └── request.ts └── lib │ └── sendTokens.ts ├── bin ├── run.cmd └── run ├── renovate.json ├── .mocharc.json ├── .gitignore ├── .editorconfig ├── .eslintrc ├── tsconfig.json ├── .github └── dependabot.yml ├── .circleci └── config.yml ├── LICENSE ├── package.json └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export {run} from '@oclif/core' 2 | -------------------------------------------------------------------------------- /bin/run.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/data/networks.ts: -------------------------------------------------------------------------------- 1 | const networks = ["mumbai", "rinkeby"]; 2 | const solNetworks = ["devnet"]; 3 | 4 | export default networks; 5 | 6 | export { solNetworks }; 7 | -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": ["test/helpers/init.js", "ts-node/register"], 3 | "watch-extensions": ["ts"], 4 | "recursive": true, 5 | "reporter": "spec", 6 | "timeout": 60000 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-debug.log 2 | *-debug.log 3 | *-error.log 4 | *-error.log 5 | /.nyc_output 6 | /dist 7 | /dist 8 | /lib 9 | /lib 10 | /tmp 11 | /tmp 12 | node_modules 13 | node_modules 14 | oclif.manifest.json 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "parser": "@typescript-eslint/parser", 7 | "parserOptions": { 8 | "ecmaVersion": "latest", 9 | "sourceType": "module" 10 | }, 11 | "plugins": ["@typescript-eslint"], 12 | "rules": { 13 | "indent": ["error", 2] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | if (process.argv.slice(2).length == 0) { 4 | const figchalk = require("figchalk"); 5 | 6 | console.log(figchalk.mix("🌈 F a u c e t l i", "redBright")); 7 | } 8 | 9 | require("@oclif/command") 10 | .run() 11 | .then(require("@oclif/command/flush")) 12 | .catch(require("@oclif/errors/handle")); 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "importHelpers": true, 5 | "moduleResolution": "node", 6 | "module": "commonjs", 7 | "outDir": "dist", 8 | "rootDir": "src", 9 | "strict": true, 10 | "target": "es2019", 11 | "esModuleInterop": true, 12 | "resolveJsonModule": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/data/constants.ts: -------------------------------------------------------------------------------- 1 | import os from "os"; 2 | 3 | const constants = { 4 | configFilePath: `${os.homedir()}/.config/faucetli/config.json`, 5 | configFolderPath: `${os.homedir()}/.config/faucetli`, 6 | ratelimitFilePath: `${os.homedir()}/.config/faucetli/ratelimit.json`, 7 | ratelimitDuration: 3600000 * 3, 8 | ratelimitDurationLocale: "3 hours", 9 | apiUrl: "https://faucetli-backend-production.up.railway.app/api/v1", 10 | }; 11 | 12 | export default constants; 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | versioning-strategy: increase 5 | directory: "/" 6 | schedule: 7 | interval: "monthly" 8 | labels: 9 | - "dependencies" 10 | open-pull-requests-limit: 100 11 | pull-request-branch-name: 12 | separator: "-" 13 | ignore: 14 | - dependency-name: "fs-extra" 15 | - dependency-name: "*" 16 | update-types: ["version-update:semver-major"] 17 | -------------------------------------------------------------------------------- /src/utils/getAddressFromConfigFile.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | import constants from "../data/constants"; 4 | 5 | const getAddressFromConfigFile = (blockchain: string = "ethereum") => { 6 | if (fs.existsSync(constants["configFilePath"])) { 7 | const configFile = fs.readFileSync(constants["configFilePath"], "utf8"); 8 | const config = JSON.parse(configFile); 9 | return blockchain === "ethereum" ? config.address : config.solAddress; 10 | } 11 | }; 12 | 13 | export default getAddressFromConfigFile; 14 | -------------------------------------------------------------------------------- /src/commands/networks.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "@oclif/core"; 2 | 3 | import chalk from "chalk"; 4 | 5 | import networks, { solNetworks } from "../data/networks"; 6 | 7 | export default class Networks extends Command { 8 | static description = "🌈 Get the list of all the supported testnets"; 9 | 10 | async run() { 11 | console.log( 12 | chalk.green("\n🌈 These are the testnets supported by faucetli:") 13 | ); 14 | console.log(); 15 | console.log( 16 | chalk.gray("Ethereum") + chalk.blueBright("\n- " + networks.join("\n- ")) 17 | ); 18 | console.log(""); 19 | console.log("Solana" + chalk.blueBright("\n- " + solNetworks.join("\n- "))); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2.1 3 | 4 | orbs: 5 | release-management: salesforce/npm-release-management@4.37.1 6 | 7 | workflows: 8 | version: 2 9 | test-and-release: 10 | jobs: 11 | - release-management/test-package: 12 | matrix: 13 | parameters: 14 | os: 15 | - linux 16 | - windows 17 | node_version: 18 | - latest 19 | - lts 20 | - maintenance 21 | dependabot-automerge: 22 | triggers: 23 | - schedule: 24 | cron: "0 2,5,8,11 * * *" 25 | filters: 26 | branches: 27 | only: 28 | - main 29 | jobs: 30 | - release-management/dependabot-automerge 31 | -------------------------------------------------------------------------------- /src/commands/funding.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "@oclif/core"; 2 | 3 | import chalk from "chalk"; 4 | 5 | export default class Funding extends Command { 6 | static description = 7 | "🎉 If you found this faucet useful and want to keep it going we accept donations on this address: 0x894b6579524c61b56B3aB5624740464EaDF5237E"; 8 | 9 | async run() { 10 | console.log( 11 | chalk.green( 12 | `\n🎉 If you found this faucet useful and want to keep it going we accept donations on this address: ${chalk.bold( 13 | chalk.blue("0x894b6579524c61b56B3aB5624740464EaDF5237E") 14 | )}\nLink: ${chalk.blue( 15 | "https://rinkeby.etherscan.io/address/0x894b6579524c61b56B3aB5624740464EaDF5237E" 16 | )}` 17 | ) 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/commands/solana.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "@oclif/core"; 2 | 3 | import inquirer from "inquirer"; 4 | 5 | import sendTokens from "../lib/sendTokens"; 6 | import getAddressFromConfigFile from "../utils/getAddressFromConfigFile"; 7 | 8 | import solQuestions from "../data/solQuestions"; 9 | import createOrUpdateConfigFile from "../utils/createOrUpdateConfigFile"; 10 | 11 | export default class Solana extends Command { 12 | static description = "🦄 Get devnet Solana by using the solana command"; 13 | 14 | async run() { 15 | inquirer.prompt(solQuestions).then(async (answers) => { 16 | if (answers.wallet !== undefined) 17 | createOrUpdateConfigFile("", answers.wallet); 18 | 19 | await sendTokens( 20 | getAddressFromConfigFile("solana"), 21 | answers.network, 22 | "solana" 23 | ); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/commands/request.ts: -------------------------------------------------------------------------------- 1 | import { Command } from "@oclif/core"; 2 | 3 | import inquirer from "inquirer"; 4 | 5 | import sendTokens from "../lib/sendTokens"; 6 | import getAddressFromConfigFile from "../utils/getAddressFromConfigFile"; 7 | 8 | import questions from "../data/questions"; 9 | import createOrUpdateConfigFile from "../utils/createOrUpdateConfigFile"; 10 | 11 | export default class Request extends Command { 12 | static description = "🦄 Get testnet tokens by using request command"; 13 | 14 | async run() { 15 | inquirer.prompt(questions).then(async (answers) => { 16 | if (answers.wallet !== undefined) { 17 | createOrUpdateConfigFile(answers.wallet); 18 | await sendTokens(getAddressFromConfigFile(), answers.network); 19 | } else { 20 | await sendTokens(getAddressFromConfigFile(), answers.network); 21 | } 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/utils/ratelimit.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import constants from "../data/constants"; 3 | 4 | const ratelimit = (timestamp: number) => { 5 | if (fs.existsSync(constants["ratelimitFilePath"])) { 6 | const data = fs.readFileSync(constants["ratelimitFilePath"], "utf8"); 7 | 8 | if (timestamp >= parseInt(JSON.parse(data)["reset"])) { 9 | fs.writeFileSync( 10 | constants["ratelimitFilePath"], 11 | JSON.stringify({ 12 | reset: timestamp + constants["ratelimitDuration"], 13 | }) 14 | ); 15 | return true; 16 | } else { 17 | return false; 18 | } 19 | } else { 20 | fs.writeFileSync( 21 | constants["ratelimitFilePath"], 22 | JSON.stringify({ 23 | reset: timestamp + constants["ratelimitDuration"], 24 | }) 25 | ); 26 | return true; 27 | } 28 | }; 29 | 30 | export default ratelimit; 31 | -------------------------------------------------------------------------------- /src/utils/createOrUpdateConfigFile.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import shelljs from "shelljs"; 3 | 4 | import constants from "../data/constants"; 5 | 6 | const createOrUpdateConfigFile = ( 7 | address: string | null = null, 8 | solAddress: string | null = null 9 | ) => { 10 | shelljs.mkdir("-p", constants["configFolderPath"]); 11 | 12 | if (fs.existsSync(constants["configFilePath"])) { 13 | let config = JSON.parse( 14 | fs.readFileSync(constants["configFilePath"], "utf-8") 15 | ); 16 | 17 | if (address) { 18 | config.address = address; 19 | } 20 | 21 | if (solAddress) { 22 | config.solAddress = solAddress; 23 | } 24 | 25 | config = JSON.stringify(config); 26 | fs.writeFileSync(constants["configFilePath"], config); 27 | } else { 28 | const config = JSON.stringify({ 29 | address: address, 30 | solAddress: solAddress, 31 | }); 32 | fs.writeFileSync(constants["configFilePath"], config); 33 | } 34 | }; 35 | 36 | export default createOrUpdateConfigFile; 37 | -------------------------------------------------------------------------------- /src/data/questions.ts: -------------------------------------------------------------------------------- 1 | import networks from "./networks"; 2 | import getAddressFromConfigFile from "../utils/getAddressFromConfigFile"; 3 | 4 | let questions: Array = []; 5 | 6 | if (getAddressFromConfigFile("ethereum")) { 7 | questions = [ 8 | { 9 | type: "list", 10 | name: "network", 11 | message: "🦄 enter the network name:", 12 | default: "mumbai", 13 | choices: networks, 14 | }, 15 | ]; 16 | } else { 17 | questions = [ 18 | { 19 | type: "input", 20 | name: "wallet", 21 | message: "✨ enter your wallet address:", 22 | validate: function (value: string) { 23 | if (value.length) { 24 | return true; 25 | } else { 26 | return "😿 please enter your wallet address"; 27 | } 28 | }, 29 | }, 30 | { 31 | type: "list", 32 | name: "network", 33 | message: "🦄 enter the network name:", 34 | default: "mumbai", 35 | choices: networks, 36 | }, 37 | ]; 38 | } 39 | 40 | export default questions; 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Kira 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/data/solQuestions.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | import { solNetworks } from "./networks"; 4 | import constants from "./constants"; 5 | import getAddressFromConfigFile from "../utils/getAddressFromConfigFile"; 6 | 7 | let solQuestions: Array = []; 8 | 9 | if (getAddressFromConfigFile("solana")) { 10 | solQuestions = [ 11 | { 12 | type: "list", 13 | name: "network", 14 | message: "🦄 enter the network name:", 15 | default: "devnet", 16 | choices: solNetworks, 17 | }, 18 | ]; 19 | } else { 20 | solQuestions = [ 21 | { 22 | type: "input", 23 | name: "wallet", 24 | message: "✨ enter your wallet address:", 25 | validate: function (value: string) { 26 | if (value.length) { 27 | return true; 28 | } else { 29 | return "😿 please enter your wallet address"; 30 | } 31 | }, 32 | }, 33 | { 34 | type: "list", 35 | name: "network", 36 | message: "🦄 enter the network name:", 37 | default: "devnet", 38 | choices: solNetworks, 39 | }, 40 | ]; 41 | } 42 | 43 | export default solQuestions; 44 | -------------------------------------------------------------------------------- /src/lib/sendTokens.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import chalk from "chalk"; 3 | import ora from "ora"; 4 | 5 | import ratelimit from "../utils/ratelimit"; 6 | 7 | import constants from "../data/constants"; 8 | 9 | const sendTokens = async ( 10 | wallet: string, 11 | network: string, 12 | blockchain: string = "ethereum" 13 | ) => { 14 | const spinner = ora(`🦄 sending tokens to ${wallet} on ${network}`).start(); 15 | 16 | const currentTimestamp = new Date().getTime(); 17 | if (!ratelimit(currentTimestamp)) { 18 | spinner.fail( 19 | chalk.redBright( 20 | `⏳ ratelimit reached, wait for ${chalk.yellow( 21 | `${constants["ratelimitDurationLocale"]} to get more tokens` 22 | )}` 23 | ) 24 | ); 25 | } else { 26 | const endpoint = blockchain === "ethereum" ? "token" : "solana"; 27 | await axios 28 | .get( 29 | `${constants.apiUrl}/${endpoint}?address=${wallet}&network=${network}` 30 | ) 31 | .then((res) => { 32 | if (res.data.insufficientFunds === true) { 33 | spinner.fail( 34 | chalk.redBright( 35 | `😿 I'm out of funds! You can use the Chainlink Faucet until I get refilled. https://faucets.chain.link.\nDonate: 0x894b6579524c61b56B3aB5624740464EaDF5237E` 36 | ) 37 | ); 38 | } else { 39 | if (res.data.invalidAddress === true) { 40 | spinner.fail(chalk.redBright(`🤷‍♂️ The address provided is invalid`)); 41 | } else if (res.data.exceedsMaxLimit === true) { 42 | spinner.fail( 43 | chalk.redBright( 44 | `🤷‍♂️ You already have enough tokens to pay the gas fees` 45 | ) 46 | ); 47 | } else { 48 | spinner.succeed( 49 | chalk.greenBright( 50 | `🎉 sent the tokens to ${wallet} on ${network}, check ${res.data.txLink} to verify if the transaction was successful` 51 | ) 52 | ); 53 | } 54 | } 55 | }) 56 | .catch((err) => { 57 | spinner.fail(chalk.redBright`😿 ${err}`); 58 | }); 59 | } 60 | }; 61 | 62 | export default sendTokens; 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "faucetli", 3 | "version": "1.1.10", 4 | "description": "🦄 A command line tool to get tokens on testnets quickly!", 5 | "author": "Kira272921", 6 | "bin": { 7 | "faucetli": "./bin/run" 8 | }, 9 | "homepage": "https://github.com/Kira272921/faucetli", 10 | "license": "MIT", 11 | "main": "dist/index.js", 12 | "repository": "Kira272921/faucetli", 13 | "files": [ 14 | "/bin", 15 | "/dist", 16 | "/npm-shrinkwrap.json", 17 | "/oclif.manifest.json", 18 | "/package.json" 19 | ], 20 | "dependencies": { 21 | "@oclif/command": "^1.8.16", 22 | "@oclif/core": "^1", 23 | "@oclif/plugin-help": "^5", 24 | "@oclif/plugin-plugins": "^2.0.1", 25 | "axios": "^0.27.2", 26 | "chalk": "4.1.2", 27 | "figchalk": "^1.0.3", 28 | "inquirer": "^8.2.4", 29 | "ora": "5.4.1", 30 | "shelljs": "^0.8.5" 31 | }, 32 | "devDependencies": { 33 | "@oclif/test": "2.1.0", 34 | "@types/chai": "4.3.1", 35 | "@types/inquirer": "8.2.1", 36 | "@types/listr": "0.14.4", 37 | "@types/mocha": "9.1.1", 38 | "@types/node": "16.11.56", 39 | "@types/shelljs": "0.8.11", 40 | "chai": "4.3.6", 41 | "eslint": "8.23.0", 42 | "eslint-config-oclif": "4.0.0", 43 | "eslint-config-oclif-typescript": "1.0.2", 44 | "globby": "11.1.0", 45 | "mocha": "10.0.0", 46 | "oclif": "3.1.1", 47 | "shx": "0.3.4", 48 | "ts-node": "10.9.1", 49 | "tslib": "2.4.0", 50 | "typescript": "4.7.4" 51 | }, 52 | "oclif": { 53 | "bin": "faucetli", 54 | "dirname": "faucetli", 55 | "commands": "./dist/commands", 56 | "plugins": [ 57 | "@oclif/plugin-help", 58 | "@oclif/plugin-plugins" 59 | ], 60 | "topicSeparator": " ", 61 | "topics": { 62 | "hello": { 63 | "description": "Say hello to the world and others" 64 | } 65 | } 66 | }, 67 | "scripts": { 68 | "build": "shx rm -rf dist && tsc -b", 69 | "lint": "eslint . --ext .ts --config .eslintrc", 70 | "postpack": "shx rm -f oclif.manifest.json", 71 | "posttest": "yarn lint", 72 | "prepack": "yarn build && oclif manifest && oclif readme", 73 | "test": "mocha --forbid-only \"test/**/*.test.ts\"", 74 | "version": "oclif readme && git add README.md", 75 | "watch": "tsc -b -w" 76 | }, 77 | "engines": { 78 | "node": ">=12.0.0" 79 | }, 80 | "bugs": "https://github.com/Kira272921/faucetli/issues", 81 | "keywords": [ 82 | "oclif" 83 | ], 84 | "types": "dist/index.d.ts" 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🦄 faucetli 2 | 3 | ![](https://imgur.com/9WQdXPl.png) 4 | 5 | Faucetli - 🦄 A command-line tool to get tokens on testnets quickly! | Product Hunt Faucetli - 🦄 A command-line tool to get tokens on testnets quickly! | Product Hunt 6 | 7 | 🦄 A command line tool to get tokens on testnets quickly! 8 | 9 | - [Usage](#usage) 10 | - [Commands](#commands) 11 | 12 | # Usage 13 | 14 | ``` 15 | $ npm install -g faucetli 16 | $ faucetli COMMAND 17 | running command... 18 | $ faucetli (--version) 19 | faucetli/0.0.0 win32-x64 node-v16.13.0 20 | $ faucetli --help [COMMAND] 21 | USAGE 22 | $ faucetli COMMAND 23 | ... 24 | ``` 25 | 26 | # Commands 27 | 28 | - [`faucetli request`](#faucetli-request) 29 | - [`faucetli solana`](#faucetli-solana) 30 | - [`faucetli networks`](#faucetli-networks) 31 | - [`faucetli funding`](#faucetli-funding) 32 | - [`faucetli help [COMMAND]`](#faucetli-help-command) 33 | 34 | ## `faucetli request` 35 | 36 | 🦄 Get testnet tokens by using request command 37 | 38 | ``` 39 | USAGE 40 | $ faucetli request 41 | 42 | DESCRIPTION 43 | 🦄 Get testnet tokens by using request command 44 | 45 | EXAMPLES 46 | $ faucetli request 47 | 48 | 🎉 sent the tokens to 0xd24CA0297558f0827e2C467603869D1AC9fF435d on rinkeby, check https://rinkeby.etherscan.io/tx/0x1d769e3f6a57a5176b9d1c6fbd8c3692fa0b3764c314ca6c263140794fde2cbd to verify if the transaction was successful 49 | ``` 50 | 51 | ## `faucetli solana` 52 | 53 | 🦄 Get devnet Solana by using the solana command 54 | 55 | ``` 56 | USAGE 57 | $ faucetli solana 58 | 59 | DESCRIPTION 60 | 🦄 Get devnet Solana by using the solana command 61 | 62 | EXAMPLES 63 | $ faucetli solana 64 | 65 | 🎉 sent the tokens to 8Dyk53RrtmN3MshQxxWdfTRco9sQJzUHSqkUg8chbe88 on devnet, check https://explorer.solana.com/tx/2hQ5NZzJieBfGvNhTzUQnAQ9ntZ3ybDy9B2o1TUjpFfMqvzD4VDDYp1XiK9kb1KPyCKrWARmvCVC175DBnGiksh2?cluster=devnet to verify if the transaction was successful 66 | ``` 67 | 68 | ## `faucetli networks` 69 | 70 | 🌈 Get the list of all the supported testnets 71 | 72 | ``` 73 | USAGE 74 | $ faucetli networks 75 | 76 | DESCRIPTION 77 | 🌈 Get the list of all the supported testnets 78 | 79 | EXAMPLES 80 | $ faucetli networks 81 | 82 | 🌈 These are the testnets supported by faucetli: 83 | 84 | - mumbai 85 | - rinkeby 86 | ``` 87 | 88 | ## `faucetli help [COMMAND]` 89 | 90 | Display help for faucetli. 91 | 92 | ``` 93 | USAGE 94 | $ faucetli help [COMMAND] [-n] 95 | 96 | ARGUMENTS 97 | COMMAND Command to show help for. 98 | 99 | FLAGS 100 | -n, --nested-commands Include all nested commands in the output. 101 | 102 | DESCRIPTION 103 | Display help for faucetli. 104 | ``` 105 | 106 | ## Authors 107 | 108 | ### Mukesh 109 | 110 | - Twitter: [@0xMukesh](https://twitter.com/0xMukesh) 111 | 112 | ### Avneesh Agarwal 113 | 114 | - Website: https://www.avneesh.tech/ 115 | - Twitter: [@avneesh0612](https://twitter.com/avneesh0612) 116 | - Github: [@avneesh0612](https://github.com/avneesh0612) 117 | - LinkedIn: [@avneesh0612](https://www.linkedin.com/in/avneesh0612) 118 | --------------------------------------------------------------------------------