├── src ├── App.css ├── index.css ├── main.jsx ├── ShowSolBalance.jsx ├── RequestAirdrop.jsx ├── SendTokens.jsx ├── SignMessage.jsx ├── App.jsx └── assets │ └── react.svg ├── vite.config.js ├── .gitignore ├── index.html ├── README.md ├── eslint.config.js ├── package.json └── public └── vite.svg /src/App.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import { nodePolyfills } from 'vite-plugin-node-polyfills' 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), nodePolyfills()], 8 | }) -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import App from './App.jsx' 4 | import './index.css' 5 | 6 | createRoot(document.getElementById('root')).render( 7 | 8 | 9 | , 10 | ) 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React + Vite 2 | 3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. 4 | 5 | Currently, two official plugins are available: 6 | 7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 | -------------------------------------------------------------------------------- /src/ShowSolBalance.jsx: -------------------------------------------------------------------------------- 1 | import { useConnection, useWallet } from "@solana/wallet-adapter-react"; 2 | import { LAMPORTS_PER_SOL } from "@solana/web3.js"; 3 | 4 | export function ShowSolBalance() { 5 | const { connection } = useConnection(); 6 | const wallet = useWallet(); 7 | 8 | async function getBalance() { 9 | if (wallet.publicKey) { 10 | 11 | const balance = await connection.getBalance(wallet.publicKey); 12 | document.getElementById("balance").innerHTML = balance / LAMPORTS_PER_SOL; 13 | } 14 | } 15 | 16 | getBalance(); 17 | return
18 |

SOL Balance:

19 |
20 | } -------------------------------------------------------------------------------- /src/RequestAirdrop.jsx: -------------------------------------------------------------------------------- 1 | import { useWallet } from "@solana/wallet-adapter-react"; 2 | import { useConnection } from "@solana/wallet-adapter-react"; 3 | import { LAMPORTS_PER_SOL } from "@solana/web3.js"; 4 | 5 | export function RequestAirdrop() { 6 | const wallet = useWallet(); 7 | const { connection } = useConnection(); 8 | 9 | async function requestAirdrop() { 10 | let amount = document.getElementById("amount").value; 11 | await connection.requestAirdrop(wallet.publicKey, amount * LAMPORTS_PER_SOL); 12 | alert("Airdropped " + amount + " SOL to " + wallet.publicKey.toBase58()); 13 | } 14 | 15 | return
16 |

17 | 18 | 19 |
20 | } -------------------------------------------------------------------------------- /src/SendTokens.jsx: -------------------------------------------------------------------------------- 1 | import { useConnection, useWallet } from "@solana/wallet-adapter-react" 2 | import { LAMPORTS_PER_SOL, PublicKey, SystemProgram, Transaction} from "@solana/web3.js"; 3 | 4 | 5 | export function SendTokens() { 6 | const wallet = useWallet(); 7 | const {connection} = useConnection(); 8 | 9 | async function sendTokens() { 10 | let to = document.getElementById("to").value; 11 | let amount = document.getElementById("amount").value; 12 | const transaction = new Transaction(); 13 | transaction.add(SystemProgram.transfer({ 14 | fromPubkey: wallet.publicKey, 15 | toPubkey: new PublicKey(to), 16 | lamports: amount * LAMPORTS_PER_SOL, 17 | })); 18 | 19 | await wallet.sendTransaction(transaction, connection); 20 | alert("Sent " + amount + " SOL to " + to); 21 | } 22 | 23 | return
24 | 25 | 26 | 27 |
28 | } -------------------------------------------------------------------------------- /src/SignMessage.jsx: -------------------------------------------------------------------------------- 1 | import { ed25519 } from '@noble/curves/ed25519'; 2 | import { useWallet } from '@solana/wallet-adapter-react'; 3 | import bs58 from 'bs58'; 4 | import React from 'react'; 5 | 6 | export function SignMessage() { 7 | const { publicKey, signMessage } = useWallet(); 8 | 9 | async function onClick() { 10 | if (!publicKey) throw new Error('Wallet not connected!'); 11 | if (!signMessage) throw new Error('Wallet does not support message signing!'); 12 | 13 | const message = document.getElementById("message").value; 14 | const encodedMessage = new TextEncoder().encode(message); 15 | const signature = await signMessage(encodedMessage); 16 | 17 | if (!ed25519.verify(signature, encodedMessage, publicKey.toBytes())) throw new Error('Message signature invalid!'); 18 | alert('success', `Message signature: ${bs58.encode(signature)}`); 19 | }; 20 | 21 | return ( 22 |
23 | 24 | 27 |
28 | ); 29 | }; -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import react from 'eslint-plugin-react' 4 | import reactHooks from 'eslint-plugin-react-hooks' 5 | import reactRefresh from 'eslint-plugin-react-refresh' 6 | 7 | export default [ 8 | { ignores: ['dist'] }, 9 | { 10 | files: ['**/*.{js,jsx}'], 11 | languageOptions: { 12 | ecmaVersion: 2020, 13 | globals: globals.browser, 14 | parserOptions: { 15 | ecmaVersion: 'latest', 16 | ecmaFeatures: { jsx: true }, 17 | sourceType: 'module', 18 | }, 19 | }, 20 | settings: { react: { version: '18.3' } }, 21 | plugins: { 22 | react, 23 | 'react-hooks': reactHooks, 24 | 'react-refresh': reactRefresh, 25 | }, 26 | rules: { 27 | ...js.configs.recommended.rules, 28 | ...react.configs.recommended.rules, 29 | ...react.configs['jsx-runtime'].rules, 30 | ...reactHooks.configs.recommended.rules, 31 | 'react/jsx-no-target-blank': 'off', 32 | 'react-refresh/only-export-components': [ 33 | 'warn', 34 | { allowConstantExport: true }, 35 | ], 36 | }, 37 | }, 38 | ] 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-week-5", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@noble/curves": "^1.5.0", 14 | "@solana/spl-token": "^0.4.8", 15 | "@solana/wallet-adapter-base": "^0.9.23", 16 | "@solana/wallet-adapter-react": "^0.15.35", 17 | "@solana/wallet-adapter-react-ui": "^0.9.35", 18 | "@solana/wallet-adapter-wallets": "^0.19.32", 19 | "@solana/web3.js": "^1.95.3", 20 | "buffer": "^6.0.3", 21 | "react": "^18.3.1", 22 | "react-dom": "^18.3.1", 23 | "vite-plugin-node-polyfills": "^0.22.0" 24 | }, 25 | "devDependencies": { 26 | "@eslint/js": "^9.9.0", 27 | "@types/react": "^18.3.3", 28 | "@types/react-dom": "^18.3.0", 29 | "@vitejs/plugin-react": "^4.3.1", 30 | "eslint": "^9.9.0", 31 | "eslint-plugin-react": "^7.35.0", 32 | "eslint-plugin-react-hooks": "^5.1.0-rc.0", 33 | "eslint-plugin-react-refresh": "^0.4.9", 34 | "globals": "^15.9.0", 35 | "vite": "^5.4.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from 'react'; 2 | import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'; 3 | import { WalletAdapterNetwork } from '@solana/wallet-adapter-base'; 4 | import { 5 | WalletModalProvider, 6 | WalletDisconnectButton, 7 | WalletMultiButton 8 | } from '@solana/wallet-adapter-react-ui'; 9 | import { clusterApiUrl } from '@solana/web3.js'; 10 | 11 | import '@solana/wallet-adapter-react-ui/styles.css'; 12 | import { SendTokens } from './SendTokens'; 13 | import { SignMessage } from './SignMessage'; 14 | 15 | function App() { 16 | const network = WalletAdapterNetwork.Devnet; 17 | 18 | const endpoint = useMemo(() => clusterApiUrl(network), [network]); 19 | 20 | return ( 21 | 22 | 23 | 24 |
25 | 26 | 27 |
28 | {/* 29 | */} 30 | {/* */} 31 | 32 | 33 |
34 |
35 |
36 | ); 37 | } 38 | 39 | export default App 40 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------