├── app ├── CNAME ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ ├── credix_logo_zwart.svg │ ├── credix_logo_wit.svg │ └── index.html ├── src │ ├── setupTests.js │ ├── config │ │ ├── config.js │ │ └── spl_token_faucet.json │ ├── reportWebVitals.js │ ├── App.test.js │ ├── components │ │ ├── Utils │ │ │ ├── utils.js │ │ │ └── notify.js │ │ ├── Footer │ │ │ ├── index.js │ │ │ └── style.scss │ │ ├── Navbar │ │ │ ├── style.scss │ │ │ ├── CheckBalance │ │ │ │ └── index.js │ │ │ └── index.js │ │ └── Airdrop │ │ │ ├── style.scss │ │ │ └── index.js │ ├── index.js │ ├── App.js │ └── index.scss ├── .gitignore ├── config-overrides.js ├── package.json └── README.md ├── Cargo.toml ├── .gitignore ├── programs └── spl-token-faucet │ ├── Xargo.toml │ ├── Cargo.toml │ └── src │ └── lib.rs ├── spl_token_faucet-keypair.json ├── tsconfig.json ├── Brewfile ├── Anchor.toml ├── package.json ├── migrations └── deploy.ts ├── setup └── usdc_airdrop.js ├── tests └── spl-token-faucet.ts ├── README.md ├── LICENSE ├── Cargo.lock └── yarn.lock /app/CNAME: -------------------------------------------------------------------------------- 1 | spl-token-faucet.com 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | -------------------------------------------------------------------------------- /app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /programs/spl-token-faucet/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/credix-finance/spl-token-faucet/HEAD/app/public/favicon.ico -------------------------------------------------------------------------------- /spl_token_faucet-keypair.json: -------------------------------------------------------------------------------- 1 | [154,24,203,214,50,23,163,39,165,182,119,111,242,226,167,24,98,89,22,110,52,88,220,153,10,180,205,153,108,92,99,220,57,121,253,121,44,203,5,241,143,3,65,210,151,59,209,190,111,166,83,204,116,93,193,126,162,27,8,202,142,94,195,163] -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["mocha", "chai"], 4 | "typeRoots": ["./node_modules/@types"], 5 | "lib": ["es2015"], 6 | "module": "commonjs", 7 | "target": "es6", 8 | "esModuleInterop": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /Brewfile: -------------------------------------------------------------------------------- 1 | tap "caarlos0/tap" 2 | tap "homebrew/bundle" 3 | tap "homebrew/cask" 4 | tap "homebrew/core" 5 | brew "coreutils" 6 | brew "cowsay" 7 | brew "fortune" 8 | brew "gh" 9 | brew "kubectx" 10 | brew "libpq" 11 | brew "node" 12 | brew "pre-commit" 13 | brew "python@3.9" 14 | brew "ssss" 15 | -------------------------------------------------------------------------------- /app/src/config/config.js: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | 3 | export const programID = new PublicKey('4sN8PnN2ki2W4TFXAfzR645FWs8nimmsYeNtxM8RBK6A'); 4 | export const dummyMintPk = new PublicKey('Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr'); 5 | export const dummyMintPkBump = 255; 6 | -------------------------------------------------------------------------------- /Anchor.toml: -------------------------------------------------------------------------------- 1 | [programs.localnet] 2 | spl_token_faucet = "4sN8PnN2ki2W4TFXAfzR645FWs8nimmsYeNtxM8RBK6A" 3 | 4 | [registry] 5 | url = "https://anchor.projectserum.com" 6 | 7 | [provider] 8 | cluster = "localnet" 9 | wallet = "~/.config/solana/id.json" 10 | 11 | [scripts] 12 | test = "ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@project-serum/anchor": "^0.18.0", 4 | "@solana/spl-token": "^0.1.8" 5 | }, 6 | "devDependencies": { 7 | "@types/mocha": "^9.0.0", 8 | "chai": "^4.3.4", 9 | "mocha": "^9.0.3", 10 | "ts-mocha": "^8.0.0", 11 | "typescript": "^4.3.5" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Credix", 3 | "name": "Credix", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /programs/spl-token-faucet/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "spl-token-faucet" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "spl_token_faucet" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | cpi = ["no-entrypoint"] 15 | default = [] 16 | 17 | [dependencies] 18 | anchor-lang = "0.18.2" 19 | anchor-spl = "0.18.0" 20 | -------------------------------------------------------------------------------- /app/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = (onPerfEntry) => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ 4 | getCLS, getFID, getFCP, getLCP, getTTFB, 5 | }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | const mockEnqueue = jest.fn(); 6 | 7 | jest.mock('notistack', () => ({ 8 | ...jest.requireActual('notistack'), 9 | useSnackbar: () => ({ 10 | enqueueSnackbar: mockEnqueue, 11 | }), 12 | })); 13 | 14 | it('renders without crashing', () => { 15 | const div = document.createElement('div'); 16 | ReactDOM.render(, div); 17 | }); 18 | -------------------------------------------------------------------------------- /app/config-overrides.js: -------------------------------------------------------------------------------- 1 | const NodePolyfillPlugin = require("node-polyfill-webpack-plugin"); 2 | const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin"); 3 | 4 | module.exports = function override(config, env) { 5 | // do stuff with the webpack config... 6 | config.plugins.push(new NodePolyfillPlugin()); 7 | config.resolve.plugins = config.resolve.plugins.filter( 8 | (plugin) => !(plugin instanceof ModuleScopePlugin) 9 | ); 10 | return config; 11 | }; 12 | -------------------------------------------------------------------------------- /migrations/deploy.ts: -------------------------------------------------------------------------------- 1 | // Migrations are an early feature. Currently, they're nothing more than this 2 | // single deploy script that's invoked from the CLI, injecting a provider 3 | // configured from the workspace's Anchor.toml. 4 | 5 | const anchor = require("@project-serum/anchor"); 6 | 7 | module.exports = async function (provider) { 8 | // Configure client to use the provider. 9 | anchor.setProvider(provider); 10 | 11 | // Add your deploy script here. 12 | } 13 | -------------------------------------------------------------------------------- /app/src/components/Utils/utils.js: -------------------------------------------------------------------------------- 1 | import { Connection } from "@solana/web3.js"; 2 | import { AnchorProvider } from "@project-serum/anchor"; 3 | 4 | export function GetProvider(wallet, network) { 5 | const opts = { 6 | preflightCommitment: "processed", 7 | }; 8 | const connection = new Connection(network, opts.preflightCommitment); 9 | const provider = new AnchorProvider( 10 | connection, 11 | wallet, 12 | opts.preflightCommitment 13 | ); 14 | return [provider, connection]; 15 | } 16 | -------------------------------------------------------------------------------- /app/src/components/Footer/index.js: -------------------------------------------------------------------------------- 1 | import "./style.scss"; 2 | 3 | const Footer: FC = () => { 4 | return ( 5 |
6 |
7 | GitHub 8 |
9 |
10 | made with ❤ by credix.finance 11 |
12 |
13 | ); 14 | } 15 | 16 | export default Footer; 17 | -------------------------------------------------------------------------------- /app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.scss'; 4 | import { SnackbarProvider } from 'notistack'; 5 | import App from './App'; 6 | import reportWebVitals from './reportWebVitals'; 7 | 8 | ReactDOM.render( 9 | 10 | 11 | 12 | 13 | , 14 | document.getElementById('root'), 15 | ); 16 | 17 | // If you want to start measuring performance in your app, pass a function 18 | // to log results (for example: reportWebVitals(console.log)) 19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 20 | reportWebVitals(); 21 | -------------------------------------------------------------------------------- /app/public/credix_logo_zwart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/components/Footer/style.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | //width: 300px; 3 | position: absolute; 4 | bottom: 0; 5 | height: 40px; 6 | border-top: 1px solid lightgrey; 7 | text-align: right; 8 | display: flex; 9 | align-items: center; 10 | justify-content: flex-end; 11 | padding-right: 50px; 12 | 13 | a { 14 | text-decoration: none; 15 | font-size: 12px; 16 | display: inline-block; 17 | color: black; 18 | margin-left: 50px; 19 | margin-bottom: 0px; 20 | 21 | &:hover { 22 | font-weight: bold; 23 | } 24 | } 25 | } 26 | 27 | .footer-left { 28 | left: 0; 29 | border-right: 1px solid lightgrey; 30 | } 31 | 32 | .footer-right { 33 | right: 0; 34 | border-left: 1px solid lightgrey; 35 | } 36 | 37 | .start-here { 38 | font-weight: bold; 39 | } 40 | 41 | .green { 42 | font-weight: bold; 43 | color: green !important; 44 | } 45 | 46 | .animated { 47 | animation-duration: 2.5s; 48 | animation-fill-mode: both; 49 | animation-iteration-count: infinite; 50 | } 51 | 52 | @keyframes bounce { 53 | 0%, 20%, 50%, 80%, 100% {transform: translateY(0);} 54 | 40% {transform: translateY(-4px);} 55 | 60% {transform: translateY(-2px);} 56 | } 57 | .bounce { 58 | animation-name: bounce; 59 | } 60 | -------------------------------------------------------------------------------- /app/public/credix_logo_wit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/components/Navbar/style.scss: -------------------------------------------------------------------------------- 1 | .navbar-wrapper { 2 | width: 100%; 3 | position: absolute; 4 | top: 0; 5 | z-index: 1000; 6 | } 7 | 8 | .notification-bar { 9 | height: 40px; 10 | width: 100%; 11 | top: 0; 12 | background-color: #7cd06e; 13 | display: flex; 14 | justify-content: center; 15 | align-items: center; 16 | p { 17 | font-weight: bolder; 18 | font-size: 14px; 19 | } 20 | 21 | a { 22 | color: black; 23 | margin-left: 10px; 24 | } 25 | } 26 | 27 | .navbar-container { 28 | height: 70px; 29 | width: 100%; 30 | border-bottom: 1px solid lightgrey; 31 | display: flex; 32 | justify-content: space-between; 33 | align-items: center; 34 | } 35 | 36 | .logo-and-tag-line { 37 | width: 400px; 38 | display: flex; 39 | align-items: center; 40 | } 41 | 42 | .tag-line { 43 | display: inline-block; 44 | font-size: 12px; 45 | max-width: 400px; 46 | margin-left: 20px; 47 | padding-bottom: 3px; 48 | font-size: 20px; 49 | } 50 | 51 | .navbar-button { 52 | margin-right: 20px !important; 53 | } 54 | 55 | .balance-wallet-container { 56 | display: flex; 57 | justify-content: space-between; 58 | align-items: flex-end; 59 | } 60 | 61 | .balance-and-pk { 62 | margin-left: 20px; 63 | margin-right: 50px; 64 | 65 | h1 { 66 | font-size: 20px; 67 | margin: 0 !important; 68 | } 69 | 70 | p { 71 | color: grey; 72 | font-size: 10px; 73 | margin-top: 3px; 74 | } 75 | } 76 | 77 | img.logo { 78 | max-height: 40px; 79 | margin-left: 20px; 80 | } 81 | -------------------------------------------------------------------------------- /app/src/config/spl_token_faucet.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "name": "spl_token_faucet", 4 | "instructions": [ 5 | { 6 | "name": "airdrop", 7 | "accounts": [ 8 | { 9 | "name": "mint", 10 | "isMut": true, 11 | "isSigner": false 12 | }, 13 | { 14 | "name": "destination", 15 | "isMut": true, 16 | "isSigner": false 17 | }, 18 | { 19 | "name": "payer", 20 | "isMut": false, 21 | "isSigner": true 22 | }, 23 | { 24 | "name": "receiver", 25 | "isMut": false, 26 | "isSigner": false 27 | }, 28 | { 29 | "name": "systemProgram", 30 | "isMut": false, 31 | "isSigner": false 32 | }, 33 | { 34 | "name": "tokenProgram", 35 | "isMut": false, 36 | "isSigner": false 37 | }, 38 | { 39 | "name": "associatedTokenProgram", 40 | "isMut": false, 41 | "isSigner": false 42 | }, 43 | { 44 | "name": "rent", 45 | "isMut": false, 46 | "isSigner": false 47 | } 48 | ], 49 | "args": [ 50 | { 51 | "name": "mintBump", 52 | "type": "u8" 53 | }, 54 | { 55 | "name": "amount", 56 | "type": "u64" 57 | } 58 | ] 59 | } 60 | ], 61 | "metadata": { 62 | "address": "4sN8PnN2ki2W4TFXAfzR645FWs8nimmsYeNtxM8RBK6A" 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/components/Airdrop/style.scss: -------------------------------------------------------------------------------- 1 | .airdrop-pk-input { 2 | width: 100%; 3 | margin-top: 10px !important; 4 | margin-bottom: 40px !important; 5 | text-transform: none !important; 6 | 7 | &:disabled { 8 | opacity: 0.3; 9 | } 10 | } 11 | 12 | .network-dropdown { 13 | font-size: 12px !important; 14 | padding: 0; 15 | margin-bottom: 40px; 16 | margin-top: 10px; 17 | width: 100%; 18 | } 19 | 20 | .network-dropdown-wrapper { 21 | width: 500px; 22 | } 23 | 24 | .airdrop-container { 25 | height: calc(100vh - 70px); 26 | width: 100vw; 27 | position: absolute; 28 | bottom: 0; 29 | display: flex; 30 | justify-content: center; 31 | align-items: center; 32 | } 33 | 34 | .airdrop-wrapper { 35 | border: 1px solid black; 36 | padding: 40px; 37 | display: flex; 38 | max-width: 500px; 39 | flex-direction: column; 40 | justify-content: space-between; 41 | align-items: flex-end; 42 | 43 | h3 { 44 | width: 100%; 45 | margin: 0; 46 | } 47 | 48 | p { 49 | font-size: 12px; 50 | width: 100%; 51 | margin: 0; 52 | } 53 | } 54 | 55 | .sol-airdrop { 56 | width: 100% !important; 57 | margin-top: 10px !important; 58 | margin-bottom: 40px !important; 59 | } 60 | 61 | .stake-input { 62 | flex-grow: 2; 63 | margin-left: 0 !important; 64 | 65 | &:disabled { 66 | opacity: 0.3; 67 | } 68 | } 69 | .form-row { 70 | width: 100%; 71 | justify-content: flex-end; 72 | display: flex; 73 | margin-top: 10px; 74 | margin-bottom: 40px; 75 | 76 | input { 77 | margin-left: 10px; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { FC, useMemo, useState } from "react"; 2 | import { WalletDialogProvider } from "@solana/wallet-adapter-material-ui"; 3 | import { 4 | ConnectionProvider, 5 | useLocalStorage, 6 | WalletProvider, 7 | } from "@solana/wallet-adapter-react"; 8 | import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets"; 9 | import { BrowserRouter as Router, Route } from "react-router-dom"; 10 | import Navbar from "./components/Navbar"; 11 | import Footer from "./components/Footer"; 12 | import AirDrop from "./components/Airdrop"; 13 | 14 | const App: FC = () => { 15 | const [network, setNetwork] = useState("https://api.devnet.solana.com"); 16 | const [reload, setReload] = useState(true); 17 | const [autoConnect, _setAutoConnect] = useLocalStorage("autoConnect", false); 18 | const search = window.location.search; 19 | const params = new URLSearchParams(search); 20 | let tokenName = params.get("token-name"); 21 | if (!tokenName) { 22 | tokenName = "DUMMY"; 23 | } 24 | 25 | const wallets = useMemo(() => [new PhantomWalletAdapter()], []); 26 | 27 | return ( 28 | 29 | 30 | 31 | 32 | 33 | 40 |