├── .gitignore ├── README.md ├── project-1-favorites ├── .gitignore ├── .prettierignore ├── Anchor.toml ├── Cargo.toml ├── README.md ├── migrations │ └── deploy.ts ├── package.json ├── pnpm-lock.yaml ├── programs │ └── favorites │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ └── lib.rs ├── tests │ ├── favorites.ts │ └── system-errors.ts └── tsconfig.json ├── project-10-lending ├── .gitattributes ├── .gitignore ├── .prettierignore ├── Anchor.toml ├── Cargo.toml ├── README.md ├── bankrun-utils │ └── bankrunConnection.ts ├── jest.config.ts ├── migrations │ └── deploy.ts ├── package.json ├── programs │ └── lending │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ ├── constants.rs │ │ ├── error.rs │ │ ├── instructions │ │ ├── admin.rs │ │ ├── borrow.rs │ │ ├── deposit.rs │ │ ├── liquidate.rs │ │ ├── mod.rs │ │ ├── repay.rs │ │ └── withdraw.rs │ │ ├── lib.rs │ │ ├── mod.rs │ │ └── state.rs ├── tests │ ├── bankrun.spec.ts │ └── fixtures │ │ └── lending.so └── tsconfig.json ├── project-11-programmable-money ├── README.md ├── frontend │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── anchor │ │ ├── idl.json │ │ ├── idlType.ts │ │ └── setup.ts │ ├── app │ │ ├── config │ │ │ └── page.tsx │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── liquidate │ │ │ └── page.tsx │ │ ├── page.tsx │ │ └── utils.ts │ ├── components.json │ ├── components │ │ ├── main-nav.tsx │ │ ├── providers │ │ │ ├── collateral-account-provider.tsx │ │ │ ├── config-account-provider.tsx │ │ │ ├── pyth-pricefeed-provider.tsx │ │ │ ├── theme-provider.tsx │ │ │ └── wallet-provider.tsx │ │ ├── site-header.tsx │ │ ├── stablecoin │ │ │ ├── collateral-table.tsx │ │ │ ├── collateral.tsx │ │ │ ├── deposit-withdraw.tsx │ │ │ ├── deposit.tsx │ │ │ ├── liquidate.tsx │ │ │ ├── toast.tsx │ │ │ ├── update-config.tsx │ │ │ └── withdraw.tsx │ │ ├── tailwind-indicator.tsx │ │ ├── ui │ │ │ ├── alert.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── dialog.tsx │ │ │ ├── form.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── select.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── slider.tsx │ │ │ ├── switch.tsx │ │ │ ├── table.tsx │ │ │ ├── tabs.tsx │ │ │ ├── toast.tsx │ │ │ ├── toaster.tsx │ │ │ ├── toggle.tsx │ │ │ └── use-toast.ts │ │ └── wallet-multi-button.tsx │ ├── config │ │ └── site.ts │ ├── lib │ │ ├── fonts.ts │ │ └── utils.ts │ ├── next.config.mjs │ ├── package.json │ ├── pnpm-lock.yaml │ ├── postcss.config.js │ ├── prettier.config.js │ ├── public │ │ ├── chibi.jpeg │ │ ├── next.svg │ │ └── vercel.svg │ ├── styles │ │ └── globals.css │ ├── tailwind.config.ts │ ├── tsconfig.json │ └── types │ │ └── nav.ts └── program │ ├── .gitignore │ ├── .prettierignore │ ├── Anchor.toml │ ├── Cargo.toml │ ├── migrations │ └── deploy.ts │ ├── package.json │ ├── programs │ └── stablecoin │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ ├── constants.rs │ │ ├── error.rs │ │ ├── instructions │ │ ├── admin │ │ │ ├── initialize_config.rs │ │ │ ├── mod.rs │ │ │ └── update_config.rs │ │ ├── deposit │ │ │ ├── deposit_collateral_and_mint_tokens.rs │ │ │ ├── mod.rs │ │ │ └── utils.rs │ │ ├── mod.rs │ │ ├── utils.rs │ │ └── withdraw │ │ │ ├── liquidate.rs │ │ │ ├── mod.rs │ │ │ ├── redeem_collateral_and_burn_tokens.rs │ │ │ └── utils.rs │ │ ├── lib.rs │ │ └── state.rs │ ├── tests │ └── stablecoin.ts │ └── tsconfig.json ├── project-12-attack-the-bank ├── README.md ├── bank_one │ ├── .gitignore │ ├── .prettierignore │ ├── Anchor.toml │ ├── Cargo.toml │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ └── bank_one │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── tests │ │ └── bank_one.ts │ └── tsconfig.json ├── bank_three │ ├── .gitignore │ ├── .prettierignore │ ├── Anchor.toml │ ├── Cargo.toml │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ ├── bank_three │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ │ └── lib.rs │ │ └── fake_bank │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── tests │ │ └── bank_three.ts │ └── tsconfig.json └── bank_two │ ├── .gitignore │ ├── .prettierignore │ ├── Anchor.toml │ ├── Cargo.toml │ ├── migrations │ └── deploy.ts │ ├── package.json │ ├── programs │ └── bank_two │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ └── lib.rs │ ├── tests │ └── bank_two.ts │ └── tsconfig.json ├── project-13-getting-to-production ├── LICENSE ├── README.md ├── anchor │ ├── .eslintrc.json │ ├── .swcrc │ ├── Anchor.toml │ ├── Cargo.toml │ ├── README.md │ ├── jest.config.ts │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ └── voting │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── project.json │ ├── src │ │ ├── index.ts │ │ └── voting-exports.ts │ ├── tests │ │ ├── fixtures │ │ │ └── voting.so │ │ └── voting.spec.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── jest.config.ts ├── jest.preset.js ├── nx.json ├── package.json ├── tsconfig.base.json ├── vercel.json └── web │ ├── .eslintrc.json │ ├── app │ ├── api │ │ ├── hello │ │ │ └── route.ts │ │ └── vote │ │ │ └── route.ts │ ├── global.css │ ├── layout.tsx │ ├── page.module.css │ ├── page.tsx │ └── react-query-provider.tsx │ ├── components │ ├── account │ │ ├── account-data-access.tsx │ │ ├── account-detail-feature.tsx │ │ ├── account-list-feature.tsx │ │ └── account-ui.tsx │ ├── cluster │ │ ├── cluster-data-access.tsx │ │ ├── cluster-feature.tsx │ │ └── cluster-ui.tsx │ ├── counter │ │ ├── counter-data-access.tsx │ │ ├── counter-feature.tsx │ │ └── counter-ui.tsx │ ├── dashboard │ │ └── dashboard-feature.tsx │ ├── solana │ │ └── solana-provider.tsx │ ├── ui │ │ └── ui-layout.tsx │ └── voting │ │ ├── voting-data-access.tsx │ │ ├── voting-feature.tsx │ │ └── voting-ui.tsx │ ├── index.d.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── postcss.config.js │ ├── project.json │ ├── public │ ├── .gitkeep │ ├── favicon.ico │ └── logo.png │ ├── tailwind.config.js │ └── tsconfig.json ├── project-2-voting ├── LICENSE ├── README.md ├── anchor │ ├── .eslintrc.json │ ├── .swcrc │ ├── Anchor.toml │ ├── Cargo.toml │ ├── README.md │ ├── jest.config.ts │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ └── voting │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── project.json │ ├── src │ │ ├── index.ts │ │ └── voting-exports.ts │ ├── tests │ │ ├── bankrun.spec.ts │ │ ├── basic.spec.ts │ │ └── fixtures │ │ │ └── voting.so │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── jest.config.ts ├── jest.preset.js ├── nx.json ├── package.json ├── tsconfig.base.json ├── vercel.json └── web │ ├── .eslintrc.json │ ├── app │ ├── account │ │ ├── [address] │ │ │ └── page.tsx │ │ └── page.tsx │ ├── api │ │ ├── hello │ │ │ └── route.ts │ │ └── vote │ │ │ └── route.ts │ ├── basic │ │ └── page.tsx │ ├── clusters │ │ └── page.tsx │ ├── global.css │ ├── layout.tsx │ ├── page.module.css │ ├── page.tsx │ └── react-query-provider.tsx │ ├── components │ ├── account │ │ ├── account-data-access.tsx │ │ ├── account-detail-feature.tsx │ │ ├── account-list-feature.tsx │ │ └── account-ui.tsx │ ├── basic │ │ ├── basic-data-access.tsx │ │ ├── basic-feature.tsx │ │ └── basic-ui.tsx │ ├── cluster │ │ ├── cluster-data-access.tsx │ │ ├── cluster-feature.tsx │ │ └── cluster-ui.tsx │ ├── dashboard │ │ └── dashboard-feature.tsx │ ├── solana │ │ └── solana-provider.tsx │ └── ui │ │ └── ui-layout.tsx │ ├── index.d.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── postcss.config.js │ ├── project.json │ ├── public │ ├── .gitkeep │ ├── favicon.ico │ └── logo.png │ ├── tailwind.config.js │ └── tsconfig.json ├── project-3-blinks ├── LICENSE ├── README.md ├── anchor │ ├── .eslintrc.json │ ├── .swcrc │ ├── Anchor.toml │ ├── Cargo.toml │ ├── README.md │ ├── jest.config.ts │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ └── voting │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── project.json │ ├── src │ │ ├── counter-exports.ts │ │ └── index.ts │ ├── tests │ │ ├── fixtures │ │ │ └── voting.so │ │ └── voting.spec.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── jest.config.ts ├── jest.preset.js ├── nx.json ├── package.json ├── tsconfig.base.json ├── vercel.json └── web │ ├── .eslintrc.json │ ├── app │ ├── account │ │ ├── [address] │ │ │ └── page.tsx │ │ └── page.tsx │ ├── api │ │ ├── hello │ │ │ └── route.ts │ │ └── vote │ │ │ └── route.ts │ ├── clusters │ │ └── page.tsx │ ├── counter │ │ └── page.tsx │ ├── global.css │ ├── layout.tsx │ ├── page.module.css │ ├── page.tsx │ └── react-query-provider.tsx │ ├── components │ ├── account │ │ ├── account-data-access.tsx │ │ ├── account-detail-feature.tsx │ │ ├── account-list-feature.tsx │ │ └── account-ui.tsx │ ├── cluster │ │ ├── cluster-data-access.tsx │ │ ├── cluster-feature.tsx │ │ └── cluster-ui.tsx │ ├── counter │ │ ├── counter-data-access.tsx │ │ ├── counter-feature.tsx │ │ └── counter-ui.tsx │ ├── dashboard │ │ └── dashboard-feature.tsx │ ├── solana │ │ └── solana-provider.tsx │ └── ui │ │ └── ui-layout.tsx │ ├── index.d.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── postcss.config.js │ ├── project.json │ ├── public │ ├── .gitkeep │ ├── favicon.ico │ └── logo.png │ ├── tailwind.config.js │ └── tsconfig.json ├── project-4-crud-app ├── .gitignore ├── LICENSE ├── README.md ├── anchor │ ├── .eslintrc.json │ ├── .swcrc │ ├── Anchor.toml │ ├── Cargo.toml │ ├── README.md │ ├── jest.config.ts │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ └── journal │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── project.json │ ├── src │ │ ├── index.ts │ │ └── journal-exports.ts │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── jest.config.ts ├── jest.preset.js ├── nx.json ├── package.json ├── tsconfig.base.json ├── vercel.json └── web │ ├── .eslintrc.json │ ├── app │ ├── account │ │ ├── [address] │ │ │ └── page.tsx │ │ └── page.tsx │ ├── api │ │ └── hello │ │ │ └── route.ts │ ├── clusters │ │ └── page.tsx │ ├── global.css │ ├── journal │ │ └── page.tsx │ ├── layout.tsx │ ├── page.module.css │ ├── page.tsx │ └── react-query-provider.tsx │ ├── components │ ├── account │ │ ├── account-data-access.tsx │ │ ├── account-detail-feature.tsx │ │ ├── account-list-feature.tsx │ │ └── account-ui.tsx │ ├── cluster │ │ ├── cluster-data-access.tsx │ │ ├── cluster-feature.tsx │ │ └── cluster-ui.tsx │ ├── dashboard │ │ └── dashboard-feature.tsx │ ├── journal │ │ ├── journal-data-access.tsx │ │ ├── journal-feature.tsx │ │ └── journal-ui.tsx │ ├── solana │ │ └── solana-provider.tsx │ └── ui │ │ └── ui-layout.tsx │ ├── index.d.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── postcss.config.js │ ├── project.json │ ├── public │ ├── .gitkeep │ ├── favicon.ico │ └── solana-logo.png │ ├── tailwind.config.js │ └── tsconfig.json ├── project-5-tokens ├── README.md ├── create-token-metadata.ts ├── create-token-mint.ts ├── mint-tokens.ts └── send-spl-tokens.ts ├── project-6-nfts ├── README.md ├── create-collection.ts ├── create-nft.ts ├── package.json └── verify-nft.ts ├── project-7-swap ├── .gitignore ├── .prettierignore ├── Anchor.toml ├── Cargo.toml ├── README.md ├── migrations │ └── deploy.ts ├── package.json ├── programs │ └── swap │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ ├── constants.rs │ │ ├── error.rs │ │ ├── instructions │ │ ├── make_offer.rs │ │ ├── mod.rs │ │ ├── shared.rs │ │ └── take_offer.rs │ │ ├── lib.rs │ │ └── state │ │ ├── mod.rs │ │ └── offer.rs ├── tests │ └── swap.ts └── tsconfig.json ├── project-8-token-vesting ├── LICENSE ├── README copy.md ├── README.md ├── anchor │ ├── .eslintrc.json │ ├── .swcrc │ ├── Anchor.toml │ ├── Cargo.toml │ ├── README.md │ ├── jest.config.ts │ ├── migrations │ │ └── deploy.ts │ ├── package.json │ ├── programs │ │ └── vesting │ │ │ ├── Cargo.toml │ │ │ ├── Xargo.toml │ │ │ └── src │ │ │ └── lib.rs │ ├── project.json │ ├── src │ │ ├── index.ts │ │ └── vesting-exports.ts │ ├── tests │ │ ├── bankrun.spec.ts │ │ └── fixtures │ │ │ └── vesting.so │ ├── tsconfig.json │ ├── tsconfig.lib.json │ └── tsconfig.spec.json ├── jest.config.ts ├── jest.preset.js ├── nx.json ├── package.json ├── tsconfig.base.json ├── vercel.json └── web │ ├── .eslintrc.json │ ├── app │ ├── account │ │ ├── [address] │ │ │ └── page.tsx │ │ └── page.tsx │ ├── api │ │ └── hello │ │ │ └── route.ts │ ├── clusters │ │ └── page.tsx │ ├── global.css │ ├── layout.tsx │ ├── page.module.css │ ├── page.tsx │ ├── react-query-provider.tsx │ └── vesting │ │ └── page.tsx │ ├── components │ ├── account │ │ ├── account-data-access.tsx │ │ ├── account-detail-feature.tsx │ │ ├── account-list-feature.tsx │ │ └── account-ui.tsx │ ├── cluster │ │ ├── cluster-data-access.tsx │ │ ├── cluster-feature.tsx │ │ └── cluster-ui.tsx │ ├── dashboard │ │ └── dashboard-feature.tsx │ ├── solana │ │ └── solana-provider.tsx │ ├── ui │ │ └── ui-layout.tsx │ └── vesting │ │ ├── vesting-data-access.tsx │ │ ├── vesting-feature.tsx │ │ └── vesting-ui.tsx │ ├── index.d.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── postcss.config.js │ ├── project.json │ ├── public │ ├── .gitkeep │ ├── favicon.ico │ └── logo.png │ ├── tailwind.config.js │ └── tsconfig.json └── project-9-token-lottery ├── Anchor.toml ├── Cargo.toml ├── README.md ├── metadata.json ├── migrations └── deploy.ts ├── package.json ├── programs └── token-lottery │ ├── Cargo.toml │ ├── Xargo.toml │ └── src │ └── lib.rs ├── setup ├── metadata.so ├── ondemand.so ├── oracle0.json ├── oracle1.json ├── oracle2.json ├── oracle3.json ├── oracle4.json ├── oracle5.json ├── oracle6.json ├── oracle7.json ├── package.json ├── randomness_queue.json ├── sb_randomness_config.json ├── setup-local.sh ├── start-validator.sh └── switchboard.so ├── tests ├── ondemand-idl.json └── token-lottery.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | yarn.lock 3 | package-lock.json 4 | target/ 5 | .DS_Store 6 | .nx 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules 38 | jspm_packages 39 | 40 | # Optional npm cache directory 41 | .npm 42 | 43 | # Optional REPL history 44 | .node_repl_history 45 | .next/ 46 | .anchor/ -------------------------------------------------------------------------------- /project-1-favorites/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .anchor 3 | .DS_Store 4 | target 5 | **/*.rs.bk 6 | node_modules 7 | test-ledger 8 | .yarn 9 | .env 10 | -------------------------------------------------------------------------------- /project-1-favorites/.prettierignore: -------------------------------------------------------------------------------- 1 | 2 | .anchor 3 | .DS_Store 4 | target 5 | node_modules 6 | dist 7 | build 8 | test-ledger 9 | -------------------------------------------------------------------------------- /project-1-favorites/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | favorites = "ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "pnpm ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | -------------------------------------------------------------------------------- /project-1-favorites/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | 12 | [profile.release.build-override] 13 | opt-level = 3 14 | incremental = false 15 | codegen-units = 1 16 | -------------------------------------------------------------------------------- /project-1-favorites/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('@coral-xyz/anchor'); 6 | 7 | module.exports = async (provider) => { 8 | // Configure client to use the provider. 9 | anchor.setProvider(provider); 10 | 11 | // Add your deploy script here. 12 | }; 13 | -------------------------------------------------------------------------------- /project-1-favorites/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 4 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 5 | }, 6 | "dependencies": { 7 | "@coral-xyz/anchor": "^0.30.0", 8 | "@solana-developers/helpers": "^2.0.0" 9 | }, 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@types/bn.js": "^5.1.0", 13 | "@types/chai": "^4.3.0", 14 | "@types/mocha": "^9.0.0", 15 | "chai": "^4.3.4", 16 | "mocha": "^9.0.3", 17 | "prettier": "^2.6.2", 18 | "ts-mocha": "^10.0.0", 19 | "typescript": "^4.3.5" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /project-1-favorites/programs/favorites/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "favorites" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "favorites" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = {version = "0.30.1", features = ["init-if-needed"]} 21 | solana-program = "=1.18.5" 22 | -------------------------------------------------------------------------------- /project-1-favorites/programs/favorites/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-1-favorites/tests/system-errors.ts: -------------------------------------------------------------------------------- 1 | // From https://github.com/solana-labs/solana/blob/a94920a4eadf1008fc292e47e041c1b3b0d949df/sdk/program/src/system_instruction.rs 2 | export const systemProgramErrors = [ 3 | 'an account with the same address already exists', 4 | 5 | 'account does not have enough SOL to perform the operation', 6 | 7 | 'cannot assign account to this program id', 8 | 9 | 'cannot allocate account data of this length', 10 | 11 | 'length of requested seed is too long', 12 | 13 | 'provided address does not match addressed derived from seed', 14 | 15 | 'advancing stored nonce requires a populated RecentBlockhashes sysvar', 16 | 17 | 'stored nonce is still in recent_blockhashes', 18 | 19 | 'specified nonce does not match stored nonce', 20 | ]; 21 | -------------------------------------------------------------------------------- /project-1-favorites/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 | -------------------------------------------------------------------------------- /project-10-lending/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /project-10-lending/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /project-10-lending/.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /project-10-lending/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | anchor_version = "0.30.1" 3 | 4 | [features] 5 | resolution = true 6 | skip-lint = false 7 | 8 | [programs.localnet] 9 | lending = "CdZeD33fXsAHfZYS8jdxg4qHgXYJwBQ1Bv6GJyETtLST" 10 | 11 | [registry] 12 | url = "https://api.apr.dev" 13 | 14 | [provider] 15 | cluster = "Localnet" 16 | wallet = "~/.config/solana/id.json" 17 | 18 | [scripts] 19 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 20 | -------------------------------------------------------------------------------- /project-10-lending/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-10-lending/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { readFileSync } from 'fs'; 3 | 4 | // Reading the SWC compilation config and remove the "exclude" 5 | // for the test files to be compiled by SWC 6 | const { exclude: _, ...swcJestConfig } = JSON.parse( 7 | readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8 | ); 9 | 10 | // disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11 | // If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12 | if (swcJestConfig.swcrc === undefined) { 13 | swcJestConfig.swcrc = false; 14 | } 15 | 16 | // Uncomment if using global setup/teardown files being transformed via swc 17 | // https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries 18 | // jest needs EsModule Interop to find the default exported setup/teardown functions 19 | // swcJestConfig.module.noInterop = false; 20 | 21 | export default { 22 | displayName: 'anchor', 23 | preset: '../jest.preset.js', 24 | transform: { 25 | '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 26 | }, 27 | moduleFileExtensions: ['ts', 'js', 'html'], 28 | testEnvironment: '', 29 | coverageDirectory: '../coverage/anchor', 30 | }; 31 | -------------------------------------------------------------------------------- /project-10-lending/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-10-lending/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "ISC", 3 | "scripts": { 4 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 | }, 7 | "dependencies": { 8 | "@coral-xyz/anchor": "^0.30.1", 9 | "@pythnetwork/price-service-client": "^1.9.0", 10 | "@pythnetwork/pyth-solana-receiver": "^0.8.0", 11 | "@solana/spl-token": "0.4.8", 12 | "@solana/web3.js": "1.94.0", 13 | "anchor-bankrun": "0.4.0", 14 | "solana-bankrun": "0.2.0", 15 | "spl-token-bankrun": "0.2.5", 16 | "rpc-websockets": "7.11.0" 17 | }, 18 | "devDependencies": { 19 | "@types/bn.js": "^5.1.0", 20 | "@types/chai": "^4.3.0", 21 | "@types/mocha": "^9.0.0", 22 | "chai": "^4.3.4", 23 | "mocha": "^9.0.3", 24 | "prettier": "^2.6.2", 25 | "ts-mocha": "^10.0.0", 26 | "typescript": "^4.3.5" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /project-10-lending/programs/lending/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lending" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "lending" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version="0.30.1", features=["init-if-needed"] } 21 | anchor-spl = "0.30.1" 22 | pyth-sdk-solana = "0.10.1" 23 | pyth-solana-receiver-sdk = "0.3.1" 24 | solana-program = "1.18.17" 25 | -------------------------------------------------------------------------------- /project-10-lending/programs/lending/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-10-lending/programs/lending/src/constants.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[constant] 4 | // https://pyth.network/developers/price-feed-ids#solana-stable 5 | pub const SOL_USD_FEED_ID: &str = "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"; 6 | pub const USDC_USD_FEED_ID: &str = "0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a"; 7 | pub const MAXIMUM_AGE: u64 = 100; // allow price feed 100 sec old, to avoid stale price feed errors 8 | 9 | -------------------------------------------------------------------------------- /project-10-lending/programs/lending/src/error.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[error_code] 4 | pub enum ErrorCode { 5 | #[msg("Borrowed amount exceeds the maximum LTV.")] 6 | OverLTV, 7 | #[msg("Borrowed amount results in an under collateralized loan.")] 8 | UnderCollateralized, 9 | #[msg("Insufficient funds to withdraw.")] 10 | InsufficientFunds, 11 | #[msg("Attempting to repay more than borrowed.")] 12 | OverRepay, 13 | #[msg("Attempting to borrow more than allowed.")] 14 | OverBorrowableAmount, 15 | #[msg("User is not undercollateralized.")] 16 | NotUndercollateralized 17 | } -------------------------------------------------------------------------------- /project-10-lending/programs/lending/src/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | pub use admin::*; 2 | pub mod admin; 3 | pub use deposit::*; 4 | pub mod deposit; 5 | pub use borrow::*; 6 | pub mod borrow; 7 | pub use withdraw::*; 8 | pub mod withdraw; 9 | pub use repay::*; 10 | pub mod repay; 11 | pub use liquidate::*; 12 | pub mod liquidate; -------------------------------------------------------------------------------- /project-10-lending/programs/lending/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use instructions::*; 3 | 4 | mod state; 5 | mod instructions; 6 | mod error; 7 | mod constants; 8 | 9 | declare_id!("CdZeD33fXsAHfZYS8jdxg4qHgXYJwBQ1Bv6GJyETtLST"); 10 | 11 | #[program] 12 | pub mod lending_protocol { 13 | 14 | use super::*; 15 | 16 | pub fn init_bank(ctx: Context, liquidation_threshold: u64, max_ltv: u64) -> Result<()> { 17 | process_init_bank(ctx, liquidation_threshold, max_ltv) 18 | } 19 | 20 | pub fn init_user(ctx: Context, usdc_address: Pubkey) -> Result<()> { 21 | process_init_user(ctx, usdc_address) 22 | } 23 | 24 | pub fn deposit (ctx: Context, amount: u64) -> Result<()> { 25 | process_deposit(ctx, amount) 26 | } 27 | 28 | pub fn withdraw (ctx: Context, amount: u64) -> Result<()> { 29 | process_withdraw(ctx, amount) 30 | } 31 | 32 | pub fn borrow(ctx: Context, amount: u64) -> Result<()> { 33 | process_borrow(ctx, amount) 34 | } 35 | 36 | pub fn repay(ctx: Context, amount: u64) -> Result<()> { 37 | process_repay(ctx, amount) 38 | } 39 | 40 | pub fn liquidate(ctx: Context) -> Result<()> { 41 | process_liquidate(ctx) 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /project-10-lending/programs/lending/src/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod state; 2 | pub mod error; 3 | pub mod instructions; 4 | pub mod constants; -------------------------------------------------------------------------------- /project-10-lending/tests/fixtures/lending.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-10-lending/tests/fixtures/lending.so -------------------------------------------------------------------------------- /project-10-lending/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 | -------------------------------------------------------------------------------- /project-11-programmable-money/README.md: -------------------------------------------------------------------------------- 1 | # Programmable Money 2 | 3 | ### Disclaimer: This code is not audited and should not be used in production. There are several edge cases that have not been addressed and error handling that has not been implemented. This is for education purposes only. 4 | 5 | ## Frontend 6 | 7 | View hosted frontend here: [Programmable Money UI](anchor-stablecoin.vercel.app) 8 | 9 | ## Anchor Program 10 | 11 | 1. Build the program 12 | 13 | ```shell 14 | cd program 15 | anchor build 16 | ``` 17 | 18 | 2. Run local validator 19 | 20 | ```shell 21 | solana-test-validator 22 | ``` 23 | 24 | 3. Deploy the program locally 25 | 26 | ```shell 27 | anchor deploy --provider.cluster localnet 28 | ``` 29 | 30 | 4. Test 31 | 32 | ```shell 33 | anchor test 34 | ``` 35 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "react-hooks/rules-of-hooks": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/anchor/setup.ts: -------------------------------------------------------------------------------- 1 | import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js"; 2 | import { IdlAccounts, Program } from "@coral-xyz/anchor"; 3 | import type { Stablecoin } from "./idlType"; 4 | import idl from "./idl.json"; 5 | 6 | const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); 7 | 8 | export const program = new Program(idl as Stablecoin, { 9 | connection, 10 | }); 11 | 12 | export const [configPDA] = PublicKey.findProgramAddressSync( 13 | [Buffer.from("config")], 14 | program.programId, 15 | ); 16 | 17 | export type ConfigAccount = IdlAccounts["config"]; 18 | export type CollateralAccount = IdlAccounts["collateral"]; 19 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/app/config/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import UpdateConfigUI from "@/components/stablecoin/update-config"; 4 | 5 | export default function ConfigPage() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-11-programmable-money/frontend/app/favicon.ico -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/app/liquidate/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import CollateralAccountsTable from "@/components/stablecoin/collateral-table"; 4 | 5 | export default function LiquidatePage() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/app/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import DepositAndWithdraw from "@/components/stablecoin/deposit-withdraw"; 4 | import CollateralAccountDisplay from "@/components/stablecoin/collateral"; 5 | 6 | export default function DepositWithdrawPage() { 7 | return ( 8 |
9 | 10 | 11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/main-nav.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import Link from "next/link"; 3 | import { NavItem } from "@/types/nav"; 4 | import { siteConfig } from "@/config/site"; 5 | import { cn } from "@/lib/utils"; 6 | 7 | interface MainNavProps { 8 | items?: NavItem[]; 9 | } 10 | 11 | export function MainNav({ items }: MainNavProps) { 12 | return ( 13 |
14 | 15 | {siteConfig.name} 16 | 17 | {items?.length ? ( 18 | 35 | ) : null} 36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/providers/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as React from "react"; 4 | import { ThemeProvider as NextThemesProvider } from "next-themes"; 5 | import { type ThemeProviderProps } from "next-themes/dist/types"; 6 | 7 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 8 | return {children}; 9 | } 10 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/providers/wallet-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { WalletAdapterNetwork } from "@solana/wallet-adapter-base"; 4 | import { 5 | ConnectionProvider, 6 | WalletProvider, 7 | } from "@solana/wallet-adapter-react"; 8 | import { WalletModalProvider } from "@solana/wallet-adapter-react-ui"; 9 | import { clusterApiUrl } from "@solana/web3.js"; 10 | import "@solana/wallet-adapter-react-ui/styles.css"; 11 | import { useMemo } from "react"; 12 | 13 | export function SolanaWalletProvider({ 14 | children, 15 | }: { 16 | children: React.ReactNode; 17 | }) { 18 | const network = WalletAdapterNetwork.Devnet; 19 | const endpoint = useMemo(() => clusterApiUrl(network), [network]); 20 | 21 | return ( 22 | 23 | 24 | {children} 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/site-header.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { siteConfig } from "@/config/site"; 4 | import { MainNav } from "@/components/main-nav"; 5 | import { WalletMultiButton } from "@solana/wallet-adapter-react-ui"; 6 | 7 | export function SiteHeader() { 8 | return ( 9 |
10 |
11 | 12 |
13 | 16 |
17 |
18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/stablecoin/deposit-withdraw.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; 3 | import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; 4 | import CollateralMintUI from "@/components/stablecoin/deposit"; 5 | import RedeemBurnUI from "@/components/stablecoin/withdraw"; 6 | 7 | // deposit/withdraw widget 8 | const DepositWithdrawUI = () => { 9 | const [mode, setMode] = useState("deposit"); 10 | 11 | return ( 12 | 13 | 14 | Deposit and Withdraw 15 | 16 | 17 | 18 | 19 | Deposit 20 | Withdraw 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | ); 32 | }; 33 | 34 | export default DepositWithdrawUI; 35 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/stablecoin/toast.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useToast } from "@/components/ui/use-toast"; 3 | import { Button } from "@/components/ui/button"; 4 | import { ExternalLink } from "lucide-react"; 5 | 6 | // Toast with link to solana explorer transaction 7 | export const useTransactionToast = () => { 8 | const { toast } = useToast(); 9 | 10 | const showTransactionToast = (transactionSignature: string) => { 11 | toast({ 12 | title: "Transaction Sent", 13 | description: ( 14 | 29 | ), 30 | duration: 3000, 31 | }); 32 | }; 33 | 34 | return { showTransactionToast }; 35 | }; 36 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/tailwind-indicator.tsx: -------------------------------------------------------------------------------- 1 | export function TailwindIndicator() { 2 | if (process.env.NODE_ENV === "production") return null; 3 | 4 | return ( 5 |
6 |
xs
7 |
sm
8 |
md
9 |
lg
10 |
xl
11 |
2xl
12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/checkbox.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox" 5 | import { Check } from "lucide-react" 6 | 7 | import { cn } from "@/lib/utils" 8 | 9 | const Checkbox = React.forwardRef< 10 | React.ElementRef, 11 | React.ComponentPropsWithoutRef 12 | >(({ className, ...props }, ref) => ( 13 | 21 | 24 | 25 | 26 | 27 | )) 28 | Checkbox.displayName = CheckboxPrimitive.Root.displayName 29 | 30 | export { Checkbox } 31 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes {} 7 | 8 | const Input = React.forwardRef( 9 | ({ className, type, ...props }, ref) => { 10 | return ( 11 | 20 | ) 21 | } 22 | ) 23 | Input.displayName = "Input" 24 | 25 | export { Input } 26 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as LabelPrimitive from "@radix-ui/react-label" 5 | import { cva, type VariantProps } from "class-variance-authority" 6 | 7 | import { cn } from "@/lib/utils" 8 | 9 | const labelVariants = cva( 10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 11 | ) 12 | 13 | const Label = React.forwardRef< 14 | React.ElementRef, 15 | React.ComponentPropsWithoutRef & 16 | VariantProps 17 | >(({ className, ...props }, ref) => ( 18 | 23 | )) 24 | Label.displayName = LabelPrimitive.Root.displayName 25 | 26 | export { Label } 27 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ); 13 | } 14 | 15 | export { Skeleton }; 16 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/slider.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as SliderPrimitive from "@radix-ui/react-slider" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Slider = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | 21 | 22 | 23 | 24 | 25 | )) 26 | Slider.displayName = SliderPrimitive.Root.displayName 27 | 28 | export { Slider } 29 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/switch.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as SwitchPrimitives from "@radix-ui/react-switch" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Switch = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | 25 | 26 | )) 27 | Switch.displayName = SwitchPrimitives.Root.displayName 28 | 29 | export { Switch } 30 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/ui/toaster.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import { 4 | Toast, 5 | ToastClose, 6 | ToastDescription, 7 | ToastProvider, 8 | ToastTitle, 9 | ToastViewport, 10 | } from "@/components/ui/toast" 11 | import { useToast } from "@/components/ui/use-toast" 12 | 13 | export function Toaster() { 14 | const { toasts } = useToast() 15 | 16 | return ( 17 | 18 | {toasts.map(function ({ id, title, description, action, ...props }) { 19 | return ( 20 | 21 |
22 | {title && {title}} 23 | {description && ( 24 | {description} 25 | )} 26 |
27 | {action} 28 | 29 |
30 | ) 31 | })} 32 | 33 |
34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/components/wallet-multi-button.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import dynamic from "next/dynamic"; 4 | 5 | const WalletMultiButton = dynamic( 6 | () => 7 | import("@solana/wallet-adapter-react-ui").then( 8 | (module) => module.WalletMultiButton, 9 | ), 10 | { ssr: false }, 11 | ); 12 | 13 | export default WalletMultiButton; 14 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/config/site.ts: -------------------------------------------------------------------------------- 1 | export type SiteConfig = typeof siteConfig; 2 | 3 | export const siteConfig = { 4 | name: "StableCoin", 5 | mainNav: [ 6 | { 7 | title: "Deposit/Withdraw", 8 | href: "/", 9 | }, 10 | { 11 | title: "Liquidate", 12 | href: "/liquidate", 13 | }, 14 | { 15 | title: "Config", 16 | href: "/config", 17 | }, 18 | ], 19 | }; 20 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/lib/fonts.ts: -------------------------------------------------------------------------------- 1 | import { 2 | JetBrains_Mono as FontMono, 3 | Inter as FontSans, 4 | } from "next/font/google"; 5 | 6 | export const fontSans = FontSans({ 7 | subsets: ["latin"], 8 | variable: "--font-sans", 9 | }); 10 | 11 | export const fontMono = FontMono({ 12 | subsets: ["latin"], 13 | variable: "--font-mono", 14 | }); 15 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: false, 4 | }; 5 | 6 | export default nextConfig; 7 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/prettier.config.js: -------------------------------------------------------------------------------- 1 | // prettier.config.js 2 | module.exports = { 3 | plugins: ['prettier-plugin-tailwindcss'], 4 | } -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/public/chibi.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-11-programmable-money/frontend/public/chibi.jpeg -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /project-11-programmable-money/frontend/types/nav.ts: -------------------------------------------------------------------------------- 1 | export interface NavItem { 2 | title: string; 3 | href?: string; 4 | disabled?: boolean; 5 | external?: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | stablecoin = "6DjiD8tQhJ9ZS3WZrwNubfoBRBrqfWacNR3bXBQ7ir91" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "devnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | 20 | [test] 21 | startup_wait = 5000 22 | shutdown_wait = 2000 23 | upgradeable = false 24 | 25 | [test.validator] 26 | bind_address = "0.0.0.0" 27 | url = "https://api.mainnet-beta.solana.com" 28 | ledger = ".anchor/test-ledger" 29 | rpc_port = 8899 30 | 31 | [[test.validator.clone]] 32 | address = "7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE" 33 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "ISC", 3 | "scripts": { 4 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 | }, 7 | "dependencies": { 8 | "@coral-xyz/anchor": "^0.30.1", 9 | "@pythnetwork/price-service-client": "^1.9.0", 10 | "@pythnetwork/pyth-solana-receiver": "0.7.0", 11 | "@solana/web3.js": "1.73.0", 12 | "rpc-websockets": "7.11.0" 13 | }, 14 | "devDependencies": { 15 | "@types/bn.js": "^5.1.0", 16 | "@types/chai": "^4.3.0", 17 | "@types/mocha": "^9.0.0", 18 | "chai": "^4.3.4", 19 | "mocha": "^9.0.3", 20 | "prettier": "^2.6.2", 21 | "ts-mocha": "^10.0.0", 22 | "typescript": "^4.3.5" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stablecoin" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "stablecoin" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version = "0.30.1", features = ["init-if-needed"] } 21 | anchor-spl = "0.30.1" 22 | pyth-solana-receiver-sdk = "0.2.0" 23 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/constants.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | pub const SEED_CONFIG_ACCOUNT: &[u8] = b"config"; 4 | pub const SEED_COLLATERAL_ACCOUNT: &[u8] = b"collateral"; 5 | pub const SEED_SOL_ACCOUNT: &[u8] = b"sol"; 6 | pub const SEED_MINT_ACCOUNT: &[u8] = b"mint"; 7 | 8 | #[constant] 9 | pub const FEED_ID: &str = "0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"; 10 | pub const MAXIMUM_AGE: u64 = 100; // allow pricefeed 100 sec old, to avoid stale price feed errors 11 | pub const PRICE_FEED_DECIMAL_ADJUSTMENT: u128 = 10; // price feed returns 1e8, multiple by 10 to match lamports 10e9 12 | 13 | // Constants for configuration values 14 | pub const LIQUIDATION_THRESHOLD: u64 = 50; // 200% over-collateralized 15 | pub const LIQUIDATION_BONUS: u64 = 10; // 10% bonus lamports when liquidating 16 | pub const MIN_HEALTH_FACTOR: u64 = 1; 17 | pub const MINT_DECIMALS: u8 = 9; 18 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/error.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[error_code] 4 | pub enum CustomError { 5 | #[msg("Below Minimum Health Factor")] 6 | BelowMinimumHealthFactor, 7 | #[msg("Above Minimum Health Factor, Cannot Liquidate Healthy Account")] 8 | AboveMinimumHealthFactor, 9 | #[msg("Price should not be negative")] 10 | InvalidPrice, 11 | } 12 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/instructions/admin/mod.rs: -------------------------------------------------------------------------------- 1 | pub use initialize_config::*; 2 | pub mod update_config; 3 | pub use update_config::*; 4 | pub mod initialize_config; 5 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/instructions/admin/update_config.rs: -------------------------------------------------------------------------------- 1 | use crate::{Config, SEED_CONFIG_ACCOUNT}; 2 | use anchor_lang::prelude::*; 3 | 4 | #[derive(Accounts)] 5 | pub struct UpdateConfig<'info> { 6 | #[account( 7 | mut, 8 | seeds = [SEED_CONFIG_ACCOUNT], 9 | bump = config_account.bump, 10 | )] 11 | pub config_account: Account<'info, Config>, 12 | } 13 | 14 | // Change health factor to test liquidate instruction, no authority check, anyone can invoke 15 | pub fn process_update_config(ctx: Context, min_health_factor: u64) -> Result<()> { 16 | let config_account = &mut ctx.accounts.config_account; 17 | config_account.min_health_factor = min_health_factor; 18 | 19 | msg!("Update Config Acccount:{:#?}", ctx.accounts.config_account); 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/instructions/deposit/mod.rs: -------------------------------------------------------------------------------- 1 | pub use deposit_collateral_and_mint_tokens::*; 2 | pub mod deposit_collateral_and_mint_tokens; 3 | pub use utils::*; 4 | pub mod utils; 5 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | pub use admin::*; 2 | pub mod admin; 3 | pub use deposit::*; 4 | pub mod deposit; 5 | pub use withdraw::*; 6 | pub mod withdraw; 7 | pub use utils::*; 8 | pub mod utils; 9 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/programs/stablecoin/src/instructions/withdraw/mod.rs: -------------------------------------------------------------------------------- 1 | pub use redeem_collateral_and_burn_tokens::*; 2 | pub mod redeem_collateral_and_burn_tokens; 3 | pub use liquidate::*; 4 | pub mod liquidate; 5 | pub use utils::*; 6 | pub mod utils; 7 | -------------------------------------------------------------------------------- /project-11-programmable-money/program/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 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/README.md: -------------------------------------------------------------------------------- 1 | # Project 12: Attack the Bank 2 | 3 | In this project we will learn how to think like an attacker and find vulnerabilities in 3 different smart contracts. 4 | 5 | You can follow along [with the video to learn more](https://www.youtube.com/watch?v=HOdYZSe1uhE&t=20615s). We recommend creating a separate github repository for each project and commiting your code as you follow along. 6 | 7 | ## Resources 8 | 9 | - [Solana Documentation](https://solana.com/docs) 10 | - [More Security Education](https://solana.com/developers/courses/program-security) -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | bank_one = "HAAzYF1LMBi8R2avDaa4s2VZyMyGzA1RGQNFPXPjctZo" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "ISC", 3 | "scripts": { 4 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 | }, 7 | "dependencies": { 8 | "@coral-xyz/anchor": "^0.30.1" 9 | }, 10 | "devDependencies": { 11 | "chai": "^4.3.4", 12 | "mocha": "^9.0.3", 13 | "ts-mocha": "^10.0.0", 14 | "@types/bn.js": "^5.1.0", 15 | "@types/chai": "^4.3.0", 16 | "@types/mocha": "^9.0.0", 17 | "typescript": "^4.3.5", 18 | "prettier": "^2.6.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/programs/bank_one/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bank_one" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "bank_one" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version = "0.30.1", features = ["init-if-needed"] } 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/programs/bank_one/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_one/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 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | bank_three = "H2vvatVxBg1LufZqsXBuc4BHgK5TKLmrGY7rSEK2dD2L" 9 | fake_bank = "FxCXeDFCSXMPaTB7PQBTKuPHiowPxGQoQaTTL4x2tKQo" 10 | 11 | [registry] 12 | url = "https://api.apr.dev" 13 | 14 | [provider] 15 | cluster = "Localnet" 16 | wallet = "~/.config/solana/id.json" 17 | 18 | [scripts] 19 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 20 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "ISC", 3 | "scripts": { 4 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 | }, 7 | "dependencies": { 8 | "@coral-xyz/anchor": "^0.30.1" 9 | }, 10 | "devDependencies": { 11 | "chai": "^4.3.4", 12 | "mocha": "^9.0.3", 13 | "ts-mocha": "^10.0.0", 14 | "@types/bn.js": "^5.1.0", 15 | "@types/chai": "^4.3.0", 16 | "@types/mocha": "^9.0.0", 17 | "typescript": "^4.3.5", 18 | "prettier": "^2.6.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/programs/bank_three/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bank_three" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "bank_three" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version = "0.30.1", features = ["init-if-needed"] } 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/programs/bank_three/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/programs/fake_bank/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fake_bank" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "fake_bank" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = "0.30.1" 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/programs/fake_bank/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/programs/fake_bank/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | declare_id!("FxCXeDFCSXMPaTB7PQBTKuPHiowPxGQoQaTTL4x2tKQo"); 4 | 5 | #[program] 6 | pub mod fake_bank { 7 | use super::*; 8 | 9 | pub fn initialize(ctx: Context, vault_address: Pubkey) -> Result<()> { 10 | *ctx.accounts.bank = Bank { 11 | authority: ctx.accounts.fake_authority.key(), 12 | vault: vault_address, 13 | is_initialized: true, 14 | }; 15 | msg!("{:#?}", ctx.accounts.bank); 16 | Ok(()) 17 | } 18 | } 19 | 20 | #[derive(Accounts)] 21 | pub struct Initialize<'info> { 22 | #[account(mut)] 23 | pub fake_authority: Signer<'info>, 24 | #[account( 25 | init, 26 | payer = fake_authority, 27 | space = 8 + Bank::INIT_SPACE, 28 | seeds = [b"bank"], 29 | bump, 30 | )] 31 | pub bank: Account<'info, Bank>, 32 | pub system_program: Program<'info, System>, 33 | } 34 | 35 | #[account] 36 | #[derive(InitSpace, Debug)] 37 | pub struct Bank { 38 | pub authority: Pubkey, 39 | pub vault: Pubkey, 40 | pub is_initialized: bool, 41 | } 42 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_three/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 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | bank_two = "B8o5MhGbbxCxM5ugMZ8WKUpxrDKSUAHktdSQRSCa1S6i" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "ISC", 3 | "scripts": { 4 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 | }, 7 | "dependencies": { 8 | "@coral-xyz/anchor": "^0.30.1" 9 | }, 10 | "devDependencies": { 11 | "chai": "^4.3.4", 12 | "mocha": "^9.0.3", 13 | "ts-mocha": "^10.0.0", 14 | "@types/bn.js": "^5.1.0", 15 | "@types/chai": "^4.3.0", 16 | "@types/mocha": "^9.0.0", 17 | "typescript": "^4.3.5", 18 | "prettier": "^2.6.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/programs/bank_two/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bank_two" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "bank_two" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version = "0.30.1", features = ["init-if-needed"] } 21 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/programs/bank_two/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-12-attack-the-bank/bank_two/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 | -------------------------------------------------------------------------------- /project-13-getting-to-production/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jacobcreech 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 | -------------------------------------------------------------------------------- /project-13-getting-to-production/README.md: -------------------------------------------------------------------------------- 1 | # Getting to Production 2 | 3 | In this project we will deep dive on a number of different tools in preparation for deploying to production. 4 | 5 | You can follow along [in the video to learn more](https://www.youtube.com/watch?v=HOdYZSe1uhE&t=24025s). 6 | 7 | ## Resources 8 | 9 | - [Deploying a Program](https://solana.com/docs/programs/deploying) 10 | - [Squads multisig](https://app.squads.so/create-squad) 11 | - [Verifiable Builds](https://github.com/otter-sec/solana-verifiable-build) -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/dependency-checks": [ 22 | "error", 23 | { 24 | "ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"] 25 | } 26 | ] 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsc": { 3 | "target": "es2017", 4 | "parser": { 5 | "syntax": "typescript", 6 | "decorators": true, 7 | "dynamicImport": true 8 | }, 9 | "transform": { 10 | "decoratorMetadata": true, 11 | "legacyDecorator": true 12 | }, 13 | "keepClassNames": true, 14 | "externalHelpers": true, 15 | "loose": true 16 | }, 17 | "module": { 18 | "type": "es6" 19 | }, 20 | "sourceMaps": true, 21 | "exclude": [ 22 | "jest.config.ts", 23 | ".*\\.spec.tsx?$", 24 | ".*\\.test.tsx?$", 25 | "./src/jest-setup.ts$", 26 | "./**/jest-setup.ts$", 27 | ".*.js$" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | voting = "HDxHrQL4N5GaBo19UjEF3sypkrGiDijjuGyQXBNhnrKB" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "../node_modules/.bin/nx run anchor:jest" 19 | 20 | [test] 21 | startup_wait = 5000 22 | shutdown_wait = 2000 23 | upgradeable = false 24 | 25 | [test.validator] 26 | bind_address = "127.0.0.1" 27 | ledger = ".anchor/test-ledger" 28 | rpc_port = 8899 29 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["programs/*"] 3 | resolver = "2" 4 | [profile.release] 5 | overflow-checks = true 6 | lto = "fat" 7 | codegen-units = 1 8 | 9 | [profile.release.build-override] 10 | opt-level = 3 11 | incremental = false 12 | codegen-units = 1 13 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/README.md: -------------------------------------------------------------------------------- 1 | # anchor 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build anchor` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test anchor` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { readFileSync } from 'fs'; 3 | 4 | // Reading the SWC compilation config and remove the "exclude" 5 | // for the test files to be compiled by SWC 6 | const { exclude: _, ...swcJestConfig } = JSON.parse( 7 | readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8 | ); 9 | 10 | // disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11 | // If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12 | if (swcJestConfig.swcrc === undefined) { 13 | swcJestConfig.swcrc = false; 14 | } 15 | 16 | // Uncomment if using global setup/teardown files being transformed via swc 17 | // https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries 18 | // jest needs EsModule Interop to find the default exported setup/teardown functions 19 | // swcJestConfig.module.noInterop = false; 20 | 21 | export default { 22 | displayName: 'anchor', 23 | preset: '../jest.preset.js', 24 | transform: { 25 | '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 26 | }, 27 | moduleFileExtensions: ['ts', 'js', 'html'], 28 | testEnvironment: '', 29 | coverageDirectory: '../coverage/anchor', 30 | }; 31 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/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 | import * as anchor from '@coral-xyz/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 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@voting-dapp/anchor", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@coral-xyz/anchor": "^0.30.0", 6 | "@solana/web3.js": "1.91.9", 7 | "anchor-bankrun": "^0.4.0" 8 | }, 9 | "main": "./index.cjs", 10 | "module": "./index.js", 11 | "private": true 12 | } 13 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/programs/voting/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "voting" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "voting" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = "0.30.1" 21 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/programs/voting/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/src/index.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by preset-anchor. Programs are exported from this file. 2 | 3 | export * from './voting-exports'; 4 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/src/voting-exports.ts: -------------------------------------------------------------------------------- 1 | // Here we export some useful types and functions for interacting with the Anchor program. 2 | import { AnchorProvider, Program } from '@coral-xyz/anchor'; 3 | import { Cluster, PublicKey } from '@solana/web3.js'; 4 | import VotingIDL from '../target/idl/voting.json'; 5 | import type { Voting } from '../target/types/voting'; 6 | 7 | // Re-export the generated IDL and type 8 | export { Voting, VotingIDL }; 9 | 10 | // The programId is imported from the program IDL. 11 | export const VOTING_PROGRAM_ID = new PublicKey(VotingIDL.address); 12 | 13 | // This is a helper function to get the Voting Anchor program. 14 | export function getVotingProgram(provider: AnchorProvider) { 15 | return new Program(VotingIDL as Voting, provider); 16 | } 17 | 18 | // This is a helper function to get the program ID for the Voting program depending on the cluster. 19 | export function getVotingProgramId(cluster: Cluster) { 20 | switch (cluster) { 21 | case 'devnet': 22 | case 'testnet': 23 | case 'mainnet-beta': 24 | default: 25 | return VOTING_PROGRAM_ID; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/tests/fixtures/voting.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-13-getting-to-production/anchor/tests/fixtures/voting.so -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"], 7 | "resolveJsonModule": true, 8 | "allowSyntheticDefaultImports": true 9 | }, 10 | "include": ["src/**/*.ts"], 11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /project-13-getting-to-production/anchor/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /project-13-getting-to-production/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /project-13-getting-to-production/jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /project-13-getting-to-production/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2020", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./web/*"], 19 | "@voting-dapp/anchor": ["anchor/src/index.ts"] 20 | } 21 | }, 22 | "exclude": ["node_modules", "tmp"] 23 | } 24 | -------------------------------------------------------------------------------- /project-13-getting-to-production/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "npm run build", 3 | "outputDirectory": "dist/web/.next" 4 | } 5 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:@nx/react-typescript", 4 | "next", 5 | "next/core-web-vitals", 6 | "../.eslintrc.json" 7 | ], 8 | "ignorePatterns": ["!**/*", ".next/**/*"], 9 | "overrides": [ 10 | { 11 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 12 | "rules": { 13 | "@next/next/no-html-link-for-pages": ["error", "web/pages"] 14 | } 15 | }, 16 | { 17 | "files": ["*.ts", "*.tsx"], 18 | "rules": {} 19 | }, 20 | { 21 | "files": ["*.js", "*.jsx"], 22 | "rules": {} 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 26 | "rules": { 27 | "@nx/enforce-module-boundaries": [ 28 | "error", 29 | { 30 | "allow": ["@/"] 31 | } 32 | ] 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET(request: Request) { 2 | return new Response('Hello, from API!'); 3 | } 4 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/app/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | height: 100%; 8 | } 9 | 10 | .wallet-adapter-button-trigger { 11 | background: rgb(100, 26, 230) !important; 12 | border-radius: 8px !important; 13 | padding-left: 16px !important; 14 | padding-right: 16px !important; 15 | } 16 | .wallet-adapter-dropdown-list, 17 | .wallet-adapter-button { 18 | font-family: inherit !important; 19 | } 20 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css'; 2 | import { UiLayout } from '@/components/ui/ui-layout'; 3 | import { ClusterProvider } from '@/components/cluster/cluster-data-access'; 4 | import { SolanaProvider } from '@/components/solana/solana-provider'; 5 | import { ReactQueryProvider } from './react-query-provider'; 6 | 7 | export const metadata = { 8 | title: 'voting-dapp', 9 | description: 'Generated by create-solana-dapp', 10 | }; 11 | 12 | const links: { label: string; path: string }[] = [ 13 | ]; 14 | 15 | export default function RootLayout({ 16 | children, 17 | }: { 18 | children: React.ReactNode; 19 | }) { 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | {children} 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | } 3 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/app/page.tsx: -------------------------------------------------------------------------------- 1 | import VotingFeature from '@/components/voting/voting-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/app/react-query-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React, { ReactNode, useState } from 'react'; 4 | import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'; 5 | import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; 6 | 7 | export function ReactQueryProvider({ children }: { children: ReactNode }) { 8 | const [client] = useState(new QueryClient()); 9 | 10 | return ( 11 | 12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/components/account/account-list-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | 6 | import { redirect } from 'next/navigation'; 7 | 8 | export default function AccountListFeature() { 9 | const { publicKey } = useWallet(); 10 | 11 | if (publicKey) { 12 | return redirect(`/account/${publicKey.toString()}`); 13 | } 14 | 15 | return ( 16 |
17 |
18 | 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/components/cluster/cluster-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useState } from 'react'; 4 | import { AppHero } from '../ui/ui-layout'; 5 | import { ClusterUiModal } from './cluster-ui'; 6 | import { ClusterUiTable } from './cluster-ui'; 7 | 8 | export default function ClusterFeature() { 9 | const [showModal, setShowModal] = useState(false); 10 | 11 | return ( 12 |
13 | 17 | setShowModal(false)} 20 | /> 21 | 27 | 28 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/components/voting/voting-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | import { AppHero, ellipsify } from '../ui/ui-layout'; 6 | import { ExplorerLink } from '../cluster/cluster-ui'; 7 | import { useVotingProgram } from './voting-data-access'; 8 | import { CandidateList, VotingCreate } from './voting-ui'; 9 | 10 | export default function VotingFeature() { 11 | const { publicKey } = useWallet(); 12 | const { programId } = useVotingProgram(); 13 | 14 | return publicKey ? ( 15 |
16 | 22 | 23 | 24 | 25 |
26 | ) : ( 27 |
28 |
29 |
30 | 31 |
32 |
33 |
34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | declare module '*.svg' { 3 | const content: any; 4 | export const ReactComponent: any; 5 | export default content; 6 | } 7 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/next.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-var-requires 4 | const { composePlugins, withNx } = require('@nx/next'); 5 | 6 | /** 7 | * @type {import('@nx/next/plugins/with-nx').WithNxOptions} 8 | **/ 9 | const nextConfig = { 10 | webpack: (config) => { 11 | config.externals = [ 12 | ...(config.externals || []), 13 | 'bigint', 14 | 'node-gyp-build', 15 | ]; 16 | return config; 17 | }, 18 | nx: { 19 | // Set this to true if you would like to use SVGR 20 | // See: https://github.com/gregberge/svgr 21 | svgr: false, 22 | }, 23 | }; 24 | 25 | const plugins = [ 26 | // Add more Next.js plugins to this list if needed. 27 | withNx, 28 | ]; 29 | 30 | module.exports = composePlugins(...plugins)(nextConfig); 31 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | // Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build 4 | // option from your application's configuration (i.e. project.json). 5 | // 6 | // See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries 7 | 8 | module.exports = { 9 | plugins: { 10 | tailwindcss: { 11 | config: join(__dirname, 'tailwind.config.js'), 12 | }, 13 | autoprefixer: {}, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-13-getting-to-production/web/public/.gitkeep -------------------------------------------------------------------------------- /project-13-getting-to-production/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-13-getting-to-production/web/public/favicon.ico -------------------------------------------------------------------------------- /project-13-getting-to-production/web/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-13-getting-to-production/web/public/logo.png -------------------------------------------------------------------------------- /project-13-getting-to-production/web/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); 2 | const { join } = require('path'); 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [ 7 | join( 8 | __dirname, 9 | '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' 10 | ), 11 | ...createGlobPatternsForDependencies(__dirname), 12 | ], 13 | theme: { 14 | extend: {}, 15 | }, 16 | plugins: [require('daisyui')], 17 | }; 18 | -------------------------------------------------------------------------------- /project-13-getting-to-production/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "preserve", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "incremental": true, 14 | "plugins": [ 15 | { 16 | "name": "next" 17 | } 18 | ] 19 | }, 20 | "include": [ 21 | "**/*.ts", 22 | "**/*.tsx", 23 | "**/*.js", 24 | "**/*.jsx", 25 | "../web/.next/types/**/*.ts", 26 | "../dist/web/.next/types/**/*.ts", 27 | "next-env.d.ts", 28 | ".next/types/**/*.ts" 29 | ], 30 | "exclude": ["node_modules", "jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 31 | } 32 | -------------------------------------------------------------------------------- /project-2-voting/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jacobcreech 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 | -------------------------------------------------------------------------------- /project-2-voting/README.md: -------------------------------------------------------------------------------- 1 | # Project 2: Voting Application 2 | 3 | The Voting Application is a program that allows people to vote between multiple options and have the results automatically tallied. Votes will count up on each vote cast and the results will be saved to an account on the Solana network. 4 | 5 | ## Resources 6 | 7 | - [Anchor Documentation](https://www.anchor-lang.com/) 8 | - [Solana Documentation](https://solana.com/docs) 9 | 10 | ## Running This Project 11 | 12 | We highly recommend [creating your own github repository](https://github.com/new) and building along with the video. This will help you learn the most and give you a reference to look back on later. 13 | 14 | If you want to check the final result of the project, you can clone this repository and run the following commands: 15 | 16 | ``` 17 | npm i 18 | cd anchor 19 | anchor build 20 | ``` 21 | 22 | ## Challenges 23 | 24 | There are a few challenges you can take on to extend this project: 25 | 26 | 1. **Easy**: Allow multiple polls to be run at the same time in the UI. 27 | 2. **Hard**: Limit votes to one per signer. -------------------------------------------------------------------------------- /project-2-voting/anchor/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/dependency-checks": [ 22 | "error", 23 | { 24 | "ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"] 25 | } 26 | ] 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /project-2-voting/anchor/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsc": { 3 | "target": "es2017", 4 | "parser": { 5 | "syntax": "typescript", 6 | "decorators": true, 7 | "dynamicImport": true 8 | }, 9 | "transform": { 10 | "decoratorMetadata": true, 11 | "legacyDecorator": true 12 | }, 13 | "keepClassNames": true, 14 | "externalHelpers": true, 15 | "loose": true 16 | }, 17 | "module": { 18 | "type": "es6" 19 | }, 20 | "sourceMaps": true, 21 | "exclude": [ 22 | "jest.config.ts", 23 | ".*\\.spec.tsx?$", 24 | ".*\\.test.tsx?$", 25 | "./src/jest-setup.ts$", 26 | "./**/jest-setup.ts$", 27 | ".*.js$" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /project-2-voting/anchor/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | voting = "5s3PtT8kLYCv1WEp6dSh3T7EuF35Z6jSu5Cvx4hWG79H" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "../node_modules/.bin/nx run anchor:jest" 19 | 20 | [test] 21 | startup_wait = 5000 22 | shutdown_wait = 2000 23 | upgradeable = false 24 | 25 | [test.validator] 26 | bind_address = "127.0.0.1" 27 | ledger = ".anchor/test-ledger" 28 | rpc_port = 8899 29 | -------------------------------------------------------------------------------- /project-2-voting/anchor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-2-voting/anchor/README.md: -------------------------------------------------------------------------------- 1 | # anchor 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build anchor` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test anchor` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /project-2-voting/anchor/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { readFileSync } from 'fs'; 3 | 4 | // Reading the SWC compilation config and remove the "exclude" 5 | // for the test files to be compiled by SWC 6 | const { exclude: _, ...swcJestConfig } = JSON.parse( 7 | readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8 | ); 9 | 10 | // disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11 | // If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12 | if (swcJestConfig.swcrc === undefined) { 13 | swcJestConfig.swcrc = false; 14 | } 15 | 16 | // Uncomment if using global setup/teardown files being transformed via swc 17 | // https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries 18 | // jest needs EsModule Interop to find the default exported setup/teardown functions 19 | // swcJestConfig.module.noInterop = false; 20 | 21 | export default { 22 | displayName: 'anchor', 23 | preset: '../jest.preset.js', 24 | transform: { 25 | '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 26 | }, 27 | moduleFileExtensions: ['ts', 'js', 'html'], 28 | testEnvironment: '', 29 | coverageDirectory: '../coverage/anchor', 30 | }; 31 | -------------------------------------------------------------------------------- /project-2-voting/anchor/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 | import * as anchor from '@coral-xyz/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 | -------------------------------------------------------------------------------- /project-2-voting/anchor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@voting/anchor", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@coral-xyz/anchor": "^0.30.0", 6 | "@solana/web3.js": "1.91.9", 7 | "anchor-bankrun": "^0.4.0", 8 | "solana-bankrun": "^0.2.0" 9 | }, 10 | "main": "./index.cjs", 11 | "module": "./index.js", 12 | "private": true 13 | } 14 | -------------------------------------------------------------------------------- /project-2-voting/anchor/programs/voting/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "voting" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "voting" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version = "0.30.1", features = ["init-if-needed"] } 21 | -------------------------------------------------------------------------------- /project-2-voting/anchor/programs/voting/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-2-voting/anchor/src/index.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by preset-anchor. Programs are exported from this file. 2 | 3 | export * from './voting-exports'; 4 | -------------------------------------------------------------------------------- /project-2-voting/anchor/src/voting-exports.ts: -------------------------------------------------------------------------------- 1 | // Here we export some useful types and functions for interacting with the Anchor program. 2 | import { AnchorProvider, Program } from '@coral-xyz/anchor'; 3 | import { PublicKey } from '@solana/web3.js'; 4 | import type { Voting } from '../target/types/voting'; 5 | import { IDL as VotingIDL } from '../target/types/voting'; 6 | 7 | // Re-export the generated IDL and type 8 | export { Voting, VotingIDL }; 9 | 10 | // The programId is imported from the program IDL. 11 | export const BASIC_PROGRAM_ID = new PublicKey(VotingIDL.address); 12 | 13 | // This is a helper function to get the Basic Anchor program. 14 | export function getBasicProgram(provider: AnchorProvider) { 15 | return new Program(VotingIDL as Voting, provider); 16 | } 17 | -------------------------------------------------------------------------------- /project-2-voting/anchor/tests/fixtures/voting.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-2-voting/anchor/tests/fixtures/voting.so -------------------------------------------------------------------------------- /project-2-voting/anchor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /project-2-voting/anchor/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"], 7 | "resolveJsonModule": true, 8 | "allowSyntheticDefaultImports": true 9 | }, 10 | "include": ["src/**/*.ts"], 11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /project-2-voting/anchor/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /project-2-voting/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /project-2-voting/jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /project-2-voting/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2020", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./web/*"], 19 | "@voting/anchor": ["anchor/src/index.ts"] 20 | } 21 | }, 22 | "exclude": ["node_modules", "tmp"] 23 | } 24 | -------------------------------------------------------------------------------- /project-2-voting/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "npm run build", 3 | "outputDirectory": "dist/web/.next" 4 | } 5 | -------------------------------------------------------------------------------- /project-2-voting/web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:@nx/react-typescript", 4 | "next", 5 | "next/core-web-vitals", 6 | "../.eslintrc.json" 7 | ], 8 | "ignorePatterns": ["!**/*", ".next/**/*"], 9 | "overrides": [ 10 | { 11 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 12 | "rules": { 13 | "@next/next/no-html-link-for-pages": ["error", "web/pages"] 14 | } 15 | }, 16 | { 17 | "files": ["*.ts", "*.tsx"], 18 | "rules": {} 19 | }, 20 | { 21 | "files": ["*.js", "*.jsx"], 22 | "rules": {} 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 26 | "rules": { 27 | "@nx/enforce-module-boundaries": [ 28 | "error", 29 | { 30 | "allow": ["@/"] 31 | } 32 | ] 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /project-2-voting/web/app/account/[address]/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountDetailFeature from '@/components/account/account-detail-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-2-voting/web/app/account/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountListFeature from '@/components/account/account-list-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-2-voting/web/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | export async function GET(request: Request) { 4 | return new Response('Hello, from API!'); 5 | } 6 | -------------------------------------------------------------------------------- /project-2-voting/web/app/basic/page.tsx: -------------------------------------------------------------------------------- 1 | import BasicFeature from '@/components/basic/basic-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-2-voting/web/app/clusters/page.tsx: -------------------------------------------------------------------------------- 1 | import ClusterFeature from '@/components/cluster/cluster-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-2-voting/web/app/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | height: 100%; 8 | } 9 | 10 | .wallet-adapter-button-trigger { 11 | background: rgb(100, 26, 230) !important; 12 | border-radius: 8px !important; 13 | padding-left: 16px !important; 14 | padding-right: 16px !important; 15 | } 16 | .wallet-adapter-dropdown-list, 17 | .wallet-adapter-button { 18 | font-family: inherit !important; 19 | } 20 | -------------------------------------------------------------------------------- /project-2-voting/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css'; 2 | import { UiLayout } from '@/components/ui/ui-layout'; 3 | import { ClusterProvider } from '@/components/cluster/cluster-data-access'; 4 | import { SolanaProvider } from '@/components/solana/solana-provider'; 5 | import { ReactQueryProvider } from './react-query-provider'; 6 | 7 | export const metadata = { 8 | title: 'voting', 9 | description: 'Generated by create-solana-dapp', 10 | }; 11 | 12 | const links: { label: string; path: string }[] = [ 13 | { label: 'Account', path: '/account' }, 14 | { label: 'Clusters', path: '/clusters' }, 15 | { label: 'Basic Program', path: '/basic' }, 16 | ]; 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: { 21 | children: React.ReactNode; 22 | }) { 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | {children} 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /project-2-voting/web/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | } 3 | -------------------------------------------------------------------------------- /project-2-voting/web/app/page.tsx: -------------------------------------------------------------------------------- 1 | import DashboardFeature from '@/components/dashboard/dashboard-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-2-voting/web/app/react-query-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React, { ReactNode, useState } from 'react'; 4 | import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'; 5 | import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; 6 | 7 | export function ReactQueryProvider({ children }: { children: ReactNode }) { 8 | const [client] = useState(new QueryClient()); 9 | 10 | return ( 11 | 12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /project-2-voting/web/components/account/account-list-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | 6 | import { redirect } from 'next/navigation'; 7 | 8 | export default function AccountListFeature() { 9 | const { publicKey } = useWallet(); 10 | 11 | if (publicKey) { 12 | return redirect(`/account/${publicKey.toString()}`); 13 | } 14 | 15 | return ( 16 |
17 |
18 | 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /project-2-voting/web/components/basic/basic-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { ExplorerLink } from '../cluster/cluster-ui'; 5 | import { WalletButton } from '../solana/solana-provider'; 6 | import { AppHero, ellipsify } from '../ui/ui-layout'; 7 | import { useBasicProgram } from './basic-data-access'; 8 | import { BasicCreate, BasicProgram } from './basic-ui'; 9 | 10 | export default function BasicFeature() { 11 | const { publicKey } = useWallet(); 12 | const { programId } = useBasicProgram(); 13 | 14 | return publicKey ? ( 15 |
16 | 20 |

21 | 25 |

26 | 27 |
28 | 29 |
30 | ) : ( 31 |
32 |
33 |
34 | 35 |
36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /project-2-voting/web/components/basic/basic-ui.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { Keypair } from '@solana/web3.js'; 4 | import { useBasicProgram } from './basic-data-access'; 5 | 6 | export function BasicCreate() { 7 | const { greet } = useBasicProgram(); 8 | 9 | return ( 10 | 17 | ); 18 | } 19 | 20 | export function BasicProgram() { 21 | const { getProgramAccount } = useBasicProgram(); 22 | 23 | if (getProgramAccount.isLoading) { 24 | return ; 25 | } 26 | if (!getProgramAccount.data?.value) { 27 | return ( 28 |
29 | 30 | Program account not found. Make sure you have deployed the program and 31 | are on the correct cluster. 32 | 33 |
34 | ); 35 | } 36 | return ( 37 |
38 |
{JSON.stringify(getProgramAccount.data.value, null, 2)}
39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /project-2-voting/web/components/cluster/cluster-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useState } from 'react'; 4 | import { AppHero } from '../ui/ui-layout'; 5 | import { ClusterUiModal } from './cluster-ui'; 6 | import { ClusterUiTable } from './cluster-ui'; 7 | 8 | export default function ClusterFeature() { 9 | const [showModal, setShowModal] = useState(false); 10 | 11 | return ( 12 |
13 | 17 | setShowModal(false)} 20 | /> 21 | 27 | 28 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /project-2-voting/web/components/dashboard/dashboard-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { AppHero } from '../ui/ui-layout'; 4 | 5 | const links: { label: string; href: string }[] = [ 6 | { label: 'Solana Docs', href: 'https://docs.solana.com/' }, 7 | { label: 'Solana Faucet', href: 'https://faucet.solana.com/' }, 8 | { label: 'Solana Cookbook', href: 'https://solanacookbook.com/' }, 9 | { label: 'Solana Stack Overflow', href: 'https://solana.stackexchange.com/' }, 10 | { 11 | label: 'Solana Developers GitHub', 12 | href: 'https://github.com/solana-developers/', 13 | }, 14 | ]; 15 | 16 | export default function DashboardFeature() { 17 | return ( 18 |
19 | 20 |
21 |
22 |

Here are some helpful links to get you started.

23 | {links.map((link, index) => ( 24 | 34 | ))} 35 |
36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /project-2-voting/web/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | declare module '*.svg' { 3 | const content: any; 4 | export const ReactComponent: any; 5 | export default content; 6 | } 7 | -------------------------------------------------------------------------------- /project-2-voting/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /project-2-voting/web/next.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-var-requires 4 | const { composePlugins, withNx } = require('@nx/next'); 5 | 6 | /** 7 | * @type {import('@nx/next/plugins/with-nx').WithNxOptions} 8 | **/ 9 | const nextConfig = { 10 | webpack: (config) => { 11 | config.externals = [ 12 | ...(config.externals || []), 13 | 'bigint', 14 | 'node-gyp-build', 15 | ]; 16 | return config; 17 | }, 18 | nx: { 19 | // Set this to true if you would like to use SVGR 20 | // See: https://github.com/gregberge/svgr 21 | svgr: false, 22 | }, 23 | }; 24 | 25 | const plugins = [ 26 | // Add more Next.js plugins to this list if needed. 27 | withNx, 28 | ]; 29 | 30 | module.exports = composePlugins(...plugins)(nextConfig); 31 | -------------------------------------------------------------------------------- /project-2-voting/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | // Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build 4 | // option from your application's configuration (i.e. project.json). 5 | // 6 | // See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries 7 | 8 | module.exports = { 9 | plugins: { 10 | tailwindcss: { 11 | config: join(__dirname, 'tailwind.config.js'), 12 | }, 13 | autoprefixer: {}, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /project-2-voting/web/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-2-voting/web/public/.gitkeep -------------------------------------------------------------------------------- /project-2-voting/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-2-voting/web/public/favicon.ico -------------------------------------------------------------------------------- /project-2-voting/web/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-2-voting/web/public/logo.png -------------------------------------------------------------------------------- /project-2-voting/web/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); 2 | const { join } = require('path'); 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [ 7 | join( 8 | __dirname, 9 | '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' 10 | ), 11 | ...createGlobPatternsForDependencies(__dirname), 12 | ], 13 | theme: { 14 | extend: {}, 15 | }, 16 | plugins: [require('daisyui')], 17 | }; 18 | -------------------------------------------------------------------------------- /project-2-voting/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "preserve", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "incremental": true, 14 | "plugins": [ 15 | { 16 | "name": "next" 17 | } 18 | ] 19 | }, 20 | "include": [ 21 | "**/*.ts", 22 | "**/*.tsx", 23 | "**/*.js", 24 | "**/*.jsx", 25 | "../web/.next/types/**/*.ts", 26 | "../dist/web/.next/types/**/*.ts", 27 | "next-env.d.ts", 28 | ".next/types/**/*.ts" 29 | ], 30 | "exclude": ["node_modules", "jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 31 | } 32 | -------------------------------------------------------------------------------- /project-3-blinks/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jacobcreech 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 | -------------------------------------------------------------------------------- /project-3-blinks/README.md: -------------------------------------------------------------------------------- 1 | # Project 3: Integrating Blinks 2 | 3 | [Blinks and Actions]() bring the blockchain to any website that can handle a hyperlink. Throughout this project, we will learn how to integrate Blinks into a website and use them to interact with a Solana smart contract. 4 | 5 | ## Resources 6 | 7 | - [Blinks Documentation](https://solana.com/docs/advanced/actions) 8 | - [Blinks Tester](https://dial.to) 9 | 10 | ## Running This Project 11 | 12 | We highly recommend creating your own github repository and building along with the video. This will help you learn the most and give you a reference to look back on later. 13 | 14 | If you want to check the final result of the project, you can clone this repository and run the following commands: 15 | 16 | ``` 17 | npm i 18 | cd anchor 19 | anchor build 20 | anchor test 21 | cd .. 22 | npm run dev 23 | ``` 24 | 25 | You should be able to view the project at [http://localhost:3000](http://localhost:3000) and interact with the blinks at [dial.to](https://dial.to/?action=solana-action:http://localhost:3000/api/vote) -------------------------------------------------------------------------------- /project-3-blinks/anchor/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/dependency-checks": [ 22 | "error", 23 | { 24 | "ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"] 25 | } 26 | ] 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsc": { 3 | "target": "es2017", 4 | "parser": { 5 | "syntax": "typescript", 6 | "decorators": true, 7 | "dynamicImport": true 8 | }, 9 | "transform": { 10 | "decoratorMetadata": true, 11 | "legacyDecorator": true 12 | }, 13 | "keepClassNames": true, 14 | "externalHelpers": true, 15 | "loose": true 16 | }, 17 | "module": { 18 | "type": "es6" 19 | }, 20 | "sourceMaps": true, 21 | "exclude": [ 22 | "jest.config.ts", 23 | ".*\\.spec.tsx?$", 24 | ".*\\.test.tsx?$", 25 | "./src/jest-setup.ts$", 26 | "./**/jest-setup.ts$", 27 | ".*.js$" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | voting = "6RMzzoy8iRv9a6ATQbxva3p5GCLFtBukjVN195aBNmQ8" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "../node_modules/.bin/nx run anchor:jest" 19 | 20 | [test] 21 | startup_wait = 5000 22 | shutdown_wait = 2000 23 | upgradeable = false 24 | 25 | [test.validator] 26 | bind_address = "127.0.0.1" 27 | ledger = ".anchor/test-ledger" 28 | rpc_port = 8899 29 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["programs/*"] 3 | resolver = "2" 4 | [profile.release] 5 | overflow-checks = true 6 | lto = "fat" 7 | codegen-units = 1 8 | 9 | [profile.release.build-override] 10 | opt-level = 3 11 | incremental = false 12 | codegen-units = 1 13 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/README.md: -------------------------------------------------------------------------------- 1 | # anchor 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build anchor` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test anchor` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { readFileSync } from 'fs'; 3 | 4 | // Reading the SWC compilation config and remove the "exclude" 5 | // for the test files to be compiled by SWC 6 | const { exclude: _, ...swcJestConfig } = JSON.parse( 7 | readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8 | ); 9 | 10 | // disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11 | // If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12 | if (swcJestConfig.swcrc === undefined) { 13 | swcJestConfig.swcrc = false; 14 | } 15 | 16 | // Uncomment if using global setup/teardown files being transformed via swc 17 | // https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries 18 | // jest needs EsModule Interop to find the default exported setup/teardown functions 19 | // swcJestConfig.module.noInterop = false; 20 | 21 | export default { 22 | displayName: 'anchor', 23 | preset: '../jest.preset.js', 24 | transform: { 25 | '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 26 | }, 27 | moduleFileExtensions: ['ts', 'js', 'html'], 28 | testEnvironment: '', 29 | coverageDirectory: '../coverage/anchor', 30 | }; 31 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/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 | import * as anchor from '@coral-xyz/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 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@voting-dapp/anchor", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@coral-xyz/anchor": "^0.30.0", 6 | "@solana/web3.js": "1.91.9", 7 | "anchor-bankrun": "^0.4.0", 8 | "solana-bankrun": "^0.2.0" 9 | }, 10 | "main": "./index.cjs", 11 | "module": "./index.js", 12 | "private": true 13 | } 14 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/programs/voting/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "voting" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "voting" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = "0.30.1" 21 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/programs/voting/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/src/counter-exports.ts: -------------------------------------------------------------------------------- 1 | // Here we export some useful types and functions for interacting with the Anchor program. 2 | import { AnchorProvider, Program } from '@coral-xyz/anchor'; 3 | import { Cluster, PublicKey } from '@solana/web3.js'; 4 | import CounterIDL from '../target/idl/counter.json'; 5 | import type { Counter } from '../target/types/counter'; 6 | 7 | // Re-export the generated IDL and type 8 | export { Counter, CounterIDL }; 9 | 10 | // The programId is imported from the program IDL. 11 | export const COUNTER_PROGRAM_ID = new PublicKey(CounterIDL.address); 12 | 13 | // This is a helper function to get the Counter Anchor program. 14 | export function getCounterProgram(provider: AnchorProvider) { 15 | return new Program(CounterIDL as Counter, provider); 16 | } 17 | 18 | // This is a helper function to get the program ID for the Counter program depending on the cluster. 19 | export function getCounterProgramId(cluster: Cluster) { 20 | switch (cluster) { 21 | case 'devnet': 22 | case 'testnet': 23 | // This is the program ID for the Counter program on devnet and testnet. 24 | return new PublicKey('CounNZdmsQmWh7uVngV9FXW2dZ6zAgbJyYsvBpqbykg'); 25 | case 'mainnet-beta': 26 | default: 27 | return COUNTER_PROGRAM_ID; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/src/index.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by preset-anchor. Programs are exported from this file. 2 | 3 | export * from './counter-exports'; 4 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/tests/fixtures/voting.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-3-blinks/anchor/tests/fixtures/voting.so -------------------------------------------------------------------------------- /project-3-blinks/anchor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"], 7 | "resolveJsonModule": true, 8 | "allowSyntheticDefaultImports": true 9 | }, 10 | "include": ["src/**/*.ts"], 11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /project-3-blinks/anchor/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /project-3-blinks/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /project-3-blinks/jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /project-3-blinks/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2020", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./web/*"], 19 | "@voting-dapp/anchor": ["anchor/src/index.ts"] 20 | } 21 | }, 22 | "exclude": ["node_modules", "tmp"] 23 | } 24 | -------------------------------------------------------------------------------- /project-3-blinks/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "npm run build", 3 | "outputDirectory": "dist/web/.next" 4 | } 5 | -------------------------------------------------------------------------------- /project-3-blinks/web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:@nx/react-typescript", 4 | "next", 5 | "next/core-web-vitals", 6 | "../.eslintrc.json" 7 | ], 8 | "ignorePatterns": ["!**/*", ".next/**/*"], 9 | "overrides": [ 10 | { 11 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 12 | "rules": { 13 | "@next/next/no-html-link-for-pages": ["error", "web/pages"] 14 | } 15 | }, 16 | { 17 | "files": ["*.ts", "*.tsx"], 18 | "rules": {} 19 | }, 20 | { 21 | "files": ["*.js", "*.jsx"], 22 | "rules": {} 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 26 | "rules": { 27 | "@nx/enforce-module-boundaries": [ 28 | "error", 29 | { 30 | "allow": ["@/"] 31 | } 32 | ] 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/account/[address]/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountDetailFeature from '@/components/account/account-detail-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/account/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountListFeature from '@/components/account/account-list-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET(request: Request) { 2 | return new Response('Hello, from API!'); 3 | } 4 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/clusters/page.tsx: -------------------------------------------------------------------------------- 1 | import ClusterFeature from '@/components/cluster/cluster-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/counter/page.tsx: -------------------------------------------------------------------------------- 1 | import CounterFeature from '@/components/counter/counter-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | height: 100%; 8 | } 9 | 10 | .wallet-adapter-button-trigger { 11 | background: rgb(100, 26, 230) !important; 12 | border-radius: 8px !important; 13 | padding-left: 16px !important; 14 | padding-right: 16px !important; 15 | } 16 | .wallet-adapter-dropdown-list, 17 | .wallet-adapter-button { 18 | font-family: inherit !important; 19 | } 20 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css'; 2 | import { UiLayout } from '@/components/ui/ui-layout'; 3 | import { ClusterProvider } from '@/components/cluster/cluster-data-access'; 4 | import { SolanaProvider } from '@/components/solana/solana-provider'; 5 | import { ReactQueryProvider } from './react-query-provider'; 6 | 7 | export const metadata = { 8 | title: 'voting-dapp', 9 | description: 'Generated by create-solana-dapp', 10 | }; 11 | 12 | const links: { label: string; path: string }[] = [ 13 | { label: 'Account', path: '/account' }, 14 | { label: 'Clusters', path: '/clusters' }, 15 | { label: 'Counter Program', path: '/counter' }, 16 | ]; 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: { 21 | children: React.ReactNode; 22 | }) { 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | {children} 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | } 3 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/page.tsx: -------------------------------------------------------------------------------- 1 | import DashboardFeature from '@/components/dashboard/dashboard-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-3-blinks/web/app/react-query-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React, { ReactNode, useState } from 'react'; 4 | import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'; 5 | import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; 6 | 7 | export function ReactQueryProvider({ children }: { children: ReactNode }) { 8 | const [client] = useState(new QueryClient()); 9 | 10 | return ( 11 | 12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /project-3-blinks/web/components/account/account-list-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | 6 | import { redirect } from 'next/navigation'; 7 | 8 | export default function AccountListFeature() { 9 | const { publicKey } = useWallet(); 10 | 11 | if (publicKey) { 12 | return redirect(`/account/${publicKey.toString()}`); 13 | } 14 | 15 | return ( 16 |
17 |
18 | 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /project-3-blinks/web/components/cluster/cluster-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useState } from 'react'; 4 | import { AppHero } from '../ui/ui-layout'; 5 | import { ClusterUiModal } from './cluster-ui'; 6 | import { ClusterUiTable } from './cluster-ui'; 7 | 8 | export default function ClusterFeature() { 9 | const [showModal, setShowModal] = useState(false); 10 | 11 | return ( 12 |
13 | 17 | setShowModal(false)} 20 | /> 21 | 27 | 28 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /project-3-blinks/web/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | declare module '*.svg' { 3 | const content: any; 4 | export const ReactComponent: any; 5 | export default content; 6 | } 7 | -------------------------------------------------------------------------------- /project-3-blinks/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /project-3-blinks/web/next.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-var-requires 4 | const { composePlugins, withNx } = require('@nx/next'); 5 | 6 | /** 7 | * @type {import('@nx/next/plugins/with-nx').WithNxOptions} 8 | **/ 9 | const nextConfig = { 10 | webpack: (config) => { 11 | config.externals = [ 12 | ...(config.externals || []), 13 | 'bigint', 14 | 'node-gyp-build', 15 | ]; 16 | return config; 17 | }, 18 | nx: { 19 | // Set this to true if you would like to use SVGR 20 | // See: https://github.com/gregberge/svgr 21 | svgr: false, 22 | }, 23 | }; 24 | 25 | const plugins = [ 26 | // Add more Next.js plugins to this list if needed. 27 | withNx, 28 | ]; 29 | 30 | module.exports = composePlugins(...plugins)(nextConfig); 31 | -------------------------------------------------------------------------------- /project-3-blinks/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | // Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build 4 | // option from your application's configuration (i.e. project.json). 5 | // 6 | // See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries 7 | 8 | module.exports = { 9 | plugins: { 10 | tailwindcss: { 11 | config: join(__dirname, 'tailwind.config.js'), 12 | }, 13 | autoprefixer: {}, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /project-3-blinks/web/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-3-blinks/web/public/.gitkeep -------------------------------------------------------------------------------- /project-3-blinks/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-3-blinks/web/public/favicon.ico -------------------------------------------------------------------------------- /project-3-blinks/web/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-3-blinks/web/public/logo.png -------------------------------------------------------------------------------- /project-3-blinks/web/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); 2 | const { join } = require('path'); 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [ 7 | join( 8 | __dirname, 9 | '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' 10 | ), 11 | ...createGlobPatternsForDependencies(__dirname), 12 | ], 13 | theme: { 14 | extend: {}, 15 | }, 16 | plugins: [require('daisyui')], 17 | }; 18 | -------------------------------------------------------------------------------- /project-3-blinks/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "preserve", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "incremental": true, 14 | "plugins": [ 15 | { 16 | "name": "next" 17 | } 18 | ] 19 | }, 20 | "include": [ 21 | "**/*.ts", 22 | "**/*.tsx", 23 | "**/*.js", 24 | "**/*.jsx", 25 | "../web/.next/types/**/*.ts", 26 | "../dist/web/.next/types/**/*.ts", 27 | "next-env.d.ts", 28 | ".next/types/**/*.ts" 29 | ], 30 | "exclude": ["node_modules", "jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 31 | } 32 | -------------------------------------------------------------------------------- /project-4-crud-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | dist 5 | tmp 6 | /out-tsc 7 | # dependencies 8 | node_modules 9 | # IDEs and editors 10 | /.idea 11 | .project 12 | .classpath 13 | .c9/ 14 | *.launch 15 | .settings/ 16 | *.sublime-workspace 17 | # IDE - VSCode 18 | .vscode/* 19 | !.vscode/settings.json 20 | !.vscode/tasks.json 21 | !.vscode/launch.json 22 | !.vscode/extensions.json 23 | # misc 24 | /.sass-cache 25 | /connect.lock 26 | /coverage 27 | /libpeerconnection.log 28 | npm-debug.log 29 | yarn-error.log 30 | testem.log 31 | /typings 32 | # System Files 33 | .DS_Store 34 | Thumbs.db 35 | .nx/cache 36 | # Next.js 37 | .next 38 | out 39 | .anchor 40 | anchor/target/* 41 | anchor/target/deploy 42 | anchor/target/debug 43 | anchor/target/release 44 | anchor/target/sbf-solana-solana 45 | anchor/target/.rustc_info.json 46 | !anchor/target/idl/*.json 47 | !anchor/target/types/*.ts 48 | test-ledger 49 | .yarn -------------------------------------------------------------------------------- /project-4-crud-app/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 brimigs 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 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/dependency-checks": [ 22 | "error", 23 | { 24 | "ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"] 25 | } 26 | ] 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsc": { 3 | "target": "es2017", 4 | "parser": { 5 | "syntax": "typescript", 6 | "decorators": true, 7 | "dynamicImport": true 8 | }, 9 | "transform": { 10 | "decoratorMetadata": true, 11 | "legacyDecorator": true 12 | }, 13 | "keepClassNames": true, 14 | "externalHelpers": true, 15 | "loose": true 16 | }, 17 | "module": { 18 | "type": "es6" 19 | }, 20 | "sourceMaps": true, 21 | "exclude": [ 22 | "jest.config.ts", 23 | ".*\\.spec.tsx?$", 24 | ".*\\.test.tsx?$", 25 | "./src/jest-setup.ts$", 26 | "./**/jest-setup.ts$", 27 | ".*.js$" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | journal = "94L2mJxVu6ZMmHaGsCHRQ65Kk2mea6aTnwWjSdfSsmBC" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "/Users/brimigs/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "../node_modules/.bin/nx run anchor:jest" 19 | 20 | [test] 21 | startup_wait = 5000 22 | shutdown_wait = 2000 23 | upgradeable = false 24 | 25 | [test.validator] 26 | bind_address = "127.0.0.1" 27 | ledger = ".anchor/test-ledger" 28 | rpc_port = 8899 29 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/README.md: -------------------------------------------------------------------------------- 1 | # anchor 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build anchor` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test anchor` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { readFileSync } from 'fs'; 3 | 4 | // Reading the SWC compilation config and remove the "exclude" 5 | // for the test files to be compiled by SWC 6 | const { exclude: _, ...swcJestConfig } = JSON.parse( 7 | readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8 | ); 9 | 10 | // disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11 | // If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12 | if (swcJestConfig.swcrc === undefined) { 13 | swcJestConfig.swcrc = false; 14 | } 15 | 16 | // Uncomment if using global setup/teardown files being transformed via swc 17 | // https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries 18 | // jest needs EsModule Interop to find the default exported setup/teardown functions 19 | // swcJestConfig.module.noInterop = false; 20 | 21 | export default { 22 | displayName: 'anchor', 23 | preset: '../jest.preset.js', 24 | transform: { 25 | '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 26 | }, 27 | moduleFileExtensions: ['ts', 'js', 'html'], 28 | testEnvironment: '', 29 | coverageDirectory: '../coverage/anchor', 30 | }; 31 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/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 | import * as anchor from '@coral-xyz/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 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@journal/anchor", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@coral-xyz/anchor": "^0.30.1", 6 | "@solana/web3.js": "1.90.0" 7 | }, 8 | "type": "commonjs", 9 | "main": "./index.cjs", 10 | "module": "./index.js" 11 | } 12 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/programs/journal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "journal" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "journal" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | idl-build = ["anchor-lang/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = "0.31" 21 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/programs/journal/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/src/index.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by preset-anchor. Programs are exported from this file. 2 | 3 | export * from './journal-exports'; 4 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/src/journal-exports.ts: -------------------------------------------------------------------------------- 1 | // Here we export some useful types and functions for interacting with the Anchor program. 2 | import { AnchorProvider, Program } from "@coral-xyz/anchor"; 3 | import { Cluster, PublicKey } from "@solana/web3.js"; 4 | import JournalIDL from "../target/idl/journal.json"; 5 | import type { Journal } from "../target/types/journal"; 6 | 7 | // Re-export the generated IDL and type 8 | export { Journal, JournalIDL }; 9 | 10 | // After updating your program ID (e.g. after running `anchor keys sync`) update the value below. 11 | export const JOURNAL_PROGRAM_ID = new PublicKey( 12 | "EZB64BQPMPzGNEV6XvrxTSPcQHCXaRF7aXMgunxQ6LNh" 13 | ); 14 | 15 | // This is a helper function to get the Counter Anchor program. 16 | export function getJournalProgram(provider: AnchorProvider) { 17 | return new Program(JournalIDL as Journal, provider); 18 | } 19 | 20 | // This is a helper function to get the program ID for the Journal program depending on the cluster. 21 | export function getJournalProgramId(cluster: Cluster) { 22 | switch (cluster) { 23 | case "devnet": 24 | case "testnet": 25 | case "mainnet-beta": 26 | default: 27 | return JOURNAL_PROGRAM_ID; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"], 7 | "resolveJsonModule": true, 8 | "allowSyntheticDefaultImports": true 9 | }, 10 | "include": ["src/**/*.ts"], 11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /project-4-crud-app/anchor/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /project-4-crud-app/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjects } from '@nx/jest'; 2 | 3 | export default { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /project-4-crud-app/jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /project-4-crud-app/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2020", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./web/*"], 19 | "@journal/anchor": ["anchor/src/index.ts"] 20 | } 21 | }, 22 | "exclude": ["node_modules", "tmp"] 23 | } 24 | -------------------------------------------------------------------------------- /project-4-crud-app/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "npm run build", 3 | "outputDirectory": "dist/web/.next" 4 | } 5 | -------------------------------------------------------------------------------- /project-4-crud-app/web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:@nx/react-typescript", 4 | "next", 5 | "next/core-web-vitals", 6 | "../.eslintrc.json" 7 | ], 8 | "ignorePatterns": ["!**/*", ".next/**/*"], 9 | "overrides": [ 10 | { 11 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 12 | "rules": { 13 | "@next/next/no-html-link-for-pages": ["error", "web/pages"] 14 | } 15 | }, 16 | { 17 | "files": ["*.ts", "*.tsx"], 18 | "rules": {} 19 | }, 20 | { 21 | "files": ["*.js", "*.jsx"], 22 | "rules": {} 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 26 | "rules": { 27 | "@nx/enforce-module-boundaries": [ 28 | "error", 29 | { 30 | "allow": ["@/"] 31 | } 32 | ] 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/account/[address]/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountDetailFeature from '@/components/account/account-detail-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/account/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountListFeature from '@/components/account/account-list-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET(request: Request) { 2 | return new Response('Hello, from API!'); 3 | } 4 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/clusters/page.tsx: -------------------------------------------------------------------------------- 1 | import ClusterFeature from '@/components/cluster/cluster-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | height: 100%; 8 | } 9 | 10 | .wallet-adapter-button-trigger { 11 | background: rgb(100, 26, 230) !important; 12 | border-radius: 8px !important; 13 | padding-left: 16px !important; 14 | padding-right: 16px !important; 15 | } 16 | .wallet-adapter-dropdown-list, 17 | .wallet-adapter-button { 18 | font-family: inherit !important; 19 | } 20 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/journal/page.tsx: -------------------------------------------------------------------------------- 1 | import JournalFeature from '@/components/journal/journal-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css'; 2 | import { UiLayout } from '@/components/ui/ui-layout'; 3 | import { ClusterProvider } from '@/components/cluster/cluster-data-access'; 4 | import { SolanaProvider } from '@/components/solana/solana-provider'; 5 | import { ReactQueryProvider } from './react-query-provider'; 6 | 7 | export const metadata = { 8 | title: 'journal', 9 | description: 'Generated by create-solana-dapp', 10 | }; 11 | 12 | const links: { label: string; path: string }[] = [ 13 | { label: 'Account', path: '/account' }, 14 | { label: 'Clusters', path: '/clusters' }, 15 | { label: 'Journal Program', path: '/journal' }, 16 | ]; 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: { 21 | children: React.ReactNode; 22 | }) { 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | {children} 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | } 3 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/page.tsx: -------------------------------------------------------------------------------- 1 | import DashboardFeature from '@/components/dashboard/dashboard-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-4-crud-app/web/app/react-query-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React, { ReactNode, useState } from 'react'; 4 | import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'; 5 | import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; 6 | 7 | export function ReactQueryProvider({ children }: { children: ReactNode }) { 8 | const [client] = useState(new QueryClient()); 9 | 10 | return ( 11 | 12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /project-4-crud-app/web/components/account/account-list-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | 6 | import { redirect } from 'next/navigation'; 7 | 8 | export default function AccountListFeature() { 9 | const { publicKey } = useWallet(); 10 | 11 | if (publicKey) { 12 | return redirect(`/account/${publicKey.toString()}`); 13 | } 14 | 15 | return ( 16 |
17 |
18 | 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /project-4-crud-app/web/components/cluster/cluster-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useState } from 'react'; 4 | import { AppHero } from '../ui/ui-layout'; 5 | import { ClusterUiModal } from './cluster-ui'; 6 | import { ClusterUiTable } from './cluster-ui'; 7 | 8 | export default function ClusterFeature() { 9 | const [showModal, setShowModal] = useState(false); 10 | 11 | return ( 12 |
13 | 17 | setShowModal(false)} 20 | /> 21 | 27 | 28 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /project-4-crud-app/web/components/journal/journal-feature.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useWallet } from "@solana/wallet-adapter-react"; 4 | import { WalletButton } from "../solana/solana-provider"; 5 | import { AppHero, ellipsify } from "../ui/ui-layout"; 6 | import { ExplorerLink } from "../cluster/cluster-ui"; 7 | import { useJournalProgram } from "./journal-data-access"; 8 | import { JournalCreate, JournalList } from "./journal-ui"; 9 | 10 | export default function JournalFeature() { 11 | const { publicKey } = useWallet(); 12 | const { programId } = useJournalProgram(); 13 | 14 | return publicKey ? ( 15 |
16 | 17 |

18 | 22 |

23 | 24 |
25 | 26 |
27 | ) : ( 28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /project-4-crud-app/web/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | declare module '*.svg' { 3 | const content: any; 4 | export const ReactComponent: any; 5 | export default content; 6 | } 7 | -------------------------------------------------------------------------------- /project-4-crud-app/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /project-4-crud-app/web/next.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-var-requires 4 | const { composePlugins, withNx } = require('@nx/next'); 5 | 6 | /** 7 | * @type {import('@nx/next/plugins/with-nx').WithNxOptions} 8 | **/ 9 | const nextConfig = { 10 | webpack: (config) => { 11 | config.externals = [ 12 | ...(config.externals || []), 13 | 'bigint', 14 | 'node-gyp-build', 15 | ]; 16 | return config; 17 | }, 18 | nx: { 19 | // Set this to true if you would like to use SVGR 20 | // See: https://github.com/gregberge/svgr 21 | svgr: false, 22 | }, 23 | }; 24 | 25 | const plugins = [ 26 | // Add more Next.js plugins to this list if needed. 27 | withNx, 28 | ]; 29 | 30 | module.exports = composePlugins(...plugins)(nextConfig); 31 | -------------------------------------------------------------------------------- /project-4-crud-app/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | // Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build 4 | // option from your application's configuration (i.e. project.json). 5 | // 6 | // See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries 7 | 8 | module.exports = { 9 | plugins: { 10 | tailwindcss: { 11 | config: join(__dirname, 'tailwind.config.js'), 12 | }, 13 | autoprefixer: {}, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /project-4-crud-app/web/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-4-crud-app/web/public/.gitkeep -------------------------------------------------------------------------------- /project-4-crud-app/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-4-crud-app/web/public/favicon.ico -------------------------------------------------------------------------------- /project-4-crud-app/web/public/solana-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-4-crud-app/web/public/solana-logo.png -------------------------------------------------------------------------------- /project-4-crud-app/web/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); 2 | const { join } = require('path'); 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [ 7 | join( 8 | __dirname, 9 | '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' 10 | ), 11 | ...createGlobPatternsForDependencies(__dirname), 12 | ], 13 | theme: { 14 | extend: {}, 15 | }, 16 | plugins: [require('daisyui')], 17 | }; 18 | -------------------------------------------------------------------------------- /project-4-crud-app/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "preserve", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "incremental": true, 14 | "plugins": [ 15 | { 16 | "name": "next" 17 | } 18 | ] 19 | }, 20 | "include": [ 21 | "**/*.ts", 22 | "**/*.tsx", 23 | "**/*.js", 24 | "**/*.jsx", 25 | "../web/.next/types/**/*.ts", 26 | "../dist/web/.next/types/**/*.ts", 27 | "next-env.d.ts", 28 | ".next/types/**/*.ts" 29 | ], 30 | "exclude": ["node_modules", "jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 31 | } 32 | -------------------------------------------------------------------------------- /project-5-tokens/README.md: -------------------------------------------------------------------------------- 1 | ## Creating a Token 2 | 3 | In this section, we will learn how to create a token on the Solana blockchain. 4 | 5 | ## Resources 6 | 7 | - [Solana Documentation](https://solana.com/docs) 8 | - [Creating a Token](https://solana.com/developers/guides/getstarted/how-to-create-a-token) -------------------------------------------------------------------------------- /project-5-tokens/create-token-mint.ts: -------------------------------------------------------------------------------- 1 | import { createMint } from "@solana/spl-token"; 2 | import "dotenv/config"; 3 | import { 4 | getKeypairFromEnvironment, 5 | getExplorerLink, 6 | } from "@solana-developers/helpers"; 7 | import { Connection, clusterApiUrl } from "@solana/web3.js"; 8 | 9 | const connection = new Connection(clusterApiUrl("devnet")); 10 | 11 | const user = getKeypairFromEnvironment("SECRET_KEY"); 12 | 13 | console.log( 14 | `🔑 Loaded our keypair securely, using an env file! Our public key is: ${user.publicKey.toBase58()}` 15 | ); 16 | 17 | // This is a shortcut that runs: 18 | // SystemProgram.createAccount 19 | // token.createInitializeMintInstruction 20 | // See https://www.soldev.app/course/token-program 21 | const tokenMint = await createMint(connection, user, user.publicKey, null, 2); 22 | 23 | const link = getExplorerLink("address", tokenMint.toString(), "devnet"); 24 | 25 | console.log(`✅ Success! Created token mint: ${link}`); 26 | -------------------------------------------------------------------------------- /project-6-nfts/README.md: -------------------------------------------------------------------------------- 1 | # Creating a NFT 2 | 3 | In this project you will learn how to create a Non-Fungible Token (NFT) on the Solana blockchain. 4 | 5 | [You can follow along with the video to create the NFT](https://www.youtube.com/watch?v=amAq-WHAFs8&t=13752s) 6 | 7 | ## Resources 8 | 9 | - [Solana Documentation](https://solana.com/docs) 10 | - [Umi docs](https://developers.metaplex.com/umi/getting-started) -------------------------------------------------------------------------------- /project-6-nfts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "new-nft", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "@metaplex-foundation/mpl-token-metadata": "^3.2.1", 14 | "@metaplex-foundation/umi-bundle-defaults": "^0.9.2", 15 | "@solana-developers/helpers": "^2.5.2", 16 | "esrun": "^3.2.26" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /project-7-swap/.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | **/*.rs.bk 5 | node_modules 6 | test-ledger 7 | .yarn 8 | -------------------------------------------------------------------------------- /project-7-swap/.prettierignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .DS_Store 3 | target 4 | node_modules 5 | dist 6 | build 7 | test-ledger 8 | -------------------------------------------------------------------------------- /project-7-swap/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | swap = "DAehvmx2vZoWCJi7Qo3Y4YF5vrEWHQRJ288kqKwDy5DV" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | -------------------------------------------------------------------------------- /project-7-swap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-7-swap/README.md: -------------------------------------------------------------------------------- 1 | # Building a Swap Program 2 | 3 | In this project, you will learn how to create a swap program on the Solana blockchain. 4 | 5 | We recommend creating a separate github repository for this project and following along [with the video](https://www.youtube.com/watch?v=amAq-WHAFs8&t=15922s). -------------------------------------------------------------------------------- /project-7-swap/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-7-swap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "ISC", 3 | "scripts": { 4 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 | }, 7 | "dependencies": { 8 | "@coral-xyz/anchor": "^0.30.1", 9 | "@solana-developers/helpers": "^2.4.0", 10 | "@solana/spl-token": "^0.4.8" 11 | }, 12 | "devDependencies": { 13 | "@types/bn.js": "^5.1.0", 14 | "@types/chai": "^4.3.0", 15 | "@types/mocha": "^9.0.0", 16 | "chai": "^4.3.4", 17 | "mocha": "^9.0.3", 18 | "prettier": "^2.6.2", 19 | "ts-mocha": "^10.0.0", 20 | "typescript": "^4.3.5" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "swap" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "swap" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version = "0.30.1", features=["init-if-needed"]} 21 | anchor-spl = "0.30.1" 22 | solana-program= "=2.0.3" -------------------------------------------------------------------------------- /project-7-swap/programs/swap/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/constants.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[constant] 4 | pub const SEED: &str = "anchor"; 5 | 6 | pub const ANCHOR_DISCRIMINATOR: usize = 8; 7 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/error.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[error_code] 4 | pub enum ErrorCode { 5 | #[msg("Custom error message")] 6 | CustomError, 7 | } 8 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod make_offer; 2 | pub use make_offer::*; 3 | 4 | pub mod take_offer; 5 | pub use take_offer::*; 6 | 7 | pub mod shared; 8 | pub use shared::*; 9 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/instructions/shared.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use anchor_spl::token_interface::{ 3 | transfer_checked, Mint, TokenAccount, TokenInterface, TransferChecked, 4 | }; 5 | 6 | pub fn transfer_tokens<'info>( 7 | from: &InterfaceAccount<'info, TokenAccount>, 8 | to: &InterfaceAccount<'info, TokenAccount>, 9 | amount: &u64, 10 | mint: &InterfaceAccount<'info, Mint>, 11 | authority: &Signer<'info>, 12 | token_program: &Interface<'info, TokenInterface>, 13 | ) -> Result<()> { 14 | let transfer_accounts_options = TransferChecked { 15 | from: from.to_account_info(), 16 | mint: mint.to_account_info(), 17 | to: to.to_account_info(), 18 | authority: authority.to_account_info(), 19 | }; 20 | 21 | let cpi_context = CpiContext::new(token_program.to_account_info(), transfer_accounts_options); 22 | 23 | transfer_checked(cpi_context, *amount, mint.decimals) 24 | } 25 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod constants; 2 | pub mod error; 3 | pub mod instructions; 4 | pub mod state; 5 | 6 | use anchor_lang::prelude::*; 7 | 8 | pub use constants::*; 9 | pub use instructions::*; 10 | pub use state::*; 11 | 12 | declare_id!("DAehvmx2vZoWCJi7Qo3Y4YF5vrEWHQRJ288kqKwDy5DV"); 13 | 14 | #[program] 15 | pub mod swap { 16 | use super::*; 17 | 18 | pub fn make_offer( 19 | context: Context, 20 | id: u64, 21 | token_a_offered_amount: u64, 22 | token_b_wanted_amount: u64, 23 | ) -> Result<()> { 24 | instructions::make_offer::send_offered_tokens_to_vault(&context, token_a_offered_amount)?; 25 | instructions::make_offer::save_offer(context, id, token_b_wanted_amount) 26 | } 27 | 28 | pub fn take_offer(context: Context) -> Result<()> { 29 | instructions::take_offer::send_wanted_tokens_to_maker(&context)?; 30 | instructions::take_offer::withdraw_and_close_vault(context) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/state/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod offer; 2 | 3 | pub use offer::*; 4 | -------------------------------------------------------------------------------- /project-7-swap/programs/swap/src/state/offer.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[account] 4 | #[derive(InitSpace)] 5 | pub struct Offer { 6 | pub id: u64, 7 | pub maker: Pubkey, 8 | pub token_mint_a: Pubkey, 9 | pub token_mint_b: Pubkey, 10 | pub token_b_wanted_amount: u64, 11 | pub bump: u8, 12 | } 13 | -------------------------------------------------------------------------------- /project-7-swap/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 | -------------------------------------------------------------------------------- /project-8-token-vesting/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 brimigs 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 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["*.ts", "*.tsx"], 11 | "rules": {} 12 | }, 13 | { 14 | "files": ["*.js", "*.jsx"], 15 | "rules": {} 16 | }, 17 | { 18 | "files": ["*.json"], 19 | "parser": "jsonc-eslint-parser", 20 | "rules": { 21 | "@nx/dependency-checks": [ 22 | "error", 23 | { 24 | "ignoredFiles": ["{projectRoot}/rollup.config.{js,ts,mjs,mts}"] 25 | } 26 | ] 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/.swcrc: -------------------------------------------------------------------------------- 1 | { 2 | "jsc": { 3 | "target": "es2017", 4 | "parser": { 5 | "syntax": "typescript", 6 | "decorators": true, 7 | "dynamicImport": true 8 | }, 9 | "transform": { 10 | "decoratorMetadata": true, 11 | "legacyDecorator": true 12 | }, 13 | "keepClassNames": true, 14 | "externalHelpers": true, 15 | "loose": true 16 | }, 17 | "module": { 18 | "type": "es6" 19 | }, 20 | "sourceMaps": true, 21 | "exclude": [ 22 | "jest.config.ts", 23 | ".*\\.spec.tsx?$", 24 | ".*\\.test.tsx?$", 25 | "./src/jest-setup.ts$", 26 | "./**/jest-setup.ts$", 27 | ".*.js$" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | vesting = "GFdLg11UBR8ZeePW43ZyD1gY4z4UQ96LPa22YBgnn4z8" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "../node_modules/.bin/nx run anchor:jest" 19 | 20 | [test] 21 | startup_wait = 5000 22 | shutdown_wait = 2000 23 | upgradeable = false 24 | 25 | [test.validator] 26 | bind_address = "127.0.0.1" 27 | ledger = ".anchor/test-ledger" 28 | rpc_port = 8899 29 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/README.md: -------------------------------------------------------------------------------- 1 | # anchor 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Building 6 | 7 | Run `nx build anchor` to build the library. 8 | 9 | ## Running unit tests 10 | 11 | Run `nx test anchor` to execute the unit tests via [Jest](https://jestjs.io). 12 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { readFileSync } from 'fs'; 3 | 4 | // Reading the SWC compilation config and remove the "exclude" 5 | // for the test files to be compiled by SWC 6 | const { exclude: _, ...swcJestConfig } = JSON.parse( 7 | readFileSync(`${__dirname}/.swcrc`, 'utf-8') 8 | ); 9 | 10 | // disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves. 11 | // If we do not disable this, SWC Core will read .swcrc and won't transform our test files due to "exclude" 12 | if (swcJestConfig.swcrc === undefined) { 13 | swcJestConfig.swcrc = false; 14 | } 15 | 16 | // Uncomment if using global setup/teardown files being transformed via swc 17 | // https://nx.dev/packages/jest/documents/overview#global-setup/teardown-with-nx-libraries 18 | // jest needs EsModule Interop to find the default exported setup/teardown functions 19 | // swcJestConfig.module.noInterop = false; 20 | 21 | export default { 22 | displayName: 'anchor', 23 | preset: '../jest.preset.js', 24 | transform: { 25 | '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], 26 | }, 27 | moduleFileExtensions: ['ts', 'js', 'html'], 28 | testEnvironment: '', 29 | coverageDirectory: '../coverage/anchor', 30 | }; 31 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/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 | import * as anchor from '@coral-xyz/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 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@token-vesting/anchor", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "@coral-xyz/anchor": "^0.30.1", 6 | "@solana/spl-token": "^0.4.8", 7 | "@solana/web3.js": "1.94.0", 8 | "anchor-bankrun": "^0.4.0", 9 | "solana-bankrun": "^0.2.0", 10 | "spl-token-bankrun": "0.2.5" 11 | }, 12 | "main": "./index.cjs", 13 | "module": "./index.js", 14 | "private": true 15 | } 16 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/programs/vesting/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vesting" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "vesting" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version="0.30.1", features=["init-if-needed"] } 21 | anchor-spl = "0.30.1" 22 | solana-program = "1.18.17" -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/programs/vesting/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/src/index.ts: -------------------------------------------------------------------------------- 1 | // This file was generated by preset-anchor. Programs are exported from this file. 2 | 3 | export * from './vesting-exports'; 4 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/src/vesting-exports.ts: -------------------------------------------------------------------------------- 1 | // Here we export some useful types and functions for interacting with the Anchor program. 2 | import { AnchorProvider, Program } from '@coral-xyz/anchor'; 3 | import { Cluster, PublicKey } from '@solana/web3.js'; 4 | import VestingIDL from '../target/idl/vesting.json'; 5 | import type { Vesting } from '../target/types/vesting'; 6 | 7 | // Re-export the generated IDL and type 8 | export { Vesting, VestingIDL }; 9 | 10 | // The programId is imported from the program IDL. 11 | export const VESTING_PROGRAM_ID = new PublicKey(VestingIDL.address); 12 | 13 | // This is a helper function to get the Vesting Anchor program. 14 | export function getVestingProgram(provider: AnchorProvider) { 15 | return new Program(VestingIDL as Vesting, provider); 16 | } 17 | 18 | // This is a helper function to get the program ID for the Vesting program depending on the cluster. 19 | export function getVestingProgramId(cluster: Cluster) { 20 | switch (cluster) { 21 | case 'devnet': 22 | case 'testnet': 23 | // This is the program ID for the Vesting program on devnet and testnet. 24 | return new PublicKey('2vKg76rA1Ho27YD4uuc2Z2FCwRTySxdyHup1JjsXS6dp'); 25 | case 'mainnet-beta': 26 | default: 27 | return VESTING_PROGRAM_ID; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/tests/fixtures/vesting.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-8-token-vesting/anchor/tests/fixtures/vesting.so -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "module": "commonjs" 5 | }, 6 | "files": [], 7 | "include": [], 8 | "references": [ 9 | { 10 | "path": "./tsconfig.lib.json" 11 | }, 12 | { 13 | "path": "./tsconfig.spec.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "declaration": true, 6 | "types": ["node"], 7 | "resolveJsonModule": true, 8 | "allowSyntheticDefaultImports": true 9 | }, 10 | "include": ["src/**/*.ts"], 11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /project-8-token-vesting/anchor/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "jest.config.ts", 10 | "src/**/*.test.ts", 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /project-8-token-vesting/jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjectsAsync } from '@nx/jest'; 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /project-8-token-vesting/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2020", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@/*": ["./web/*"], 19 | "@token-vesting/anchor": ["anchor/src/index.ts"] 20 | } 21 | }, 22 | "exclude": ["node_modules", "tmp"] 23 | } 24 | -------------------------------------------------------------------------------- /project-8-token-vesting/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "buildCommand": "npm run build", 3 | "outputDirectory": "dist/web/.next" 4 | } 5 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "plugin:@nx/react-typescript", 4 | "next", 5 | "next/core-web-vitals", 6 | "../.eslintrc.json" 7 | ], 8 | "ignorePatterns": ["!**/*", ".next/**/*"], 9 | "overrides": [ 10 | { 11 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 12 | "rules": { 13 | "@next/next/no-html-link-for-pages": ["error", "web/pages"] 14 | } 15 | }, 16 | { 17 | "files": ["*.ts", "*.tsx"], 18 | "rules": {} 19 | }, 20 | { 21 | "files": ["*.js", "*.jsx"], 22 | "rules": {} 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 26 | "rules": { 27 | "@nx/enforce-module-boundaries": [ 28 | "error", 29 | { 30 | "allow": ["@/"] 31 | } 32 | ] 33 | } 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/account/[address]/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountDetailFeature from '@/components/account/account-detail-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/account/page.tsx: -------------------------------------------------------------------------------- 1 | import AccountListFeature from '@/components/account/account-list-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/api/hello/route.ts: -------------------------------------------------------------------------------- 1 | export async function GET(request: Request) { 2 | return new Response('Hello, from API!'); 3 | } 4 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/clusters/page.tsx: -------------------------------------------------------------------------------- 1 | import ClusterFeature from '@/components/cluster/cluster-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html, 6 | body { 7 | height: 100%; 8 | } 9 | 10 | .wallet-adapter-button-trigger { 11 | background: rgb(100, 26, 230) !important; 12 | border-radius: 8px !important; 13 | padding-left: 16px !important; 14 | padding-right: 16px !important; 15 | } 16 | .wallet-adapter-dropdown-list, 17 | .wallet-adapter-button { 18 | font-family: inherit !important; 19 | } 20 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import './global.css'; 2 | import { UiLayout } from '@/components/ui/ui-layout'; 3 | import { ClusterProvider } from '@/components/cluster/cluster-data-access'; 4 | import { SolanaProvider } from '@/components/solana/solana-provider'; 5 | import { ReactQueryProvider } from './react-query-provider'; 6 | 7 | export const metadata = { 8 | title: 'token-vesting', 9 | description: 'Generated by create-solana-dapp', 10 | }; 11 | 12 | const links: { label: string; path: string }[] = [ 13 | { label: 'Account', path: '/account' }, 14 | { label: 'Clusters', path: '/clusters' }, 15 | { label: 'Vesting Program', path: '/vesting' }, 16 | ]; 17 | 18 | export default function RootLayout({ 19 | children, 20 | }: { 21 | children: React.ReactNode; 22 | }) { 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | {children} 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/page.module.css: -------------------------------------------------------------------------------- 1 | .page { 2 | } 3 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/page.tsx: -------------------------------------------------------------------------------- 1 | import DashboardFeature from '@/components/dashboard/dashboard-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/react-query-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import React, { ReactNode, useState } from 'react'; 4 | import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'; 5 | import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; 6 | 7 | export function ReactQueryProvider({ children }: { children: ReactNode }) { 8 | const [client] = useState(new QueryClient()); 9 | 10 | return ( 11 | 12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/app/vesting/page.tsx: -------------------------------------------------------------------------------- 1 | import VestingFeature from '@/components/vesting/vesting-feature'; 2 | 3 | export default function Page() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/components/account/account-list-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | 6 | import { redirect } from 'next/navigation'; 7 | 8 | export default function AccountListFeature() { 9 | const { publicKey } = useWallet(); 10 | 11 | if (publicKey) { 12 | return redirect(`/account/${publicKey.toString()}`); 13 | } 14 | 15 | return ( 16 |
17 |
18 | 19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/components/cluster/cluster-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useState } from 'react'; 4 | import { AppHero } from '../ui/ui-layout'; 5 | import { ClusterUiModal } from './cluster-ui'; 6 | import { ClusterUiTable } from './cluster-ui'; 7 | 8 | export default function ClusterFeature() { 9 | const [showModal, setShowModal] = useState(false); 10 | 11 | return ( 12 |
13 | 17 | setShowModal(false)} 20 | /> 21 | 27 | 28 | 29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/components/vesting/vesting-feature.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import { useWallet } from '@solana/wallet-adapter-react'; 4 | import { WalletButton } from '../solana/solana-provider'; 5 | import { AppHero, ellipsify } from '../ui/ui-layout'; 6 | import { ExplorerLink } from '../cluster/cluster-ui'; 7 | import { useVestingProgram } from './vesting-data-access'; 8 | import { VestingCreate, VestingList } from './vesting-ui'; 9 | 10 | export default function VestingFeature() { 11 | const { publicKey } = useWallet(); 12 | const { programId } = useVestingProgram(); 13 | 14 | return publicKey ? ( 15 |
16 | 20 |

21 | 25 |

26 | 27 |
28 | 29 |
30 | ) : ( 31 |
32 |
33 |
34 | 35 |
36 |
37 |
38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/index.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | declare module '*.svg' { 3 | const content: any; 4 | export const ReactComponent: any; 5 | export default content; 6 | } 7 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/next.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-var-requires 4 | const { composePlugins, withNx } = require('@nx/next'); 5 | 6 | /** 7 | * @type {import('@nx/next/plugins/with-nx').WithNxOptions} 8 | **/ 9 | const nextConfig = { 10 | webpack: (config) => { 11 | config.externals = [ 12 | ...(config.externals || []), 13 | 'bigint', 14 | 'node-gyp-build', 15 | ]; 16 | return config; 17 | }, 18 | nx: { 19 | // Set this to true if you would like to use SVGR 20 | // See: https://github.com/gregberge/svgr 21 | svgr: false, 22 | }, 23 | }; 24 | 25 | const plugins = [ 26 | // Add more Next.js plugins to this list if needed. 27 | withNx, 28 | ]; 29 | 30 | module.exports = composePlugins(...plugins)(nextConfig); 31 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | 3 | // Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build 4 | // option from your application's configuration (i.e. project.json). 5 | // 6 | // See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries 7 | 8 | module.exports = { 9 | plugins: { 10 | tailwindcss: { 11 | config: join(__dirname, 'tailwind.config.js'), 12 | }, 13 | autoprefixer: {}, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-8-token-vesting/web/public/.gitkeep -------------------------------------------------------------------------------- /project-8-token-vesting/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-8-token-vesting/web/public/favicon.ico -------------------------------------------------------------------------------- /project-8-token-vesting/web/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-8-token-vesting/web/public/logo.png -------------------------------------------------------------------------------- /project-8-token-vesting/web/tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); 2 | const { join } = require('path'); 3 | 4 | /** @type {import('tailwindcss').Config} */ 5 | module.exports = { 6 | content: [ 7 | join( 8 | __dirname, 9 | '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' 10 | ), 11 | ...createGlobPatternsForDependencies(__dirname), 12 | ], 13 | theme: { 14 | extend: {}, 15 | }, 16 | plugins: [require('daisyui')], 17 | }; 18 | -------------------------------------------------------------------------------- /project-8-token-vesting/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "jsx": "preserve", 5 | "allowJs": true, 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "incremental": true, 14 | "plugins": [ 15 | { 16 | "name": "next" 17 | } 18 | ] 19 | }, 20 | "include": [ 21 | "**/*.ts", 22 | "**/*.tsx", 23 | "**/*.js", 24 | "**/*.jsx", 25 | "../web/.next/types/**/*.ts", 26 | "../dist/web/.next/types/**/*.ts", 27 | "next-env.d.ts", 28 | ".next/types/**/*.ts" 29 | ], 30 | "exclude": ["node_modules", "jest.config.ts", "**/*.spec.ts", "**/*.test.ts"] 31 | } 32 | -------------------------------------------------------------------------------- /project-9-token-lottery/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | resolution = true 5 | skip-lint = false 6 | 7 | [programs.devnet] 8 | token_lottery = "2RTh2Y4e2N421EbSnUYTKdGqDHJH7etxZb3VrWDMpNMY" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "localnet" 15 | wallet = "~/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | 20 | [[test.validator.clone]] 21 | address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" -------------------------------------------------------------------------------- /project-9-token-lottery/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | resolver = "2" 6 | 7 | [profile.release] 8 | overflow-checks = true 9 | lto = "fat" 10 | codegen-units = 1 11 | [profile.release.build-override] 12 | opt-level = 3 13 | incremental = false 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /project-9-token-lottery/README.md: -------------------------------------------------------------------------------- 1 | # Creating a Token Lottery Program 2 | 3 | In this project, you will learn how to create a token lottery program on the Solana blockchain. 4 | 5 | [You can follow along with the video to create the token lottery](https://www.youtube.com/watch?v=amAq-WHAFs8&t=30677s) 6 | 7 | ## Resources 8 | 9 | - [Solana Documentation](https://solana.com/docs) 10 | - [Switchboard Documentation](https://docs.switchboard.xyz/docs/switchboard/switchboard-randomness) 11 | - [Switchboard SDK](https://github.com/switchboard-xyz/sb-on-demand-examples/tree/main/sb-randomness-on-demand) -------------------------------------------------------------------------------- /project-9-token-lottery/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Token Lottery Ticket #", 3 | "symbol": "TLT", 4 | "description": "Lottery Ticket", 5 | "image": "https://img.freepik.com/free-photo/old-used-brown-torn-ticket-stub-isolated_1101-3193.jpg" 6 | } 7 | -------------------------------------------------------------------------------- /project-9-token-lottery/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("@coral-xyz/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 | -------------------------------------------------------------------------------- /project-9-token-lottery/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 4 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 5 | }, 6 | "dependencies": { 7 | "@coral-xyz/anchor": "^0.30.1", 8 | "@solana/spl-token": "^0.4.8", 9 | "@switchboard-xyz/on-demand": "^1.2.16", 10 | "anchor-bankrun": "^0.4.0", 11 | "solana-bankrun": "^0.3.0" 12 | }, 13 | "devDependencies": { 14 | "@types/bn.js": "^5.1.0", 15 | "@types/chai": "^4.3.0", 16 | "@types/mocha": "^9.0.0", 17 | "chai": "^4.3.4", 18 | "mocha": "^9.0.3", 19 | "prettier": "^2.6.2", 20 | "ts-mocha": "^10.0.0", 21 | "typescript": "^4.3.5" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /project-9-token-lottery/programs/token-lottery/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "token-lottery" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "token_lottery" 10 | 11 | [features] 12 | default = [] 13 | cpi = ["no-entrypoint"] 14 | no-entrypoint = [] 15 | no-idl = [] 16 | no-log-ix-name = [] 17 | idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] 18 | 19 | [dependencies] 20 | anchor-lang = { version="0.30.1", features=["init-if-needed"]} 21 | anchor-spl = { version="0.30.1", features=["metadata"]} 22 | mpl-token-metadata = "4.1.2" 23 | solana-program = "1.18.17" 24 | switchboard-on-demand = "0.1.13" 25 | -------------------------------------------------------------------------------- /project-9-token-lottery/programs/token-lottery/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /project-9-token-lottery/setup/metadata.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-9-token-lottery/setup/metadata.so -------------------------------------------------------------------------------- /project-9-token-lottery/setup/ondemand.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-9-token-lottery/setup/ondemand.so -------------------------------------------------------------------------------- /project-9-token-lottery/setup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 4 | "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 5 | }, 6 | "dependencies": { 7 | "@coral-xyz/anchor": "^0.30.0", 8 | "@solana/spl-token": "^0.4.8", 9 | "@switchboard-xyz/on-demand": "^1.2.15" 10 | }, 11 | "devDependencies": { 12 | "@types/bn.js": "^5.1.0", 13 | "@types/chai": "^4.3.0", 14 | "@types/mocha": "^9.0.0", 15 | "chai": "^4.3.4", 16 | "mocha": "^9.0.3", 17 | "prettier": "^2.6.2", 18 | "ts-mocha": "^10.0.0", 19 | "typescript": "^4.3.5" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /project-9-token-lottery/setup/start-validator.sh: -------------------------------------------------------------------------------- 1 | solana-test-validator --account 3DNK48NH6jvay2nHBiW3wk5yWegD9C2crk2vd9aznRz6 oracle7.json --account 7EyXLrFUtoRoYKhPBnRpjyo2nGTsfGgo2d7XcPb4TwPF oracle6.json --account 2RN1v42zWzzKhLty3Dgen1vbRc4eBsE8PCHanvaSLwJc oracle5.json --account CXyurDdbo9JR5Xh9QuknMJSsuGM3aQdsa38ZVrKSjp1c oracle4.json --account GLc9EQ5ARgnBJvM59wU6eNjaeAEeBa1Gj7jp8rT5NJ8v oracle3.json --account 8Vjo4QEbmB9QhhBu6QiTy66G1tw8WomtFVWECMi3a71y oracle2.json --account BuZBFufhjGn1HDUCukJYognbeoQQW8ACZJq5sWoQPnGe oracle1.json --account GcNZRMqGSEyEULZnLDD3ParcHTgFBrNfUdUCDtThP55e oracle0.json --bpf-program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s metadata.so --bpf-program SW1TCH7qEPTdLsDHRgPuMQjbQxKdH2aBStViMFnt64f switchboard.so --account A43DyUGA7s8eXPxqEjJY6EBu1KKbNgfxF8h17VAHn13w randomness_queue.json --bpf-program SBondMDrcV3K4kxZR1HNVT7osZxAHVHgYXL5Ze1oMUv ondemand.so --account 7Gs9n5FQMeC9XcEhg281bRZ6VHRrCvqp5Yq1j78HkvNa sb_randomness_config.json -r -------------------------------------------------------------------------------- /project-9-token-lottery/setup/switchboard.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solana-developers/developer-bootcamp-2024/facefbd78860bfc16eeb0d6a3686e010bd19ddfa/project-9-token-lottery/setup/switchboard.so -------------------------------------------------------------------------------- /project-9-token-lottery/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 | "resolveJsonModule": true 10 | } 11 | } 12 | --------------------------------------------------------------------------------