├── .DS_Store ├── .gitattributes ├── .gitignore ├── README.md ├── insurance-fund ├── .gitignore ├── .prettierignore ├── .solitarc.js ├── Anchor.toml ├── Anchor.toml.actual ├── Cargo.lock ├── Cargo.toml ├── README.md ├── idl │ └── insurance_fund.json ├── migrations │ └── deploy.ts ├── package.json ├── programs │ └── insurance-fund │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ ├── constants │ │ └── mod.rs │ │ ├── errors │ │ ├── errors.rs │ │ └── mod.rs │ │ ├── events │ │ └── mod.rs │ │ ├── helpers │ │ ├── calculate_receipts_on_mint.rs │ │ ├── calculate_total_deposits.rs │ │ ├── get_price_from_pyth.rs │ │ ├── get_price_from_switchboard.rs │ │ └── mod.rs │ │ ├── instructions │ │ ├── admin │ │ │ ├── add_admin.rs │ │ │ ├── add_asset.rs │ │ │ ├── boost_rewards.rs │ │ │ ├── initialize_insurance_fund.rs │ │ │ ├── initialize_lockup.rs │ │ │ ├── initialize_lockup_vaults.rs │ │ │ ├── initialize_lp.rs │ │ │ ├── initialize_lp_lockup.rs │ │ │ ├── manage_freeze.rs │ │ │ ├── mod.rs │ │ │ ├── rebalance.rs │ │ │ ├── remove_admin.rs │ │ │ └── update_deposit_cap.rs │ │ ├── cpi │ │ │ ├── get_user_balance_and_reward.rs │ │ │ └── mod.rs │ │ ├── crank │ │ │ ├── deposit_rewards.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── slash │ │ │ ├── mod.rs │ │ │ └── slash.rs │ │ ├── swap │ │ │ ├── borrow.rs │ │ │ ├── mod.rs │ │ │ ├── repay.rs │ │ │ ├── swap.rs │ │ │ └── swap_lp.rs │ │ └── user │ │ │ ├── deposit_and_lock_lp.rs │ │ │ ├── mod.rs │ │ │ ├── process_intent.rs │ │ │ ├── request_withdraw.rs │ │ │ ├── restake.rs │ │ │ └── withdraw.rs │ │ ├── lib.rs │ │ └── states │ │ ├── admin.rs │ │ ├── asset.rs │ │ ├── cooldown.rs │ │ ├── debt_record.rs │ │ ├── deposit.rs │ │ ├── intent.rs │ │ ├── lockup.rs │ │ ├── lp │ │ ├── liquidity_pool.rs │ │ ├── lp_lockup.rs │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── reward_boost.rs │ │ └── settings.rs ├── scripts │ ├── helpers │ │ ├── createToken.ts │ │ ├── debugLogs.ts │ │ ├── getOraclePrice.ts │ │ ├── mintTokens.ts │ │ ├── signAndSendTransaction.ts │ │ └── sleep.ts │ └── mainnet.ts ├── sdk │ ├── .gitignore │ ├── .npmignore │ ├── dist │ │ └── generated │ │ │ ├── instructions │ │ │ ├── getUserBalanceAndReward.d.ts │ │ │ ├── getUserBalanceAndReward.js │ │ │ ├── initializeLockupVaults.d.ts │ │ │ └── initializeLockupVaults.js │ │ │ └── types │ │ │ ├── GetUserBalanceAndRewardArgs.d.ts │ │ │ └── GetUserBalanceAndRewardArgs.js │ ├── package.json │ ├── src │ │ ├── classes │ │ │ ├── Restaking.ts │ │ │ └── index.ts │ │ ├── generated │ │ │ ├── accounts │ │ │ │ ├── Admin.ts │ │ │ │ ├── Asset.ts │ │ │ │ ├── Cooldown.ts │ │ │ │ ├── DebtRecord.ts │ │ │ │ ├── Deposit.ts │ │ │ │ ├── Intent.ts │ │ │ │ ├── LiquidityPool.ts │ │ │ │ ├── Lockup.ts │ │ │ │ ├── LpLockup.ts │ │ │ │ ├── RewardBoost.ts │ │ │ │ ├── Settings.ts │ │ │ │ └── index.ts │ │ │ ├── errors │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── instructions │ │ │ │ ├── addAdmin.ts │ │ │ │ ├── addAsset.ts │ │ │ │ ├── boostRewards.ts │ │ │ │ ├── borrow.ts │ │ │ │ ├── depositAndLockLp.ts │ │ │ │ ├── depositRewards.ts │ │ │ │ ├── getUserBalanceAndReward.ts │ │ │ │ ├── index.ts │ │ │ │ ├── initializeInsuranceFund.ts │ │ │ │ ├── initializeLockup.ts │ │ │ │ ├── initializeLockupVaults.ts │ │ │ │ ├── initializeLp.ts │ │ │ │ ├── initializeLpLockup.ts │ │ │ │ ├── manageFreeze.ts │ │ │ │ ├── rebalance.ts │ │ │ │ ├── removeAdmin.ts │ │ │ │ ├── repay.ts │ │ │ │ ├── requestWithdrawal.ts │ │ │ │ ├── restake.ts │ │ │ │ ├── slash.ts │ │ │ │ ├── swap.ts │ │ │ │ ├── swapLp.ts │ │ │ │ ├── updateDepositCap.ts │ │ │ │ └── withdraw.ts │ │ │ └── types │ │ │ │ ├── AddAdminArgs.ts │ │ │ │ ├── BoostRewardsArgs.ts │ │ │ │ ├── BorrowArgs.ts │ │ │ │ ├── CooldownRewards.ts │ │ │ │ ├── DepositAndLockLpArgs.ts │ │ │ │ ├── DepositRewardsArgs.ts │ │ │ │ ├── GetUserBalanceAndRewardArgs.ts │ │ │ │ ├── InitializeInsuranceFundArgs.ts │ │ │ │ ├── InitializeLockupArgs.ts │ │ │ │ ├── InitializeLpLockupArgs.ts │ │ │ │ ├── ManageFreezeArgs.ts │ │ │ │ ├── Oracle.ts │ │ │ │ ├── Permissions.ts │ │ │ │ ├── ProcessIntentArgs.ts │ │ │ │ ├── RebalanceArgs.ts │ │ │ │ ├── RemoveAdminArgs.ts │ │ │ │ ├── RepayArgs.ts │ │ │ │ ├── RequestWithdrawalArgs.ts │ │ │ │ ├── RequestWithdrawalMode.ts │ │ │ │ ├── RestakeArgs.ts │ │ │ │ ├── RewardConfig.ts │ │ │ │ ├── SharesConfig.ts │ │ │ │ ├── SlashArgs.ts │ │ │ │ ├── SlashState.ts │ │ │ │ ├── SwapArgs.ts │ │ │ │ ├── SwapLpArgs.ts │ │ │ │ ├── UpdateDepositCapArgs.ts │ │ │ │ ├── WithdrawArgs.ts │ │ │ │ ├── YieldMode.ts │ │ │ │ └── index.ts │ │ └── index.ts │ └── tsconfig.json ├── tests │ ├── helpers │ │ ├── calculateLpToken.ts │ │ ├── calculateReceiptToken.ts │ │ ├── comparePubkeys.ts │ │ ├── createToken.ts │ │ ├── debugLogs.ts │ │ ├── getOraclePrice.ts │ │ ├── getOraclePriceFromAccount.ts │ │ ├── mintTokens.ts │ │ ├── signAndSendTransaction.ts │ │ └── sleep.ts │ ├── insurance-fund.ts │ └── scenarios │ │ └── no-slash.ts ├── tsconfig.json └── yarn.lock ├── reflect-single-pool ├── .DS_Store ├── .gitignore ├── README.md ├── cli │ ├── .DS_Store │ ├── .gitignore │ ├── Cargo.toml │ ├── src │ │ ├── cli.rs │ │ ├── config.rs │ │ ├── main.rs │ │ ├── output.rs │ │ └── quarantine.rs │ └── tests │ │ └── test.rs ├── js │ ├── .gitignore │ ├── LICENSE │ ├── packages │ │ ├── classic │ │ │ ├── .eslintignore │ │ │ ├── .eslintrc.cjs │ │ │ ├── .gitignore │ │ │ ├── .prettierrc.cjs │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── src │ │ │ │ ├── addresses.ts │ │ │ │ ├── index.ts │ │ │ │ ├── instructions.ts │ │ │ │ ├── internal.ts │ │ │ │ ├── mpl_metadata.ts │ │ │ │ └── transactions.ts │ │ │ ├── tests │ │ │ │ ├── fixtures │ │ │ │ │ ├── mpl_token_metadata.so │ │ │ │ │ └── spl_single_pool.so │ │ │ │ ├── transactions.test.ts │ │ │ │ └── vote_account.json │ │ │ ├── ts-fixup.sh │ │ │ ├── tsconfig-base.json │ │ │ ├── tsconfig-cjs.json │ │ │ └── tsconfig.json │ │ └── modern │ │ │ ├── .eslintignore │ │ │ ├── .eslintrc.cjs │ │ │ ├── .gitignore │ │ │ ├── .prettierrc.cjs │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── src │ │ │ ├── addresses.ts │ │ │ ├── index.ts │ │ │ ├── instructions.ts │ │ │ ├── internal.ts │ │ │ ├── quarantine.ts │ │ │ └── transactions.ts │ │ │ ├── ts-fixup.sh │ │ │ ├── tsconfig-base.json │ │ │ ├── tsconfig-cjs.json │ │ │ └── tsconfig.json │ ├── ts-fixup.sh │ ├── tsconfig-base.json │ ├── tsconfig-cjs.json │ └── tsconfig.json └── program │ ├── .DS_Store │ ├── .gitignore │ ├── Cargo.toml │ ├── program-id.md │ ├── src │ ├── entrypoint.rs │ ├── error.rs │ ├── inline_mpl_token_metadata.rs │ ├── instruction.rs │ ├── lib.rs │ ├── processor.rs │ └── state.rs │ └── tests │ ├── accounts.rs │ ├── create_pool_token_metadata.rs │ ├── deposit.rs │ ├── fixtures │ └── mpl_token_metadata.so │ ├── helpers │ ├── mod.rs │ ├── stake.rs │ └── token.rs │ ├── initialize.rs │ ├── reactivate.rs │ ├── update_pool_token_metadata.rs │ └── withdraw.rs ├── reflect-tokenised-bonds ├── .gitignore ├── .prettierignore ├── .solitarc.js ├── Anchor.toml ├── Cargo.lock ├── Cargo.toml ├── README.md ├── idl │ └── reflect_tokenised_bonds.json ├── migrations │ └── deploy.ts ├── package.json ├── programs │ └── reflect-tokenised-bonds │ │ ├── Cargo.toml │ │ ├── Xargo.toml │ │ └── src │ │ ├── constants │ │ └── mod.rs │ │ ├── errors │ │ ├── errors.rs │ │ └── mod.rs │ │ ├── instructions │ │ ├── create_vault.rs │ │ ├── deposit.rs │ │ ├── initialize.rs │ │ ├── mod.rs │ │ └── withdraw.rs │ │ ├── lib.rs │ │ └── state │ │ ├── admin.rs │ │ ├── config.rs │ │ ├── mod.rs │ │ └── vault.rs ├── sdk │ ├── .npmignore │ ├── dist │ │ ├── accounts │ │ │ ├── LockupState.d.ts │ │ │ ├── LockupState.js │ │ │ ├── RTBProtocol.d.ts │ │ │ ├── RTBProtocol.js │ │ │ ├── UserAccount.d.ts │ │ │ ├── UserAccount.js │ │ │ ├── Vault.d.ts │ │ │ ├── Vault.js │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── errors │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── index.d.ts │ │ ├── index.js │ │ └── instructions │ │ │ ├── createVault.d.ts │ │ │ ├── createVault.js │ │ │ ├── deposit.d.ts │ │ │ ├── deposit.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── initVaultPools.d.ts │ │ │ ├── initVaultPools.js │ │ │ ├── initializeProtocol.d.ts │ │ │ ├── initializeProtocol.js │ │ │ ├── lockup.d.ts │ │ │ ├── lockup.js │ │ │ ├── withdraw.d.ts │ │ │ └── withdraw.js │ ├── package.json │ ├── src │ │ ├── accounts │ │ │ ├── LockupState.ts │ │ │ ├── RTBProtocol.ts │ │ │ ├── UserAccount.ts │ │ │ ├── Vault.ts │ │ │ └── index.ts │ │ ├── errors │ │ │ └── index.ts │ │ ├── index.ts │ │ └── instructions │ │ │ ├── createVault.ts │ │ │ ├── deposit.ts │ │ │ ├── index.ts │ │ │ ├── initVaultPools.ts │ │ │ ├── initializeProtocol.ts │ │ │ ├── lockup.ts │ │ │ └── withdraw.ts │ ├── tsconfig.json │ └── yarn.lock ├── tests │ └── reflect-tokenised-bonds.ts ├── tsconfig.json └── yarn.lock └── ssm ├── .DS_Store └── solana-stake-market ├── .DS_Store ├── .gitignore ├── .solitarc.js ├── Anchor.toml ├── Cargo.lock ├── Cargo.toml ├── README.md ├── Xargo.toml ├── idl └── solana_stake_market.json ├── migrations └── deploy.ts ├── package-lock.json ├── package.json ├── programs └── solana-stake-market │ ├── Cargo.toml │ ├── Xargo.toml │ ├── program_key │ └── sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37.json │ └── src │ ├── constants │ └── mod.rs │ ├── errors.rs │ ├── instructions │ ├── close_bid.rs │ ├── initialize_order_book.rs │ ├── mod.rs │ ├── place_bid.rs │ └── sell_stake.rs │ ├── lib.rs │ ├── states │ ├── bid.rs │ ├── mod.rs │ └── order_book.rs │ └── utils.rs ├── sdk ├── accounts │ ├── Bid.ts │ ├── OrderBook.ts │ └── index.ts ├── errors │ └── index.ts ├── index.ts └── instructions │ ├── closeBid.ts │ ├── index.ts │ ├── initializeOrderBookWrapper.ts │ ├── placeBid.ts │ └── sellStake.ts ├── tests ├── place_bid_test.rs └── solana-stake-market.ts ├── tsconfig.json └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palindrome-eng/reflect-program-library/5f4f49df98017fb85ec8a75b3626b7aaabdf203f/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # reflect-program-library 2 | Reflect Protocol fork of the Solana-Program Library for internal development. 3 | -------------------------------------------------------------------------------- /insurance-fund/.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | .anchor 3 | .DS_Store 4 | target 5 | **/*.rs.bk 6 | node_modules 7 | test-ledger 8 | .yarn 9 | sdk/dist 10 | .env 11 | .idea 12 | .crates 13 | -------------------------------------------------------------------------------- /insurance-fund/.prettierignore: -------------------------------------------------------------------------------- 1 | 2 | .anchor 3 | .DS_Store 4 | target 5 | node_modules 6 | dist 7 | build 8 | test-ledger 9 | -------------------------------------------------------------------------------- /insurance-fund/.solitarc.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const programDir = path.join(__dirname, '.', 'programs/insurance-fund'); 3 | const idlDir = path.join(__dirname, 'idl'); 4 | const sdkDir = path.join(__dirname, 'sdk/src/generated'); 5 | const binaryInstallDir = path.join(__dirname, '.crates'); 6 | 7 | module.exports = { 8 | idlGenerator: 'anchor', 9 | programName: 'insurance_fund', 10 | programId: 'rhLMe6vyM1wVLJaxrWUckVmPxSia58nSWZRDtYQow6D', 11 | idlDir, 12 | sdkDir, 13 | binaryInstallDir, 14 | programDir, 15 | }; -------------------------------------------------------------------------------- /insurance-fund/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | insurance_fund = "rhLMe6vyM1wVLJaxrWUckVmPxSia58nSWZRDtYQow6D" 9 | lp = "Wqq4jCGbvpDLW56ZxS4Z4xfamZD4ApSbjae35uGqzss" 10 | 11 | [registry] 12 | url = "https://api.apr.dev" 13 | 14 | [provider] 15 | cluster = "Localnet" 16 | wallet = "/Users/kubaplata/.config/solana/id.json" 17 | 18 | [scripts] 19 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/insurance-fund.ts" 20 | test-no-slash = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/scenarios/no-slash.ts" 21 | test-sdk = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/restaking-sdk.ts" 22 | 23 | [test] 24 | startup_wait = 5000 25 | shutdown_wait = 2000 26 | upgradeable = false 27 | 28 | [test.validator] 29 | bind_address = "0.0.0.0" 30 | url = "https://api.mainnet-beta.solana.com" 31 | ledger = ".anchor/test-ledger" 32 | rpc_port = 8899 33 | 34 | [[test.validator.clone]] 35 | address = "H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG" 36 | 37 | [[test.validator.clone]] 38 | address = "7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE" 39 | 40 | [[test.validator.clone]] 41 | address = "rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ" 42 | [[test.validator.clone]] 43 | address = "Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX" -------------------------------------------------------------------------------- /insurance-fund/Anchor.toml.actual: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | insurance_fund = "2MN1Dbnu7zM9Yj4ougn6ZCNNKevrSvi9AR56iawzkye8" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | wallet = "/Users/kubaplata/.config/solana/id.json" 16 | 17 | [scripts] 18 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 19 | 20 | [test.validator] 21 | url = "https://api.mainnet-beta.solana.com" 22 | 23 | [[test.validator.clone]] 24 | address = "7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE" 25 | 26 | [[test.validator.clone]] 27 | address = "rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ" 28 | -------------------------------------------------------------------------------- /insurance-fund/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | 6 | [profile.release] 7 | overflow-checks = true 8 | lto = "fat" 9 | codegen-units = 1 10 | [profile.release.build-override] 11 | opt-level = 3 12 | incremental = false 13 | codegen-units = 1 14 | -------------------------------------------------------------------------------- /insurance-fund/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 | -------------------------------------------------------------------------------- /insurance-fund/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.29.0", 8 | "@metaplex-foundation/solita": "^0.20.1", 9 | "@solana/spl-token": "^0.4.8", 10 | "@solana/web3.js": "1.97.0", 11 | "axios": "^1.7.7", 12 | "bn.js": "5.2.1", 13 | "bs58": "^6.0.0", 14 | "kinobi": "0.20.1" 15 | }, 16 | "devDependencies": { 17 | "@metaplex-foundation/mpl-token-metadata": "2", 18 | "@types/bn.js": "^5.1.6", 19 | "@types/chai": "^4.3.0", 20 | "@types/mocha": "^9.0.0", 21 | "chai": "^4.3.4", 22 | "mocha": "^9.0.3", 23 | "prettier": "^2.6.2", 24 | "ts-mocha": "^10.0.0", 25 | "typescript": "^4.3.5" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "insurance-fund" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "insurance_fund" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | 18 | [dependencies] 19 | anchor-lang = { version = "0.29.0", features = [ "init-if-needed" ] } 20 | anchor-spl = "0.29.0" 21 | pyth-solana-receiver-sdk = "0.3.1" 22 | switchboard-solana = "0.29" -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/constants/mod.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[constant] 4 | pub const SETTINGS_SEED: &str = "settings"; 5 | 6 | #[constant] 7 | pub const LOCKUP_SEED: &str = "lockup"; 8 | 9 | #[constant] 10 | pub const COLD_VAULT_SEED: &str = "cold_vault"; 11 | 12 | #[constant] 13 | pub const DEPOSIT_SEED: &str = "deposit"; 14 | 15 | #[constant] 16 | pub const SLASH_SEED: &str = "slash"; 17 | 18 | #[constant] 19 | pub const ASSET_SEED: &str = "asset"; 20 | 21 | #[constant] 22 | pub const REWARD_BOOST_SEED: &str = "reward_boost"; 23 | 24 | #[constant] 25 | pub const REWARD_POOL_SEED: &str = "reward_pool"; 26 | 27 | #[constant] 28 | pub const PRICE_PRECISION: i32 = 9; 29 | 30 | #[constant] 31 | pub const INTENT_SEED: &str = "intent"; 32 | 33 | #[constant] 34 | pub const COOLDOWN_SEED: &str = "cooldown"; 35 | 36 | #[constant] 37 | pub const COOLDOWN_VAULT_SEED: &str = "cooldown_vault"; 38 | 39 | #[constant] 40 | pub const ADMIN_SEED: &str = "admin"; 41 | 42 | #[constant] 43 | pub const HOT_VAULT_SEED: &str = "hot_vault"; 44 | 45 | #[constant] 46 | pub const DEPOSIT_RECEIPT_VAULT_SEED: &str = "deposit_receipt_vault"; 47 | 48 | #[constant] 49 | pub const DEBT_RECORD_SEED: &str = "debt_record"; 50 | 51 | #[constant] 52 | pub const LIQUIDITY_POOL_SEED: &str = "liquidity_pool"; 53 | 54 | #[constant] 55 | pub const LIQUIDITY_POOL_LOCKUP_SEED: &str = "lp_lockup"; 56 | 57 | #[constant] 58 | pub const ORACLE_MAXIMUM_AGE: u64 = 60 * 60; // ? -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/errors/errors.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[error_code] 4 | pub enum InsuranceFundError { 5 | #[msg("InvalidSigner")] 6 | InvalidSigner, 7 | 8 | #[msg("InvalidInput")] 9 | InvalidInput, 10 | 11 | #[msg("AssetNotWhitelisted")] 12 | AssetNotWhitelisted, 13 | 14 | #[msg("DepositTooLow")] 15 | DepositTooLow, 16 | 17 | #[msg("DepositCapOverflow")] 18 | DepositCapOverflow, 19 | 20 | #[msg("NotEnoughFunds")] 21 | NotEnoughFunds, 22 | 23 | #[msg("NotEnoughReceiptTokens")] 24 | NotEnoughReceiptTokens, 25 | 26 | #[msg("NotEnoughFundsToSlash")] 27 | NotEnoughFundsToSlash, 28 | 29 | #[msg("DepositsLocked")] 30 | DepositsLocked, 31 | 32 | #[msg("DepositsOpen")] 33 | DepositsOpen, 34 | 35 | #[msg("DepositsNotSlashed")] 36 | DepositsNotSlashed, 37 | 38 | #[msg("AllDepositsSlashed")] 39 | AllDepositsSlashed, 40 | 41 | #[msg("SlashAmountMismatch")] 42 | SlashAmountMismatch, 43 | 44 | #[msg("ShareConfigOverflow")] 45 | ShareConfigOverflow, 46 | 47 | #[msg("Frozen")] 48 | Frozen, 49 | 50 | #[msg("InvalidOracle")] 51 | InvalidOracle, 52 | 53 | #[msg("MathOverflow")] 54 | MathOverflow, 55 | 56 | #[msg("LockupInForce")] 57 | LockupInForce, 58 | 59 | #[msg("BoostNotApplied")] 60 | BoostNotApplied, 61 | 62 | #[msg("InvalidSigners")] 63 | InvalidSigners, 64 | 65 | #[msg("TransferSignatureRequired")] 66 | TransferSignatureRequired, 67 | 68 | #[msg("ColdWalletNotSlashed")] 69 | ColdWalletNotSlashed, 70 | 71 | #[msg("PermissionsTooLow")] 72 | PermissionsTooLow, 73 | 74 | #[msg("WithdrawalThresholdOverflow")] 75 | WithdrawalThresholdOverflow, 76 | 77 | #[msg("PoolImbalance")] 78 | PoolImbalance, 79 | 80 | #[msg("InvalidReceiptTokenSetup")] 81 | InvalidReceiptTokenSetup, 82 | 83 | #[msg("InvalidReceiptTokenDecimals")] 84 | InvalidReceiptTokenDecimals, 85 | 86 | #[msg("InvalidReceiptTokenMintAuthority")] 87 | InvalidReceiptTokenMintAuthority, 88 | 89 | #[msg("InvalidReceiptTokenSupply")] 90 | InvalidReceiptTokenSupply, 91 | 92 | #[msg("InvalidReceiptTokenFreezeAuthority")] 93 | InvalidReceiptTokenFreezeAuthority, 94 | 95 | #[msg("MinimumSuperadminsRequired")] 96 | MinimumSuperadminsRequired, 97 | 98 | #[msg("IntentValueTooLow")] 99 | IntentValueTooLow, 100 | 101 | #[msg("WithdrawalNeedsIntent")] 102 | WithdrawalNeedsIntent, 103 | 104 | #[msg("PriceError")] 105 | PriceError, 106 | 107 | #[msg("CooldownInForce")] 108 | CooldownInForce, 109 | 110 | #[msg("SlippageExceeded")] 111 | SlippageExceeded, 112 | 113 | #[msg("InvalidTokenOrder")] 114 | InvalidTokenOrder, 115 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/errors/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod errors; 2 | pub use errors::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/events/mod.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | use crate::states::Permissions; 4 | 5 | #[event] 6 | pub struct RestakeEvent { 7 | pub from: Pubkey, 8 | pub asset: Pubkey, 9 | pub amount: u64, 10 | pub lockup_ts: u64 11 | } 12 | 13 | #[event] 14 | pub struct WithdrawEvent { 15 | pub from: Pubkey, 16 | pub asset: Pubkey, 17 | pub base_amount: u64, 18 | pub reward_amount: u64 19 | } 20 | 21 | #[event] 22 | pub struct DepositRewardEvent { 23 | pub from: Pubkey, 24 | pub asset: Pubkey, 25 | pub amount: u64 26 | } 27 | 28 | #[event] 29 | pub struct InitializeSlashEvent { 30 | pub id: u64, 31 | pub lockup: Pubkey, 32 | pub asset: Pubkey, 33 | pub amount: u64, 34 | pub slot: u64 35 | } 36 | 37 | #[event] 38 | pub struct ProcessSlashEvent { 39 | pub progress_accounts: u64, 40 | pub target_accounts: u64, 41 | pub progress_amount: u64, 42 | pub target_amount: u64, 43 | } 44 | 45 | #[event] 46 | pub struct FinalizeSlash { 47 | pub id: u64, 48 | pub amount: u64, 49 | } 50 | 51 | #[event] 52 | pub struct CreateIntent { 53 | pub deposit: Pubkey, 54 | pub amount: u64, 55 | } 56 | 57 | // Since processing intent closes the account, 58 | // this event will be fat for indexing purposes as we don't have easy 59 | // access to this state anymore. 60 | 61 | #[event] 62 | pub struct ProcessIntent { 63 | pub amount: u64, 64 | pub deposit: Pubkey, 65 | pub processed_by: Pubkey, 66 | } 67 | 68 | #[event] 69 | pub struct AddAssetEvent { 70 | pub admin: Pubkey, 71 | pub asset: Pubkey, 72 | pub oracle: Pubkey, 73 | } 74 | 75 | #[event] 76 | pub struct ChangeAdminEvent { 77 | pub affected_admin: Pubkey, 78 | pub signer: Pubkey, 79 | pub permission_change: Option, 80 | } 81 | 82 | #[event] 83 | pub struct InitializeInsuranceFund { 84 | pub new_admin: Pubkey, 85 | } 86 | 87 | #[event] 88 | pub struct InitializeLockupEvent { 89 | pub admin: Pubkey, 90 | pub lockup: Pubkey, 91 | pub asset: Pubkey, 92 | pub duration: u64, 93 | } 94 | 95 | #[event] 96 | pub struct ManageFreezeEvent { 97 | pub admin: Pubkey, 98 | pub frozen: bool 99 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/helpers/calculate_receipts_on_mint.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::errors::InsuranceFundError; 3 | use anchor_spl::token::Mint; 4 | 5 | #[inline(never)] 6 | pub fn calculate_receipts_on_mint( 7 | receipt_token_mint: &Account, 8 | deposit: u64, 9 | total_deposits: u64 10 | ) -> Result { 11 | if receipt_token_mint.supply == 0 { 12 | Ok( 13 | deposit 14 | .try_into() 15 | .map_err(|_| InsuranceFundError::MathOverflow)? 16 | ) 17 | } else { 18 | let result = (deposit as u128) 19 | .checked_mul(total_deposits as u128) 20 | .ok_or(InsuranceFundError::MathOverflow)? 21 | .checked_div(receipt_token_mint.supply as u128) 22 | .ok_or(InsuranceFundError::MathOverflow)?; 23 | 24 | Ok( 25 | result 26 | .try_into() 27 | .map_err(|_| InsuranceFundError::MathOverflow)? 28 | ) 29 | } 30 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/helpers/calculate_total_deposits.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::errors::InsuranceFundError; 3 | use anchor_spl::token::TokenAccount; 4 | 5 | #[inline(never)] 6 | pub fn calculate_total_deposits( 7 | cold_wallet: &Account, 8 | hot_wallet: &Account 9 | ) -> Result { 10 | let result = cold_wallet.amount 11 | .checked_add(hot_wallet.amount) 12 | .ok_or(InsuranceFundError::MathOverflow)?; 13 | 14 | Ok(result) 15 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/helpers/get_price_from_pyth.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use pyth_solana_receiver_sdk::price_update::PriceUpdateV2; 3 | use super::OraclePrice; 4 | use crate::constants::*; 5 | use crate::errors::InsuranceFundError; 6 | use anchor_lang::AccountDeserialize; 7 | 8 | #[inline(never)] 9 | pub fn get_price_from_pyth( 10 | oracle_account: &AccountInfo, 11 | clock: &Clock 12 | ) -> Result { 13 | let oracle_account_data = oracle_account.try_borrow_mut_data()?; 14 | let oracle = PriceUpdateV2 15 | ::try_deserialize(&mut oracle_account_data.as_ref())?; 16 | 17 | let price = oracle.get_price_no_older_than( 18 | &clock, 19 | ORACLE_MAXIMUM_AGE, 20 | &oracle.price_message.feed_id 21 | )?; 22 | 23 | let exponent = price.exponent; 24 | 25 | Ok(OraclePrice { 26 | price: price.price, 27 | exponent 28 | }) 29 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/helpers/get_price_from_switchboard.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | 3 | use anchor_lang::prelude::*; 4 | use switchboard_solana::AggregatorAccountData; 5 | use crate::{constants::ORACLE_MAXIMUM_AGE, errors::InsuranceFundError}; 6 | use super::OraclePrice; 7 | 8 | #[inline(never)] 9 | pub fn get_price_from_switchboard( 10 | account: &AccountInfo, 11 | clock: &Clock, 12 | ) -> Result { 13 | let account_data = account.try_borrow_mut_data()?; 14 | let oracle_data = AggregatorAccountData 15 | ::new_from_bytes(&account_data.as_ref()) 16 | .map_err(|_| InsuranceFundError::PriceError)?; 17 | 18 | let unix_timestamp = clock.unix_timestamp; 19 | 20 | oracle_data.check_staleness( 21 | unix_timestamp, 22 | ORACLE_MAXIMUM_AGE as i64 23 | ).map_err(|_| InsuranceFundError::PriceError)?; 24 | 25 | let result = oracle_data 26 | .get_result() 27 | .map_err(|_| InsuranceFundError::PriceError)?; 28 | 29 | Ok(OraclePrice { 30 | price: result.try_into().map_err(|_| InsuranceFundError::PriceError)?, 31 | // result.scale is always decimal places to move to the **LEFT** to yield the actual value 32 | // since pyth can return both negative or positive scales, we have to add negative sign here 33 | exponent: (result.scale as i32).mul(-1) 34 | }) 35 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod calculate_total_deposits; 2 | pub use calculate_total_deposits::*; 3 | 4 | pub mod calculate_receipts_on_mint; 5 | pub use calculate_receipts_on_mint::*; 6 | 7 | pub mod get_price_from_pyth; 8 | pub use get_price_from_pyth::*; 9 | 10 | pub mod get_price_from_switchboard; 11 | pub use get_price_from_switchboard::*; 12 | 13 | use crate::errors::InsuranceFundError; 14 | 15 | #[derive(Debug)] 16 | pub struct OraclePrice { 17 | pub price: i64, 18 | pub exponent: i32, 19 | } 20 | 21 | impl OraclePrice { 22 | 23 | #[inline(never)] 24 | pub fn mul( 25 | &self, 26 | amount: u64 27 | ) -> Result { 28 | let price: u128; 29 | 30 | if self.exponent >= 0 { 31 | price = (amount as i128) 32 | .checked_mul(self.price.into()) 33 | .ok_or(InsuranceFundError::MathOverflow.into())? 34 | // If exponent is positive, multiply by power of 10. 35 | .checked_mul( 36 | i128::try_from( 37 | 10_i64 38 | .checked_pow(self.exponent.abs_diff(0)) 39 | .ok_or(InsuranceFundError::MathOverflow.into())? 40 | ) 41 | .map_err(|_| InsuranceFundError::MathOverflow)? 42 | ) 43 | .ok_or(InsuranceFundError::MathOverflow.into())? 44 | .try_into() 45 | .map_err(|_| InsuranceFundError::MathOverflow.into())?; 46 | } else { 47 | price = (amount as i128) 48 | .checked_mul(self.price.into()) 49 | .ok_or(InsuranceFundError::MathOverflow.into())? 50 | // If exponent is negative, divide by power of 10. 51 | .checked_div( 52 | i128::try_from( 53 | 10_i64 54 | .checked_pow(self.exponent.abs_diff(0)) 55 | .ok_or(InsuranceFundError::MathOverflow.into())? 56 | ) 57 | .map_err(|_| InsuranceFundError::MathOverflow)? 58 | ) 59 | .ok_or(InsuranceFundError::MathOverflow.into())? 60 | .try_into() 61 | .map_err(|_| InsuranceFundError::MathOverflow.into())?; 62 | } 63 | 64 | Ok(price) 65 | } 66 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/add_admin.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::states::*; 3 | use crate::constants::*; 4 | use crate::events::*; 5 | use crate::errors::InsuranceFundError; 6 | 7 | #[derive(AnchorSerialize, AnchorDeserialize)] 8 | pub struct AddAdminArgs { 9 | address: Pubkey, 10 | permissions: Permissions 11 | } 12 | 13 | pub fn add_admin( 14 | ctx: Context, 15 | args: AddAdminArgs 16 | ) -> Result<()> { 17 | 18 | let AddAdminArgs { 19 | address, 20 | permissions 21 | } = args; 22 | 23 | let settings = &mut ctx.accounts.settings; 24 | let new_admin = &mut ctx.accounts.new_admin; 25 | let signer = &ctx.accounts.signer; 26 | 27 | new_admin.address = address; 28 | new_admin.permissions = permissions; 29 | 30 | match args.permissions { 31 | Permissions::Superadmin => { 32 | settings.superadmins += 1; 33 | }, 34 | _ => {} 35 | }; 36 | 37 | emit!(ChangeAdminEvent { 38 | affected_admin: args.address, 39 | signer: signer.key(), 40 | permission_change: Some(args.permissions) 41 | }); 42 | 43 | Ok(()) 44 | } 45 | 46 | #[derive(Accounts)] 47 | #[instruction( 48 | args: AddAdminArgs 49 | )] 50 | pub struct AddAdmin<'info> { 51 | #[account( 52 | mut 53 | )] 54 | pub signer: Signer<'info>, 55 | 56 | #[account( 57 | mut, 58 | seeds = [ 59 | ADMIN_SEED.as_bytes(), 60 | signer.key().as_ref() 61 | ], 62 | bump, 63 | constraint = existing_admin.has_permissions_over(args.permissions) @ InsuranceFundError::PermissionsTooLow 64 | )] 65 | pub existing_admin: Account<'info, Admin>, 66 | 67 | #[account( 68 | // If exists, change, grant or remove one's permissions 69 | init_if_needed, 70 | payer = signer, 71 | seeds = [ 72 | ADMIN_SEED.as_bytes(), 73 | args.address.as_ref(), 74 | ], 75 | bump, 76 | space = 8 + Admin::INIT_SPACE, 77 | )] 78 | pub new_admin: Account<'info, Admin>, 79 | 80 | #[account( 81 | mut, 82 | seeds = [ 83 | SETTINGS_SEED.as_bytes() 84 | ], 85 | bump, 86 | constraint = !settings.frozen @ InsuranceFundError::Frozen 87 | )] 88 | pub settings: Account<'info, Settings>, 89 | 90 | #[account()] 91 | pub system_program: Program<'info, System>, 92 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/add_asset.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use switchboard_solana::ID as SWITCHBOARD_PROGRAM_ID; 3 | use pyth_solana_receiver_sdk::ID as PYTH_PROGRAM_ID; 4 | use crate::errors::InsuranceFundError; 5 | use crate::events::AddAssetEvent; 6 | use crate::helpers::get_price_from_pyth; 7 | use crate::helpers::get_price_from_switchboard; 8 | use crate::states::*; 9 | use crate::constants::*; 10 | use anchor_spl::token::Mint; 11 | 12 | pub fn add_asset( 13 | ctx: Context 14 | ) -> Result<()> { 15 | let asset = &mut ctx.accounts.asset; 16 | let asset_mint = &ctx.accounts.asset_mint; 17 | let oracle = &ctx.accounts.oracle; 18 | let signer = &ctx.accounts.signer; 19 | 20 | asset.mint = asset_mint.key(); 21 | asset.tvl = 0; 22 | asset.deposits = 0; 23 | asset.lockups = 0; 24 | 25 | let clock = Clock::get()?; 26 | 27 | emit!(AddAssetEvent { 28 | admin: signer.key(), 29 | asset: asset_mint.key(), 30 | oracle: oracle.key() 31 | }); 32 | 33 | if oracle.owner.eq(&PYTH_PROGRAM_ID) { 34 | get_price_from_pyth(oracle, &clock)?; 35 | asset.oracle = Oracle::Pyth(oracle.key()); 36 | 37 | Ok(()) 38 | } else if oracle.owner.eq(&SWITCHBOARD_PROGRAM_ID) { 39 | get_price_from_switchboard(oracle, &clock)?; 40 | asset.oracle = Oracle::Switchboard(oracle.key()); 41 | 42 | Ok(()) 43 | } else { 44 | Err(InsuranceFundError::InvalidOracle.into()) 45 | } 46 | } 47 | 48 | #[derive(Accounts)] 49 | pub struct AddAsset<'info> { 50 | #[account( 51 | mut 52 | )] 53 | pub signer: Signer<'info>, 54 | 55 | #[account( 56 | mut, 57 | seeds = [ 58 | ADMIN_SEED.as_bytes(), 59 | signer.key().as_ref() 60 | ], 61 | bump, 62 | constraint = admin.has_permissions(Permissions::AssetsAndLockups) @ InsuranceFundError::PermissionsTooLow 63 | )] 64 | pub admin: Account<'info, Admin>, 65 | 66 | #[account( 67 | mut, 68 | seeds = [ 69 | SETTINGS_SEED.as_bytes() 70 | ], 71 | bump, 72 | constraint = !settings.frozen @ InsuranceFundError::Frozen 73 | )] 74 | pub settings: Account<'info, Settings>, 75 | 76 | #[account( 77 | init, 78 | payer = signer, 79 | seeds = [ 80 | ASSET_SEED.as_bytes(), 81 | &asset_mint.key().to_bytes() 82 | ], 83 | bump, 84 | space = 8 + Asset::INIT_SPACE 85 | )] 86 | pub asset: Account<'info, Asset>, 87 | 88 | #[account( 89 | mut 90 | )] 91 | pub asset_mint: Account<'info, Mint>, 92 | 93 | /// CHECK: We're checking owner of this account later 94 | #[account( 95 | mut 96 | )] 97 | pub oracle: UncheckedAccount<'info>, 98 | 99 | #[account()] 100 | pub system_program: Program<'info, System>, 101 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/boost_rewards.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::constants::*; 3 | use crate::states::*; 4 | use crate::errors::InsuranceFundError; 5 | 6 | #[derive(AnchorDeserialize, AnchorSerialize, Clone)] 7 | pub struct BoostRewardsArgs { 8 | pub lockup_id: u64, 9 | pub min_usd_value: u64, 10 | pub boost_bps: u64, 11 | } 12 | 13 | pub fn boost_rewards( 14 | ctx: Context, 15 | args: BoostRewardsArgs 16 | ) -> Result<()> { 17 | 18 | let reward_boost = &mut ctx.accounts.reward_boost; 19 | let BoostRewardsArgs { 20 | boost_bps, 21 | lockup_id, 22 | min_usd_value 23 | } = args; 24 | 25 | reward_boost.boost_bps = boost_bps; 26 | reward_boost.min_usd_value = min_usd_value; 27 | reward_boost.lockup = lockup_id; 28 | 29 | Ok(()) 30 | } 31 | 32 | #[derive(Accounts)] 33 | #[instruction( 34 | args: BoostRewardsArgs 35 | )] 36 | pub struct BoostRewards<'info> { 37 | #[account( 38 | mut 39 | )] 40 | pub signer: Signer<'info>, 41 | 42 | #[account( 43 | mut, 44 | seeds = [ 45 | ADMIN_SEED.as_bytes(), 46 | signer.key().as_ref() 47 | ], 48 | bump, 49 | constraint = admin.has_permissions(Permissions::AssetsAndLockups) 50 | )] 51 | pub admin: Account<'info, Admin>, 52 | 53 | #[account( 54 | mut, 55 | seeds = [ 56 | SETTINGS_SEED.as_bytes() 57 | ], 58 | bump, 59 | constraint = !settings.frozen @ InsuranceFundError::Frozen 60 | )] 61 | pub settings: Account<'info, Settings>, 62 | 63 | #[account( 64 | mut, 65 | seeds = [ 66 | LOCKUP_SEED.as_bytes(), 67 | &args.lockup_id.to_le_bytes() 68 | ], 69 | bump 70 | )] 71 | pub lockup: Account<'info, Lockup>, 72 | 73 | #[account( 74 | init, 75 | payer = signer, 76 | seeds = [ 77 | REWARD_BOOST_SEED.as_bytes(), 78 | &lockup.key().to_bytes(), 79 | &lockup.reward_boosts.to_le_bytes() 80 | ], 81 | bump, 82 | space = 8 + RewardBoost::INIT_SPACE 83 | )] 84 | pub reward_boost: Account<'info, RewardBoost>, 85 | 86 | #[account()] 87 | pub system_program: Program<'info, System>, 88 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/initialize_insurance_fund.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::states::*; 3 | use crate::constants::*; 4 | use crate::errors::InsuranceFundError; 5 | use crate::events::InitializeInsuranceFund as InitializeInsuranceFundEvent; 6 | 7 | #[derive(AnchorSerialize, AnchorDeserialize)] 8 | pub struct InitializeInsuranceFundArgs { 9 | pub cold_wallet: Pubkey, 10 | pub hot_wallet_share_bps: u64, 11 | pub cold_wallet_share_bps: u64, 12 | pub reward_mint: Pubkey, 13 | pub cooldown_duration: u64, 14 | } 15 | 16 | pub fn initialize_insurance_fund( 17 | ctx: Context, 18 | args: InitializeInsuranceFundArgs 19 | ) -> Result<()> { 20 | 21 | let InitializeInsuranceFundArgs { 22 | cold_wallet, 23 | cold_wallet_share_bps, 24 | hot_wallet_share_bps, 25 | reward_mint, 26 | cooldown_duration 27 | } = args; 28 | 29 | require!( 30 | cold_wallet_share_bps + hot_wallet_share_bps == 10_000, 31 | InsuranceFundError::ShareConfigOverflow 32 | ); 33 | 34 | let signer = &ctx.accounts.signer; 35 | let admin = &mut ctx.accounts.admin; 36 | 37 | admin.address = signer.key(); 38 | admin.permissions = Permissions::Superadmin; 39 | 40 | let settings = &mut ctx.accounts.settings; 41 | 42 | settings.bump = ctx.bumps.settings; 43 | settings.lockups = 0; 44 | settings.cooldown_duration = cooldown_duration; 45 | settings.cold_wallet = cold_wallet; 46 | settings.shares_config = SharesConfig { 47 | cold_wallet_share_bps, 48 | hot_wallet_share_bps 49 | }; 50 | settings.reward_config = RewardConfig { 51 | main: reward_mint 52 | }; 53 | settings.frozen = false; 54 | settings.superadmins = 1; 55 | settings.debt_records = 0; 56 | 57 | emit!(InitializeInsuranceFundEvent { 58 | new_admin: signer.key() 59 | }); 60 | 61 | Ok(()) 62 | } 63 | 64 | #[derive(Accounts)] 65 | pub struct InitializeInsuranceFund<'info> { 66 | #[account( 67 | mut 68 | )] 69 | pub signer: Signer<'info>, 70 | 71 | #[account( 72 | init, 73 | payer = signer, 74 | seeds = [ 75 | ADMIN_SEED.as_bytes(), 76 | signer.key().as_ref() 77 | ], 78 | bump, 79 | space = 8 + Admin::INIT_SPACE 80 | )] 81 | pub admin: Account<'info, Admin>, 82 | 83 | #[account( 84 | init, 85 | seeds = [ 86 | SETTINGS_SEED.as_bytes() 87 | ], 88 | bump, 89 | payer = signer, 90 | space = 8 + Settings::INIT_SPACE, 91 | )] 92 | pub settings: Account<'info, Settings>, 93 | 94 | #[account()] 95 | pub system_program: Program<'info, System> 96 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/manage_freeze.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::constants::*; 3 | use crate::states::*; 4 | use crate::events::ManageFreezeEvent; 5 | use crate::errors::InsuranceFundError; 6 | 7 | #[derive(AnchorSerialize, AnchorDeserialize)] 8 | pub struct ManageFreezeArgs { 9 | pub freeze: bool 10 | } 11 | 12 | pub fn manage_freeze( 13 | ctx: Context, 14 | args: ManageFreezeArgs 15 | ) -> Result<()> { 16 | 17 | let settings = &mut ctx.accounts.settings; 18 | let signer = &ctx.accounts.signer; 19 | 20 | match args.freeze { 21 | true => settings.freeze(), 22 | false => settings.unfreeze(), 23 | } 24 | 25 | emit!(ManageFreezeEvent { 26 | admin: signer.key(), 27 | frozen: args.freeze 28 | }); 29 | 30 | Ok(()) 31 | } 32 | 33 | #[derive(Accounts)] 34 | pub struct ManageFreeze<'info> { 35 | #[account( 36 | mut, 37 | )] 38 | pub signer: Signer<'info>, 39 | 40 | #[account( 41 | mut, 42 | seeds = [ 43 | ADMIN_SEED.as_bytes(), 44 | signer.key().as_ref(), 45 | ], 46 | bump, 47 | constraint = admin.has_permissions(Permissions::Freeze) @ InsuranceFundError::InvalidSigner, 48 | )] 49 | pub admin: Account<'info, Admin>, 50 | 51 | #[account( 52 | mut, 53 | seeds = [ 54 | SETTINGS_SEED.as_bytes() 55 | ], 56 | bump, 57 | )] 58 | pub settings: Account<'info, Settings>, 59 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod add_asset; 2 | pub use add_asset::*; 3 | 4 | pub mod initialize_insurance_fund; 5 | pub use initialize_insurance_fund::*; 6 | 7 | pub mod initialize_lockup; 8 | pub use initialize_lockup::*; 9 | 10 | pub mod initialize_lockup_vaults; 11 | pub use initialize_lockup_vaults::*; 12 | 13 | pub mod boost_rewards; 14 | pub use boost_rewards::*; 15 | 16 | pub mod manage_freeze; 17 | pub use manage_freeze::*; 18 | 19 | pub mod add_admin; 20 | pub use add_admin::*; 21 | 22 | pub mod remove_admin; 23 | pub use remove_admin::*; 24 | 25 | pub mod update_deposit_cap; 26 | pub use update_deposit_cap::*; 27 | 28 | pub mod rebalance; 29 | pub use rebalance::*; 30 | 31 | pub mod initialize_lp; 32 | pub use initialize_lp::*; 33 | 34 | pub mod initialize_lp_lockup; 35 | pub use initialize_lp_lockup::*; 36 | -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/remove_admin.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::states::*; 3 | use crate::constants::*; 4 | use crate::events::*; 5 | use crate::errors::InsuranceFundError; 6 | 7 | #[derive(AnchorSerialize, AnchorDeserialize)] 8 | pub struct RemoveAdminArgs { 9 | address: Pubkey, 10 | } 11 | 12 | pub fn remove_admin( 13 | ctx: Context, 14 | args: RemoveAdminArgs 15 | ) -> Result<()> { 16 | let signer = &ctx.accounts.signer; 17 | 18 | ctx.accounts.verify_removal()?; 19 | 20 | emit!(ChangeAdminEvent { 21 | affected_admin: args.address, 22 | signer: signer.key(), 23 | permission_change: None 24 | }); 25 | 26 | Ok(()) 27 | } 28 | 29 | #[derive(Accounts)] 30 | #[instruction(args: RemoveAdminArgs)] 31 | pub struct RemoveAdmin<'info> { 32 | #[account( 33 | mut 34 | )] 35 | pub signer: Signer<'info>, 36 | 37 | #[account( 38 | mut, 39 | seeds = [ 40 | ADMIN_SEED.as_bytes(), 41 | signer.key().as_ref() 42 | ], 43 | bump, 44 | )] 45 | pub admin: Account<'info, Admin>, 46 | 47 | #[account( 48 | mut, 49 | seeds = [ 50 | ADMIN_SEED.as_bytes(), 51 | &args.address.as_ref(), 52 | ], 53 | bump, 54 | close = signer, 55 | )] 56 | pub admin_to_remove: Account<'info, Admin>, 57 | 58 | #[account( 59 | mut, 60 | seeds = [ 61 | SETTINGS_SEED.as_bytes() 62 | ], 63 | bump, 64 | constraint = !settings.frozen @ InsuranceFundError::Frozen 65 | )] 66 | pub settings: Account<'info, Settings>, 67 | 68 | #[account()] 69 | pub system_program: Program<'info, System>, 70 | } 71 | 72 | impl RemoveAdmin<'_> { 73 | 74 | pub fn verify_removal(&self) -> Result<()> { 75 | require!( 76 | self.admin.key() == self.admin_to_remove.key() || 77 | self.admin.has_permissions_over(self.admin_to_remove.permissions), 78 | InsuranceFundError::PermissionsTooLow 79 | ); 80 | 81 | match self.admin_to_remove.permissions { 82 | Permissions::Superadmin => { 83 | require!( 84 | self.settings.superadmins > 1, 85 | InsuranceFundError::MinimumSuperadminsRequired 86 | ); 87 | }, 88 | _ => {} 89 | }; 90 | 91 | Ok(()) 92 | } 93 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/admin/update_deposit_cap.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::states::*; 3 | use crate::constants::*; 4 | use crate::errors::InsuranceFundError; 5 | 6 | #[derive(AnchorDeserialize, AnchorSerialize)] 7 | pub struct UpdateDepositCapArgs { 8 | pub lockup_id: u64, 9 | pub new_cap: Option 10 | } 11 | 12 | pub fn update_deposit_cap( 13 | ctx: Context, 14 | args: UpdateDepositCapArgs 15 | ) -> Result<()> { 16 | let UpdateDepositCapArgs { 17 | lockup_id: _, 18 | new_cap 19 | } = args; 20 | 21 | let lockup = &mut ctx.accounts.lockup; 22 | lockup.deposit_cap = new_cap; 23 | 24 | Ok(()) 25 | } 26 | 27 | #[derive(Accounts)] 28 | #[instruction(args: UpdateDepositCapArgs)] 29 | pub struct UpdateDepositCap<'info> { 30 | #[account( 31 | mut, 32 | )] 33 | pub signer: Signer<'info>, 34 | 35 | #[account( 36 | mut, 37 | seeds = [ 38 | ADMIN_SEED.as_bytes(), 39 | signer.key().as_ref() 40 | ], 41 | bump, 42 | constraint = admin.has_permissions(Permissions::AssetsAndLockups) @ InsuranceFundError::InvalidSigner, 43 | )] 44 | pub admin: Account<'info, Admin>, 45 | 46 | #[account( 47 | mut, 48 | seeds = [ 49 | SETTINGS_SEED.as_bytes() 50 | ], 51 | bump, 52 | constraint = !settings.frozen @ InsuranceFundError::Frozen 53 | )] 54 | pub settings: Account<'info, Settings>, 55 | 56 | #[account( 57 | mut, 58 | seeds = [ 59 | LOCKUP_SEED.as_bytes(), 60 | &args.lockup_id.to_le_bytes() 61 | ], 62 | bump 63 | )] 64 | pub lockup: Account<'info, Lockup>, 65 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/cpi/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod get_user_balance_and_reward; 2 | pub use get_user_balance_and_reward::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/crank/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod deposit_rewards; 2 | pub use deposit_rewards::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod slash; 2 | pub use slash::*; 3 | 4 | pub mod admin; 5 | pub use admin::*; 6 | 7 | pub mod user; 8 | pub use user::*; 9 | 10 | pub mod crank; 11 | pub use crank::*; 12 | 13 | pub mod cpi; 14 | pub use cpi::*; 15 | 16 | pub mod swap; 17 | pub use swap::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/slash/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod slash; 2 | pub use slash::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/swap/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod swap; 2 | pub use swap::*; 3 | 4 | pub mod borrow; 5 | pub use borrow::*; 6 | 7 | pub mod repay; 8 | pub use repay::*; 9 | 10 | pub mod swap_lp; 11 | pub use swap_lp::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/swap/repay.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use anchor_spl::token::{Mint, TokenAccount, Token}; 3 | use crate::states::*; 4 | use crate::constants::*; 5 | 6 | #[derive(AnchorDeserialize, AnchorSerialize)] 7 | pub struct RepayArgs { 8 | pub debt_record_id: u64 9 | } 10 | 11 | pub fn repay( 12 | ctx: Context, 13 | args: RepayArgs 14 | ) -> Result<()> { 15 | let signer = &ctx.accounts.signer; 16 | let reflect_token_account = &ctx.accounts.reflect_token_account; 17 | let lockup = &ctx.accounts.lockup; 18 | let debt_record = &ctx.accounts.debt_record; 19 | let token_program = &ctx.accounts.token_program; 20 | let lockup_hot_vault = &ctx.accounts.lockup_hot_vault; 21 | 22 | lockup.deposit_hot_wallet( 23 | debt_record.amount, 24 | signer, 25 | reflect_token_account, 26 | lockup_hot_vault, 27 | token_program 28 | )?; 29 | 30 | Ok(()) 31 | } 32 | 33 | #[derive(Accounts)] 34 | #[instruction( 35 | args: RepayArgs 36 | )] 37 | pub struct Repay<'info> { 38 | #[account()] 39 | pub signer: Signer<'info>, 40 | 41 | #[account( 42 | mut, 43 | close = signer, 44 | seeds = [ 45 | DEBT_RECORD_SEED.as_bytes(), 46 | &args.debt_record_id.to_le_bytes() 47 | ], 48 | bump 49 | )] 50 | pub debt_record: Account<'info, DebtRecord>, 51 | 52 | #[account( 53 | seeds = [ 54 | LOCKUP_SEED.as_bytes(), 55 | &debt_record.lockup.to_le_bytes() 56 | ], 57 | bump 58 | )] 59 | pub lockup: Account<'info, Lockup>, 60 | 61 | #[account( 62 | constraint = asset.mint == asset_mint.key() 63 | )] 64 | pub asset: Account<'info, Asset>, 65 | 66 | #[account( 67 | address = lockup.asset_mint 68 | )] 69 | pub asset_mint: Account<'info, Mint>, 70 | 71 | #[account( 72 | mut, 73 | seeds = [ 74 | HOT_VAULT_SEED.as_bytes(), 75 | lockup.key().as_ref(), 76 | asset_mint.key().as_ref(), 77 | ], 78 | bump 79 | )] 80 | pub lockup_hot_vault: Account<'info, TokenAccount>, 81 | 82 | #[account( 83 | mut, 84 | token::mint = asset_mint, 85 | token::authority = signer 86 | )] 87 | pub reflect_token_account: Account<'info, TokenAccount>, 88 | 89 | #[account()] 90 | pub token_program: Program<'info, Token>, 91 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/instructions/user/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod restake; 2 | pub use restake::*; 3 | 4 | pub mod request_withdraw; 5 | pub use request_withdraw::*; 6 | 7 | pub mod withdraw; 8 | pub use withdraw::*; 9 | 10 | pub mod process_intent; 11 | pub use process_intent::*; 12 | 13 | pub mod deposit_and_lock_lp; 14 | pub use deposit_and_lock_lp::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/admin.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, PartialEq, PartialOrd, InitSpace)] 4 | pub enum Permissions { 5 | // Only gives ability to freeze the protocol. 6 | // This should be used for team members' wallets who can easily execute freeze of the protocol in case of emergency. 7 | Freeze = 0, 8 | // Gives ability to whitelist new assets for restaking. 9 | AssetsAndLockups = 1, 10 | // Gives ability to whitelist new assets for restaking. 11 | Slashing = 2, 12 | // Gives full authority over the program management, including removing and adding new admins of a lower scopes. 13 | Superadmin = 3 14 | } 15 | 16 | #[account] 17 | #[derive(InitSpace)] 18 | pub struct Admin { 19 | pub address: Pubkey, 20 | pub permissions: Permissions 21 | } 22 | 23 | impl Admin { 24 | pub fn has_permissions(&self, activity: Permissions) -> bool { 25 | self.permissions >= activity 26 | } 27 | 28 | pub fn has_permissions_over(&self, activity: Permissions) -> bool { 29 | match self.permissions { 30 | // Every superadmin has permissions over all other admins, including superadmins. 31 | Permissions::Superadmin => true, 32 | _ => self.permissions > activity 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/asset.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::helpers::{ 3 | get_price_from_pyth, 4 | get_price_from_switchboard, OraclePrice 5 | }; 6 | use crate::errors::InsuranceFundError; 7 | 8 | #[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, PartialEq, Debug, InitSpace)] 9 | pub enum Oracle { 10 | Pyth(Pubkey), 11 | Switchboard(Pubkey) 12 | } 13 | 14 | impl Oracle { 15 | pub const SIZE: usize = 1 + 32; 16 | 17 | pub fn key(&self) -> &Pubkey { 18 | match self { 19 | Oracle::Pyth(key) | Oracle::Switchboard(key) => key, 20 | } 21 | } 22 | } 23 | 24 | #[account] 25 | #[derive(InitSpace)] 26 | pub struct Asset { 27 | pub mint: Pubkey, 28 | pub oracle: Oracle, 29 | // For stats 30 | pub tvl: u64, 31 | pub lockups: u64, 32 | pub deposits: u64, 33 | } 34 | 35 | impl Asset { 36 | #[inline(never)] 37 | pub fn increase_tvl( 38 | &mut self, 39 | amount: u64 40 | ) -> Result<()> { 41 | self.tvl = self.tvl.checked_add(amount) 42 | .ok_or(InsuranceFundError::MathOverflow)?; 43 | 44 | Ok(()) 45 | } 46 | 47 | #[inline(never)] 48 | pub fn decrease_tvl( 49 | &mut self, 50 | amount: u64 51 | ) -> Result<()> { 52 | self.tvl = self.tvl 53 | .checked_sub(amount) 54 | .ok_or(InsuranceFundError::MathOverflow)?; 55 | 56 | Ok(()) 57 | } 58 | 59 | #[inline(never)] 60 | pub fn get_price( 61 | &self, 62 | account: &AccountInfo, 63 | clock: &Clock 64 | ) -> Result { 65 | match self.oracle { 66 | Oracle::Pyth(_) => get_price_from_pyth(account, clock), 67 | Oracle::Switchboard(_) => get_price_from_switchboard(account, clock) 68 | } 69 | } 70 | 71 | #[inline(never)] 72 | pub fn add_lockup( 73 | &mut self, 74 | ) -> Result<()> { 75 | self.lockups = self.lockups 76 | .checked_add(1) 77 | .ok_or(InsuranceFundError::MathOverflow)?; 78 | 79 | Ok(()) 80 | } 81 | 82 | #[inline(never)] 83 | pub fn add_deposit( 84 | &mut self, 85 | ) -> Result<()> { 86 | self.deposits = self.lockups 87 | .checked_add(1) 88 | .ok_or(InsuranceFundError::MathOverflow)?; 89 | 90 | Ok(()) 91 | } 92 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/cooldown.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[derive(InitSpace)] 4 | #[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy)] 5 | pub enum CooldownRewards { 6 | Single(u64), 7 | Dual([u64; 2]) 8 | } 9 | 10 | impl CooldownRewards { 11 | pub const SIZE: usize = 1 + (2 * 8); 12 | } 13 | 14 | #[derive(InitSpace)] 15 | #[account] 16 | pub struct Cooldown { 17 | pub user: Pubkey, 18 | pub deposit_id: u64, 19 | pub lockup_id: u64, 20 | pub receipt_amount: u64, 21 | pub unlock_ts: u64, 22 | pub rewards: CooldownRewards, 23 | } 24 | 25 | impl Cooldown { 26 | pub fn is_cooled(&self) -> Result { 27 | let clock = Clock::get()?; 28 | Ok(clock.unix_timestamp as u64 >= self.unlock_ts) 29 | } 30 | 31 | pub fn lock(&mut self, duration: u64) -> Result<()> { 32 | let clock = Clock::get()?; 33 | 34 | let now = clock.unix_timestamp; 35 | self.unlock_ts = (now as u64) + duration; 36 | 37 | Ok(()) 38 | } 39 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/debt_record.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[account] 4 | #[derive(InitSpace)] 5 | pub struct DebtRecord { 6 | pub amount: u64, 7 | pub asset: Pubkey, 8 | pub lockup: u64, 9 | pub timestamp: u64, 10 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/intent.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[account] 4 | #[derive(InitSpace)] 5 | pub struct Intent { 6 | pub amount: u64, 7 | pub lockup: Pubkey, 8 | pub deposit: Pubkey, 9 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/lp/lp_lockup.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::constants::*; 3 | use anchor_spl::token::{mint_to, Mint, MintTo, Token, TokenAccount}; 4 | 5 | #[derive(InitSpace)] 6 | #[account] 7 | pub struct LpLockup { 8 | pub bump: u8, 9 | pub duration: u64, 10 | pub deposits: u64, 11 | // pub lp_token: u64, // not essential 12 | pub receipt_token: Pubkey, 13 | pub liquidity_pool: Pubkey, 14 | } 15 | 16 | impl LpLockup { 17 | pub fn mint_receipt_tokens<'info>( 18 | &self, 19 | receipt_token: &Account<'info, Mint>, 20 | receipt_token_deposit_account: &AccountInfo<'info>, 21 | lp_lockup: &Account<'info, LpLockup>, 22 | token_program: &Program<'info, Token>, 23 | amount: u64 24 | ) -> Result<()> { 25 | let signer_seeds = &[ 26 | LIQUIDITY_POOL_LOCKUP_SEED.as_bytes(), 27 | self.liquidity_pool.as_ref(), 28 | &self.duration.to_le_bytes(), 29 | &[self.bump] 30 | ]; 31 | 32 | mint_to( 33 | CpiContext::new_with_signer( 34 | token_program.to_account_info(), 35 | MintTo { 36 | mint: receipt_token.to_account_info(), 37 | to: receipt_token_deposit_account.to_account_info(), 38 | authority: lp_lockup.to_account_info() 39 | }, 40 | &[signer_seeds] 41 | ), 42 | amount 43 | )?; 44 | 45 | Ok(()) 46 | } 47 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/lp/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod liquidity_pool; 2 | pub use liquidity_pool::*; 3 | 4 | pub mod lp_lockup; 5 | pub use lp_lockup::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod settings; 2 | pub use settings::*; 3 | 4 | pub mod lockup; 5 | pub use lockup::*; 6 | 7 | pub mod deposit; 8 | pub use deposit::*; 9 | 10 | pub mod asset; 11 | pub use asset::*; 12 | 13 | pub mod reward_boost; 14 | pub use reward_boost::*; 15 | 16 | pub mod intent; 17 | pub use intent::*; 18 | 19 | pub mod cooldown; 20 | pub use cooldown::*; 21 | 22 | pub mod admin; 23 | pub use admin::*; 24 | 25 | pub mod debt_record; 26 | pub use debt_record::*; 27 | 28 | pub mod lp; 29 | pub use lp::*; -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/reward_boost.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::errors::InsuranceFundError; 3 | 4 | #[account] 5 | #[derive(InitSpace)] 6 | pub struct RewardBoost { 7 | pub index: u64, 8 | // Minimum USD value of the deposit to be included in the tier. 9 | pub min_usd_value: u64, 10 | // % of the $R rewards in basepoints 11 | pub boost_bps: u64, 12 | // Which lockup does this boost apply to. 13 | pub lockup: u64, 14 | } 15 | 16 | impl RewardBoost { 17 | pub fn validate( 18 | &self, 19 | amount: u64 20 | ) -> Result<()> { 21 | require!( 22 | amount >= self.min_usd_value, 23 | InsuranceFundError::BoostNotApplied 24 | ); 25 | 26 | Ok(()) 27 | } 28 | } -------------------------------------------------------------------------------- /insurance-fund/programs/insurance-fund/src/states/settings.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::errors::InsuranceFundError; 3 | 4 | #[derive(AnchorDeserialize, AnchorSerialize, Clone, Copy, PartialEq, InitSpace)] 5 | pub struct SharesConfig { 6 | pub hot_wallet_share_bps: u64, 7 | pub cold_wallet_share_bps: u64 8 | } 9 | 10 | impl SharesConfig { 11 | pub const SIZE: usize = 2 * 8; 12 | } 13 | 14 | #[derive(AnchorDeserialize, AnchorSerialize, Clone, Copy, PartialEq, InitSpace)] 15 | pub struct RewardConfig { 16 | pub main: Pubkey, 17 | } 18 | 19 | impl RewardConfig { 20 | pub const SIZE: usize = 32; 21 | } 22 | 23 | #[account] 24 | #[derive(InitSpace)] 25 | pub struct Settings { 26 | pub bump: u8, 27 | pub superadmins: u8, 28 | pub cold_wallet: Pubkey, 29 | pub lockups: u64, 30 | pub cooldown_duration: u64, 31 | pub shares_config: SharesConfig, 32 | pub reward_config: RewardConfig, 33 | pub frozen: bool, 34 | pub debt_records: u64, 35 | } 36 | 37 | impl Settings { 38 | pub fn freeze(&mut self) { 39 | self.frozen = true; 40 | } 41 | 42 | pub fn unfreeze(&mut self) { 43 | self.frozen = false; 44 | } 45 | 46 | pub fn calculate_cold_wallet_deposit( 47 | &self, 48 | amount: u64 49 | ) -> Result { 50 | let result = amount 51 | .checked_mul(self.shares_config.cold_wallet_share_bps) 52 | .ok_or(InsuranceFundError::MathOverflow)? 53 | .checked_div(10_000) 54 | .ok_or(InsuranceFundError::MathOverflow)?; 55 | 56 | Ok(result) 57 | } 58 | 59 | pub fn calculate_hot_wallet_deposit( 60 | &self, 61 | amount: u64 62 | ) -> Result { 63 | let result = amount 64 | .checked_mul(self.shares_config.hot_wallet_share_bps) 65 | .ok_or(InsuranceFundError::MathOverflow)? 66 | .checked_div(10_000) 67 | .ok_or(InsuranceFundError::MathOverflow)?; 68 | 69 | Ok(result) 70 | } 71 | } -------------------------------------------------------------------------------- /insurance-fund/scripts/helpers/createToken.ts: -------------------------------------------------------------------------------- 1 | import {Connection, Keypair, SystemProgram, Transaction} from "@solana/web3.js"; 2 | import {AnchorProvider} from "@coral-xyz/anchor"; 3 | import {createInitializeMintInstruction, MINT_SIZE, TOKEN_PROGRAM_ID} from "@solana/spl-token"; 4 | 5 | async function createToken( 6 | connection: Connection, 7 | payer: AnchorProvider 8 | ) { 9 | const keypair = Keypair.generate(); 10 | 11 | const lamports = await connection.getMinimumBalanceForRentExemption(MINT_SIZE); 12 | const createAccountIx = SystemProgram.createAccount({ 13 | newAccountPubkey: keypair.publicKey, 14 | fromPubkey: payer.publicKey, 15 | lamports, 16 | programId: TOKEN_PROGRAM_ID, 17 | space: MINT_SIZE 18 | }); 19 | 20 | const ix = createInitializeMintInstruction( 21 | keypair.publicKey, 22 | 9, 23 | payer.publicKey, 24 | payer.publicKey 25 | ); 26 | 27 | const tx = new Transaction(); 28 | tx.add(createAccountIx, ix); 29 | 30 | const { 31 | lastValidBlockHeight, 32 | blockhash 33 | } = await connection.getLatestBlockhash(); 34 | 35 | tx.feePayer = payer.publicKey; 36 | tx.recentBlockhash = blockhash; 37 | 38 | tx.partialSign(keypair); 39 | const signed = await payer.wallet.signTransaction(tx); 40 | 41 | const sent = await connection.sendRawTransaction(signed.serialize()); 42 | await connection.confirmTransaction({ 43 | blockhash, 44 | lastValidBlockHeight, 45 | signature: sent 46 | }, "confirmed"); 47 | 48 | return keypair.publicKey; 49 | } 50 | 51 | export default createToken; -------------------------------------------------------------------------------- /insurance-fund/scripts/helpers/debugLogs.ts: -------------------------------------------------------------------------------- 1 | import {Connection} from "@solana/web3.js"; 2 | 3 | export default async function debugLogs( 4 | connection: Connection, 5 | signature: string, 6 | ) { 7 | 8 | const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(); 9 | await connection.confirmTransaction({ 10 | blockhash, 11 | lastValidBlockHeight, 12 | signature 13 | }, "confirmed"); 14 | 15 | const { 16 | meta: { 17 | logMessages, 18 | err 19 | } 20 | } = await connection.getParsedTransaction( 21 | signature, 22 | "confirmed" 23 | ); 24 | 25 | return logMessages; 26 | } -------------------------------------------------------------------------------- /insurance-fund/scripts/helpers/getOraclePrice.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import BN from "bn.js"; 3 | 4 | type Response = { 5 | id: "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d", 6 | price: { 7 | price: `${number}`, 8 | conf: `${number}`, 9 | expo: number, 10 | publish_time: number 11 | }, 12 | ema_price: { 13 | price: `${number}`, 14 | conf: `${number}`, 15 | expo: number, 16 | publish_time: number 17 | } 18 | }[] 19 | 20 | export default async function getOraclePrice() { 21 | const { 22 | data 23 | } = await axios.get("https://hermes.pyth.network/api/latest_price_feeds?ids[]=ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"); 24 | 25 | const { 26 | price: { 27 | price, 28 | expo 29 | } 30 | } = data[0]; 31 | 32 | return { 33 | price: new BN(price), 34 | precision: new BN(expo).abs() 35 | } 36 | } -------------------------------------------------------------------------------- /insurance-fund/scripts/helpers/mintTokens.ts: -------------------------------------------------------------------------------- 1 | import {Connection, Keypair, PublicKey, Transaction} from "@solana/web3.js"; 2 | import { 3 | createAssociatedTokenAccountIdempotentInstruction, 4 | createMintToInstruction, 5 | getAssociatedTokenAddressSync 6 | } from "@solana/spl-token"; 7 | 8 | export default async function mintTokens( 9 | mint: PublicKey, 10 | payer: Keypair, 11 | connection: Connection, 12 | amount: number, 13 | recipient?: PublicKey 14 | ) { 15 | 16 | const ata = getAssociatedTokenAddressSync( 17 | mint, 18 | recipient || payer.publicKey, 19 | true 20 | ); 21 | 22 | const ataIx = createAssociatedTokenAccountIdempotentInstruction( 23 | payer.publicKey, 24 | ata, 25 | recipient || payer.publicKey, 26 | mint, 27 | ); 28 | 29 | const ix = createMintToInstruction( 30 | mint, 31 | ata, 32 | payer.publicKey, 33 | amount, 34 | ); 35 | 36 | const tx = new Transaction(); 37 | tx.add(ataIx, ix); 38 | 39 | const { 40 | lastValidBlockHeight, 41 | blockhash 42 | } = await connection.getLatestBlockhash(); 43 | 44 | tx.feePayer = payer.publicKey; 45 | tx.recentBlockhash = blockhash; 46 | tx.sign(payer); 47 | 48 | const sent = await connection.sendRawTransaction(tx.serialize()); 49 | await connection.confirmTransaction({ 50 | blockhash, 51 | lastValidBlockHeight, 52 | signature: sent 53 | }, "confirmed"); 54 | } -------------------------------------------------------------------------------- /insurance-fund/scripts/helpers/signAndSendTransaction.ts: -------------------------------------------------------------------------------- 1 | import {Connection, Keypair, MessageV0, TransactionMessage, VersionedTransaction} from "@solana/web3.js"; 2 | import {AnchorProvider} from "@coral-xyz/anchor"; 3 | 4 | export default async function signAndSendTransaction( 5 | message: MessageV0, 6 | connection: Connection, 7 | skipPreflight?: boolean, 8 | signers?: Keypair[] 9 | ) { 10 | const { 11 | lastValidBlockHeight, 12 | blockhash 13 | } = await connection.getLatestBlockhash(); 14 | 15 | const transaction = new VersionedTransaction(message); 16 | 17 | if (signers && signers.length) transaction.sign(signers); 18 | 19 | const txid = await connection.sendRawTransaction( 20 | transaction.serialize(), 21 | { skipPreflight } 22 | ); 23 | 24 | await connection.confirmTransaction({ 25 | lastValidBlockHeight, 26 | blockhash, 27 | signature: txid 28 | }, "confirmed"); 29 | // 30 | // const { 31 | // meta: { 32 | // err, 33 | // logMessages 34 | // } 35 | // } = await provider.connection.getParsedTransaction(txid, "confirmed"); 36 | // 37 | // console.log({ 38 | // logMessages, 39 | // err 40 | // }); 41 | // 42 | // if (err) throw err; 43 | 44 | return txid; 45 | } -------------------------------------------------------------------------------- /insurance-fund/scripts/helpers/sleep.ts: -------------------------------------------------------------------------------- 1 | export default function sleep(s: number) { 2 | return new Promise((resolve) => setTimeout(resolve, s * 1000)); 3 | } -------------------------------------------------------------------------------- /insurance-fund/sdk/.gitignore: -------------------------------------------------------------------------------- 1 | ./dist 2 | package-lock.json 3 | yarn.lock 4 | ./src/setup -------------------------------------------------------------------------------- /insurance-fund/sdk/.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .env 3 | yarn.lock 4 | ./src 5 | package-lock.json 6 | ./src/setup -------------------------------------------------------------------------------- /insurance-fund/sdk/dist/generated/instructions/initializeLockupVaults.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category InitializeLockupVaults 12 | * @category generated 13 | */ 14 | export type InitializeLockupVaultsInstructionArgs = { 15 | lockupId: beet.bignum; 16 | }; 17 | /** 18 | * @category Instructions 19 | * @category InitializeLockupVaults 20 | * @category generated 21 | */ 22 | export declare const initializeLockupVaultsStruct: beet.BeetArgsStruct; 25 | /** 26 | * Accounts required by the _initializeLockupVaults_ instruction 27 | * 28 | * @property [_writable_, **signer**] signer 29 | * @property [_writable_] admin 30 | * @property [_writable_] settings 31 | * @property [_writable_] lockup 32 | * @property [_writable_] assetMint 33 | * @property [_writable_] lockupColdVault 34 | * @property [_writable_] lockupHotVault 35 | * @property [] rewardMint 36 | * @property [_writable_] assetRewardPool 37 | * @category Instructions 38 | * @category InitializeLockupVaults 39 | * @category generated 40 | */ 41 | export type InitializeLockupVaultsInstructionAccounts = { 42 | signer: web3.PublicKey; 43 | admin: web3.PublicKey; 44 | settings: web3.PublicKey; 45 | lockup: web3.PublicKey; 46 | assetMint: web3.PublicKey; 47 | lockupColdVault: web3.PublicKey; 48 | lockupHotVault: web3.PublicKey; 49 | rewardMint: web3.PublicKey; 50 | assetRewardPool: web3.PublicKey; 51 | tokenProgram?: web3.PublicKey; 52 | systemProgram?: web3.PublicKey; 53 | anchorRemainingAccounts?: web3.AccountMeta[]; 54 | }; 55 | export declare const initializeLockupVaultsInstructionDiscriminator: number[]; 56 | /** 57 | * Creates a _InitializeLockupVaults_ instruction. 58 | * 59 | * @param accounts that will be accessed while the instruction is processed 60 | * @param args to provide as instruction data to the program 61 | * 62 | * @category Instructions 63 | * @category InitializeLockupVaults 64 | * @category generated 65 | */ 66 | export declare function createInitializeLockupVaultsInstruction(accounts: InitializeLockupVaultsInstructionAccounts, args: InitializeLockupVaultsInstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction; 67 | -------------------------------------------------------------------------------- /insurance-fund/sdk/dist/generated/types/GetUserBalanceAndRewardArgs.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | export type GetUserBalanceAndRewardArgs = { 9 | lockupId: beet.bignum; 10 | depositId: beet.bignum; 11 | rewardBoostId: beet.COption; 12 | receiptTokens: beet.bignum; 13 | }; 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export declare const getUserBalanceAndRewardArgsBeet: beet.FixableBeetArgsStruct; 19 | -------------------------------------------------------------------------------- /insurance-fund/sdk/dist/generated/types/GetUserBalanceAndRewardArgs.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * This code was GENERATED using the solita package. 4 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 5 | * 6 | * See: https://github.com/metaplex-foundation/solita 7 | */ 8 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 9 | if (k2 === undefined) k2 = k; 10 | var desc = Object.getOwnPropertyDescriptor(m, k); 11 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 12 | desc = { enumerable: true, get: function() { return m[k]; } }; 13 | } 14 | Object.defineProperty(o, k2, desc); 15 | }) : (function(o, m, k, k2) { 16 | if (k2 === undefined) k2 = k; 17 | o[k2] = m[k]; 18 | })); 19 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 20 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 21 | }) : function(o, v) { 22 | o["default"] = v; 23 | }); 24 | var __importStar = (this && this.__importStar) || function (mod) { 25 | if (mod && mod.__esModule) return mod; 26 | var result = {}; 27 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 28 | __setModuleDefault(result, mod); 29 | return result; 30 | }; 31 | Object.defineProperty(exports, "__esModule", { value: true }); 32 | exports.getUserBalanceAndRewardArgsBeet = void 0; 33 | const beet = __importStar(require("@metaplex-foundation/beet")); 34 | /** 35 | * @category userTypes 36 | * @category generated 37 | */ 38 | exports.getUserBalanceAndRewardArgsBeet = new beet.FixableBeetArgsStruct([ 39 | ['lockupId', beet.u64], 40 | ['depositId', beet.u64], 41 | ['rewardBoostId', beet.coption(beet.u64)], 42 | ['receiptTokens', beet.u64], 43 | ], 'GetUserBalanceAndRewardArgs'); 44 | -------------------------------------------------------------------------------- /insurance-fund/sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reflectcx/restaking", 3 | "version": "2.0.2", 4 | "author": "zkchakra @ Palindrome Engineering", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/palindrome-eng/reflect-program-library.git" 8 | }, 9 | "dependencies": { 10 | "@metaplex-foundation/beet": "0.7.2", 11 | "@metaplex-foundation/beet-solana": "^0.4.1", 12 | "@metaplex-foundation/mpl-token-metadata": "2", 13 | "@solana/spl-token": "^0.4.8", 14 | "@solana/web3.js": "1.68.0", 15 | "bn.js": "5.2.1" 16 | }, 17 | "devDependencies": { 18 | "@types/bn.js": "5.1.6", 19 | "@types/chai": "^5.0.1", 20 | "@types/mocha": "^10.0.10", 21 | "bs58": "^6.0.0", 22 | "chai": "^5.1.2", 23 | "mocha": "^11.0.1" 24 | }, 25 | "license": "MIT", 26 | "main": "./src/index.js", 27 | "module": "./dist/index.js", 28 | "types": "./dist/index.d.ts", 29 | "files": [ 30 | "/dist" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/classes/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Restaking"; -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/accounts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Admin' 2 | export * from './Asset' 3 | export * from './Cooldown' 4 | export * from './DebtRecord' 5 | export * from './Deposit' 6 | export * from './Intent' 7 | export * from './LiquidityPool' 8 | export * from './Lockup' 9 | export * from './LpLockup' 10 | export * from './RewardBoost' 11 | export * from './Settings' 12 | 13 | import { Admin } from './Admin' 14 | import { Asset } from './Asset' 15 | import { Cooldown } from './Cooldown' 16 | import { DebtRecord } from './DebtRecord' 17 | import { Deposit } from './Deposit' 18 | import { Intent } from './Intent' 19 | import { Lockup } from './Lockup' 20 | import { LiquidityPool } from './LiquidityPool' 21 | import { LpLockup } from './LpLockup' 22 | import { RewardBoost } from './RewardBoost' 23 | import { Settings } from './Settings' 24 | 25 | export const accountProviders = { 26 | Admin, 27 | Asset, 28 | Cooldown, 29 | DebtRecord, 30 | Deposit, 31 | Intent, 32 | Lockup, 33 | LiquidityPool, 34 | LpLockup, 35 | RewardBoost, 36 | Settings, 37 | } 38 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/index.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js' 2 | export * from './accounts' 3 | export * from './errors' 4 | export * from './instructions' 5 | export * from './types' 6 | 7 | /** 8 | * Program address 9 | * 10 | * @category constants 11 | * @category generated 12 | */ 13 | export const PROGRAM_ADDRESS = 'rhLMe6vyM1wVLJaxrWUckVmPxSia58nSWZRDtYQow6D' 14 | 15 | /** 16 | * Program public key 17 | * 18 | * @category constants 19 | * @category generated 20 | */ 21 | export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS) 22 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/instructions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './addAdmin' 2 | export * from './addAsset' 3 | export * from './boostRewards' 4 | export * from './borrow' 5 | export * from './depositAndLockLp' 6 | export * from './depositRewards' 7 | export * from './getUserBalanceAndReward' 8 | export * from './initializeInsuranceFund' 9 | export * from './initializeLockup' 10 | export * from './initializeLockupVaults' 11 | export * from './initializeLp' 12 | export * from './initializeLpLockup' 13 | export * from './manageFreeze' 14 | export * from './rebalance' 15 | export * from './removeAdmin' 16 | export * from './repay' 17 | export * from './requestWithdrawal' 18 | export * from './restake' 19 | export * from './slash' 20 | export * from './swap' 21 | export * from './swapLp' 22 | export * from './updateDepositCap' 23 | export * from './withdraw' 24 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/AddAdminArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as web3 from '@solana/web3.js' 9 | import * as beetSolana from '@metaplex-foundation/beet-solana' 10 | import * as beet from '@metaplex-foundation/beet' 11 | import { Permissions, permissionsBeet } from './Permissions' 12 | export type AddAdminArgs = { 13 | address: web3.PublicKey 14 | permissions: Permissions 15 | } 16 | 17 | /** 18 | * @category userTypes 19 | * @category generated 20 | */ 21 | export const addAdminArgsBeet = new beet.BeetArgsStruct( 22 | [ 23 | ['address', beetSolana.publicKey], 24 | ['permissions', permissionsBeet], 25 | ], 26 | 'AddAdminArgs' 27 | ) 28 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/BoostRewardsArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type BoostRewardsArgs = { 10 | lockupId: beet.bignum 11 | minUsdValue: beet.bignum 12 | boostBps: beet.bignum 13 | } 14 | 15 | /** 16 | * @category userTypes 17 | * @category generated 18 | */ 19 | export const boostRewardsArgsBeet = new beet.BeetArgsStruct( 20 | [ 21 | ['lockupId', beet.u64], 22 | ['minUsdValue', beet.u64], 23 | ['boostBps', beet.u64], 24 | ], 25 | 'BoostRewardsArgs' 26 | ) 27 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/BorrowArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type BorrowArgs = { 10 | amount: beet.bignum 11 | fromLockupId: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const borrowArgsBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['amount', beet.u64], 21 | ['fromLockupId', beet.u64], 22 | ], 23 | 'BorrowArgs' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/CooldownRewards.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | /** 10 | * This type is used to derive the {@link CooldownRewards} type as well as the de/serializer. 11 | * However don't refer to it in your code but use the {@link CooldownRewards} type instead. 12 | * 13 | * @category userTypes 14 | * @category enums 15 | * @category generated 16 | * @private 17 | */ 18 | export type CooldownRewardsRecord = { 19 | Single: { fields: [beet.bignum] } 20 | Dual: { fields: [beet.bignum[] /* size: 2 */] } 21 | } 22 | 23 | /** 24 | * Union type respresenting the CooldownRewards data enum defined in Rust. 25 | * 26 | * NOTE: that it includes a `__kind` property which allows to narrow types in 27 | * switch/if statements. 28 | * Additionally `isCooldownRewards*` type guards are exposed below to narrow to a specific variant. 29 | * 30 | * @category userTypes 31 | * @category enums 32 | * @category generated 33 | */ 34 | export type CooldownRewards = beet.DataEnumKeyAsKind 35 | 36 | export const isCooldownRewardsSingle = ( 37 | x: CooldownRewards 38 | ): x is CooldownRewards & { __kind: 'Single' } => x.__kind === 'Single' 39 | export const isCooldownRewardsDual = ( 40 | x: CooldownRewards 41 | ): x is CooldownRewards & { __kind: 'Dual' } => x.__kind === 'Dual' 42 | 43 | /** 44 | * @category userTypes 45 | * @category generated 46 | */ 47 | export const cooldownRewardsBeet = beet.dataEnum([ 48 | [ 49 | 'Single', 50 | new beet.BeetArgsStruct( 51 | [['fields', beet.fixedSizeTuple([beet.u64])]], 52 | 'CooldownRewardsRecord["Single"]' 53 | ), 54 | ], 55 | [ 56 | 'Dual', 57 | new beet.BeetArgsStruct( 58 | [ 59 | [ 60 | 'fields', 61 | beet.fixedSizeTuple([beet.uniformFixedSizeArray(beet.u64, 2)]), 62 | ], 63 | ], 64 | 'CooldownRewardsRecord["Dual"]' 65 | ), 66 | ], 67 | ]) as beet.FixableBeet 68 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/DepositAndLockLpArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type DepositAndLockLpArgs = { 10 | tokenAAmount: beet.bignum 11 | tokenBAmount: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const depositAndLockLpArgsBeet = 19 | new beet.BeetArgsStruct( 20 | [ 21 | ['tokenAAmount', beet.u64], 22 | ['tokenBAmount', beet.u64], 23 | ], 24 | 'DepositAndLockLpArgs' 25 | ) 26 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/DepositRewardsArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type DepositRewardsArgs = { 10 | lockupId: beet.bignum 11 | amount: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const depositRewardsArgsBeet = 19 | new beet.BeetArgsStruct( 20 | [ 21 | ['lockupId', beet.u64], 22 | ['amount', beet.u64], 23 | ], 24 | 'DepositRewardsArgs' 25 | ) 26 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/GetUserBalanceAndRewardArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type GetUserBalanceAndRewardArgs = { 10 | lockupId: beet.bignum 11 | depositId: beet.bignum 12 | rewardBoostId: beet.COption 13 | receiptTokens: beet.bignum 14 | } 15 | 16 | /** 17 | * @category userTypes 18 | * @category generated 19 | */ 20 | export const getUserBalanceAndRewardArgsBeet = 21 | new beet.FixableBeetArgsStruct( 22 | [ 23 | ['lockupId', beet.u64], 24 | ['depositId', beet.u64], 25 | ['rewardBoostId', beet.coption(beet.u64)], 26 | ['receiptTokens', beet.u64], 27 | ], 28 | 'GetUserBalanceAndRewardArgs' 29 | ) 30 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/InitializeInsuranceFundArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as web3 from '@solana/web3.js' 9 | import * as beet from '@metaplex-foundation/beet' 10 | import * as beetSolana from '@metaplex-foundation/beet-solana' 11 | export type InitializeInsuranceFundArgs = { 12 | coldWallet: web3.PublicKey 13 | hotWalletShareBps: beet.bignum 14 | coldWalletShareBps: beet.bignum 15 | rewardMint: web3.PublicKey 16 | cooldownDuration: beet.bignum 17 | } 18 | 19 | /** 20 | * @category userTypes 21 | * @category generated 22 | */ 23 | export const initializeInsuranceFundArgsBeet = 24 | new beet.BeetArgsStruct( 25 | [ 26 | ['coldWallet', beetSolana.publicKey], 27 | ['hotWalletShareBps', beet.u64], 28 | ['coldWalletShareBps', beet.u64], 29 | ['rewardMint', beetSolana.publicKey], 30 | ['cooldownDuration', beet.u64], 31 | ], 32 | 'InitializeInsuranceFundArgs' 33 | ) 34 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/InitializeLockupArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | import { YieldMode, yieldModeBeet } from './YieldMode' 10 | export type InitializeLockupArgs = { 11 | minDeposit: beet.bignum 12 | depositCap: beet.bignum 13 | duration: beet.bignum 14 | yieldMode: YieldMode 15 | } 16 | 17 | /** 18 | * @category userTypes 19 | * @category generated 20 | */ 21 | export const initializeLockupArgsBeet = 22 | new beet.FixableBeetArgsStruct( 23 | [ 24 | ['minDeposit', beet.u64], 25 | ['depositCap', beet.u64], 26 | ['duration', beet.u64], 27 | ['yieldMode', yieldModeBeet], 28 | ], 29 | 'InitializeLockupArgs' 30 | ) 31 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/InitializeLpLockupArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type InitializeLpLockupArgs = { 10 | durationSeconds: beet.bignum 11 | } 12 | 13 | /** 14 | * @category userTypes 15 | * @category generated 16 | */ 17 | export const initializeLpLockupArgsBeet = 18 | new beet.BeetArgsStruct( 19 | [['durationSeconds', beet.u64]], 20 | 'InitializeLpLockupArgs' 21 | ) 22 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/ManageFreezeArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type ManageFreezeArgs = { 10 | freeze: boolean 11 | } 12 | 13 | /** 14 | * @category userTypes 15 | * @category generated 16 | */ 17 | export const manageFreezeArgsBeet = new beet.BeetArgsStruct( 18 | [['freeze', beet.bool]], 19 | 'ManageFreezeArgs' 20 | ) 21 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/Oracle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as web3 from '@solana/web3.js' 9 | import * as beet from '@metaplex-foundation/beet' 10 | import * as beetSolana from '@metaplex-foundation/beet-solana' 11 | /** 12 | * This type is used to derive the {@link Oracle} type as well as the de/serializer. 13 | * However don't refer to it in your code but use the {@link Oracle} type instead. 14 | * 15 | * @category userTypes 16 | * @category enums 17 | * @category generated 18 | * @private 19 | */ 20 | export type OracleRecord = { 21 | Pyth: { fields: [web3.PublicKey] } 22 | Switchboard: { fields: [web3.PublicKey] } 23 | } 24 | 25 | /** 26 | * Union type respresenting the Oracle data enum defined in Rust. 27 | * 28 | * NOTE: that it includes a `__kind` property which allows to narrow types in 29 | * switch/if statements. 30 | * Additionally `isOracle*` type guards are exposed below to narrow to a specific variant. 31 | * 32 | * @category userTypes 33 | * @category enums 34 | * @category generated 35 | */ 36 | export type Oracle = beet.DataEnumKeyAsKind 37 | 38 | export const isOraclePyth = (x: Oracle): x is Oracle & { __kind: 'Pyth' } => 39 | x.__kind === 'Pyth' 40 | export const isOracleSwitchboard = ( 41 | x: Oracle 42 | ): x is Oracle & { __kind: 'Switchboard' } => x.__kind === 'Switchboard' 43 | 44 | /** 45 | * @category userTypes 46 | * @category generated 47 | */ 48 | export const oracleBeet = beet.dataEnum([ 49 | [ 50 | 'Pyth', 51 | new beet.BeetArgsStruct( 52 | [['fields', beet.fixedSizeTuple([beetSolana.publicKey])]], 53 | 'OracleRecord["Pyth"]' 54 | ), 55 | ], 56 | [ 57 | 'Switchboard', 58 | new beet.BeetArgsStruct( 59 | [['fields', beet.fixedSizeTuple([beetSolana.publicKey])]], 60 | 'OracleRecord["Switchboard"]' 61 | ), 62 | ], 63 | ]) as beet.FixableBeet 64 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/Permissions.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | /** 10 | * @category enums 11 | * @category generated 12 | */ 13 | export enum Permissions { 14 | Freeze, 15 | AssetsAndLockups, 16 | Slashing, 17 | Superadmin, 18 | } 19 | 20 | /** 21 | * @category userTypes 22 | * @category generated 23 | */ 24 | export const permissionsBeet = beet.fixedScalarEnum( 25 | Permissions 26 | ) as beet.FixedSizeBeet 27 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/ProcessIntentArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type ProcessIntentArgs = { 10 | depositId: beet.bignum 11 | lockupId: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const processIntentArgsBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['depositId', beet.u64], 21 | ['lockupId', beet.u64], 22 | ], 23 | 'ProcessIntentArgs' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RebalanceArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type RebalanceArgs = { 10 | lockupId: beet.bignum 11 | } 12 | 13 | /** 14 | * @category userTypes 15 | * @category generated 16 | */ 17 | export const rebalanceArgsBeet = new beet.BeetArgsStruct( 18 | [['lockupId', beet.u64]], 19 | 'RebalanceArgs' 20 | ) 21 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RemoveAdminArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as web3 from '@solana/web3.js' 9 | import * as beetSolana from '@metaplex-foundation/beet-solana' 10 | import * as beet from '@metaplex-foundation/beet' 11 | export type RemoveAdminArgs = { 12 | address: web3.PublicKey 13 | } 14 | 15 | /** 16 | * @category userTypes 17 | * @category generated 18 | */ 19 | export const removeAdminArgsBeet = new beet.BeetArgsStruct( 20 | [['address', beetSolana.publicKey]], 21 | 'RemoveAdminArgs' 22 | ) 23 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RepayArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type RepayArgs = { 10 | debtRecordId: beet.bignum 11 | } 12 | 13 | /** 14 | * @category userTypes 15 | * @category generated 16 | */ 17 | export const repayArgsBeet = new beet.BeetArgsStruct( 18 | [['debtRecordId', beet.u64]], 19 | 'RepayArgs' 20 | ) 21 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RequestWithdrawalArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | import { 10 | RequestWithdrawalMode, 11 | requestWithdrawalModeBeet, 12 | } from './RequestWithdrawalMode' 13 | export type RequestWithdrawalArgs = { 14 | lockupId: beet.bignum 15 | depositId: beet.bignum 16 | rewardBoostId: beet.COption 17 | mode: RequestWithdrawalMode 18 | } 19 | 20 | /** 21 | * @category userTypes 22 | * @category generated 23 | */ 24 | export const requestWithdrawalArgsBeet = 25 | new beet.FixableBeetArgsStruct( 26 | [ 27 | ['lockupId', beet.u64], 28 | ['depositId', beet.u64], 29 | ['rewardBoostId', beet.coption(beet.u64)], 30 | ['mode', requestWithdrawalModeBeet], 31 | ], 32 | 'RequestWithdrawalArgs' 33 | ) 34 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RequestWithdrawalMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | /** 10 | * This type is used to derive the {@link RequestWithdrawalMode} type as well as the de/serializer. 11 | * However don't refer to it in your code but use the {@link RequestWithdrawalMode} type instead. 12 | * 13 | * @category userTypes 14 | * @category enums 15 | * @category generated 16 | * @private 17 | */ 18 | export type RequestWithdrawalModeRecord = { 19 | ExactIn: { fields: [beet.bignum] } 20 | ExactOut: { fields: [beet.bignum] } 21 | } 22 | 23 | /** 24 | * Union type respresenting the RequestWithdrawalMode data enum defined in Rust. 25 | * 26 | * NOTE: that it includes a `__kind` property which allows to narrow types in 27 | * switch/if statements. 28 | * Additionally `isRequestWithdrawalMode*` type guards are exposed below to narrow to a specific variant. 29 | * 30 | * @category userTypes 31 | * @category enums 32 | * @category generated 33 | */ 34 | export type RequestWithdrawalMode = 35 | beet.DataEnumKeyAsKind 36 | 37 | export const isRequestWithdrawalModeExactIn = ( 38 | x: RequestWithdrawalMode 39 | ): x is RequestWithdrawalMode & { __kind: 'ExactIn' } => x.__kind === 'ExactIn' 40 | export const isRequestWithdrawalModeExactOut = ( 41 | x: RequestWithdrawalMode 42 | ): x is RequestWithdrawalMode & { __kind: 'ExactOut' } => 43 | x.__kind === 'ExactOut' 44 | 45 | /** 46 | * @category userTypes 47 | * @category generated 48 | */ 49 | export const requestWithdrawalModeBeet = 50 | beet.dataEnum([ 51 | [ 52 | 'ExactIn', 53 | new beet.BeetArgsStruct( 54 | [['fields', beet.fixedSizeTuple([beet.u64])]], 55 | 'RequestWithdrawalModeRecord["ExactIn"]' 56 | ), 57 | ], 58 | [ 59 | 'ExactOut', 60 | new beet.BeetArgsStruct( 61 | [['fields', beet.fixedSizeTuple([beet.u64])]], 62 | 'RequestWithdrawalModeRecord["ExactOut"]' 63 | ), 64 | ], 65 | ]) as beet.FixableBeet 66 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RestakeArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type RestakeArgs = { 10 | lockupId: beet.bignum 11 | amount: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const restakeArgsBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['lockupId', beet.u64], 21 | ['amount', beet.u64], 22 | ], 23 | 'RestakeArgs' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/RewardConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as web3 from '@solana/web3.js' 9 | import * as beetSolana from '@metaplex-foundation/beet-solana' 10 | import * as beet from '@metaplex-foundation/beet' 11 | export type RewardConfig = { 12 | main: web3.PublicKey 13 | } 14 | 15 | /** 16 | * @category userTypes 17 | * @category generated 18 | */ 19 | export const rewardConfigBeet = new beet.BeetArgsStruct( 20 | [['main', beetSolana.publicKey]], 21 | 'RewardConfig' 22 | ) 23 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/SharesConfig.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type SharesConfig = { 10 | hotWalletShareBps: beet.bignum 11 | coldWalletShareBps: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const sharesConfigBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['hotWalletShareBps', beet.u64], 21 | ['coldWalletShareBps', beet.u64], 22 | ], 23 | 'SharesConfig' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/SlashArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type SlashArgs = { 10 | lockupId: beet.bignum 11 | amount: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const slashArgsBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['lockupId', beet.u64], 21 | ['amount', beet.u64], 22 | ], 23 | 'SlashArgs' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/SlashState.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type SlashState = { 10 | index: beet.bignum 11 | amount: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const slashStateBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['index', beet.u64], 21 | ['amount', beet.u64], 22 | ], 23 | 'SlashState' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/SwapArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type SwapArgs = { 10 | fromLockupId: beet.bignum 11 | toLockupId: beet.bignum 12 | amountIn: beet.bignum 13 | minAmountOut: beet.COption 14 | } 15 | 16 | /** 17 | * @category userTypes 18 | * @category generated 19 | */ 20 | export const swapArgsBeet = new beet.FixableBeetArgsStruct( 21 | [ 22 | ['fromLockupId', beet.u64], 23 | ['toLockupId', beet.u64], 24 | ['amountIn', beet.u64], 25 | ['minAmountOut', beet.coption(beet.u64)], 26 | ], 27 | 'SwapArgs' 28 | ) 29 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/SwapLpArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type SwapLpArgs = { 10 | amountIn: beet.bignum 11 | aToB: boolean 12 | minOut: beet.COption 13 | } 14 | 15 | /** 16 | * @category userTypes 17 | * @category generated 18 | */ 19 | export const swapLpArgsBeet = new beet.FixableBeetArgsStruct( 20 | [ 21 | ['amountIn', beet.u64], 22 | ['aToB', beet.bool], 23 | ['minOut', beet.coption(beet.u64)], 24 | ], 25 | 'SwapLpArgs' 26 | ) 27 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/UpdateDepositCapArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type UpdateDepositCapArgs = { 10 | lockupId: beet.bignum 11 | newCap: beet.COption 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const updateDepositCapArgsBeet = 19 | new beet.FixableBeetArgsStruct( 20 | [ 21 | ['lockupId', beet.u64], 22 | ['newCap', beet.coption(beet.u64)], 23 | ], 24 | 'UpdateDepositCapArgs' 25 | ) 26 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/WithdrawArgs.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | export type WithdrawArgs = { 10 | lockupId: beet.bignum 11 | depositId: beet.bignum 12 | } 13 | 14 | /** 15 | * @category userTypes 16 | * @category generated 17 | */ 18 | export const withdrawArgsBeet = new beet.BeetArgsStruct( 19 | [ 20 | ['lockupId', beet.u64], 21 | ['depositId', beet.u64], 22 | ], 23 | 'WithdrawArgs' 24 | ) 25 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/YieldMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | /** 10 | * This type is used to derive the {@link YieldMode} type as well as the de/serializer. 11 | * However don't refer to it in your code but use the {@link YieldMode} type instead. 12 | * 13 | * @category userTypes 14 | * @category enums 15 | * @category generated 16 | * @private 17 | */ 18 | export type YieldModeRecord = { 19 | Single: void /* scalar variant */ 20 | Dual: { fields: [beet.bignum] } 21 | } 22 | 23 | /** 24 | * Union type respresenting the YieldMode data enum defined in Rust. 25 | * 26 | * NOTE: that it includes a `__kind` property which allows to narrow types in 27 | * switch/if statements. 28 | * Additionally `isYieldMode*` type guards are exposed below to narrow to a specific variant. 29 | * 30 | * @category userTypes 31 | * @category enums 32 | * @category generated 33 | */ 34 | export type YieldMode = beet.DataEnumKeyAsKind 35 | 36 | export const isYieldModeSingle = ( 37 | x: YieldMode 38 | ): x is YieldMode & { __kind: 'Single' } => x.__kind === 'Single' 39 | export const isYieldModeDual = ( 40 | x: YieldMode 41 | ): x is YieldMode & { __kind: 'Dual' } => x.__kind === 'Dual' 42 | 43 | /** 44 | * @category userTypes 45 | * @category generated 46 | */ 47 | export const yieldModeBeet = beet.dataEnum([ 48 | ['Single', beet.unit], 49 | [ 50 | 'Dual', 51 | new beet.BeetArgsStruct( 52 | [['fields', beet.fixedSizeTuple([beet.u64])]], 53 | 'YieldModeRecord["Dual"]' 54 | ), 55 | ], 56 | ]) as beet.FixableBeet 57 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/generated/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AddAdminArgs' 2 | export * from './BoostRewardsArgs' 3 | export * from './BorrowArgs' 4 | export * from './CooldownRewards' 5 | export * from './DepositAndLockLpArgs' 6 | export * from './DepositRewardsArgs' 7 | export * from './GetUserBalanceAndRewardArgs' 8 | export * from './InitializeInsuranceFundArgs' 9 | export * from './InitializeLockupArgs' 10 | export * from './InitializeLpLockupArgs' 11 | export * from './ManageFreezeArgs' 12 | export * from './Oracle' 13 | export * from './Permissions' 14 | export * from './ProcessIntentArgs' 15 | export * from './RebalanceArgs' 16 | export * from './RemoveAdminArgs' 17 | export * from './RepayArgs' 18 | export * from './RequestWithdrawalArgs' 19 | export * from './RequestWithdrawalMode' 20 | export * from './RestakeArgs' 21 | export * from './RewardConfig' 22 | export * from './SharesConfig' 23 | export * from './SlashArgs' 24 | export * from './SlashState' 25 | export * from './SwapArgs' 26 | export * from './SwapLpArgs' 27 | export * from './UpdateDepositCapArgs' 28 | export * from './WithdrawArgs' 29 | export * from './YieldMode' 30 | -------------------------------------------------------------------------------- /insurance-fund/sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./classes"; 2 | export * from "./generated"; -------------------------------------------------------------------------------- /insurance-fund/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": false, 6 | "skipLibCheck": true, 7 | "declaration": true, 8 | "typeRoots": ["./node_modules/@types"], 9 | "lib": ["es2015"], 10 | "module": "commonjs", 11 | "target": "es2016", 12 | "esModuleInterop": true 13 | }, 14 | "include": [ 15 | "./src/**/*" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/calculateLpToken.ts: -------------------------------------------------------------------------------- 1 | import BN from 'bn.js'; 2 | 3 | type Price = { 4 | price: BN; 5 | precision: BN; 6 | } 7 | 8 | export default function calculateLpToken( 9 | lpTokenSupply: BN, 10 | tokenALiquidity: BN, 11 | tokenBLiquidity: BN, 12 | tokenADeposit: BN, 13 | tokenBDeposit: BN, 14 | tokenAPrice: Price, 15 | tokenBPrice: Price 16 | ): BN { 17 | const depositAValue = tokenAPrice 18 | .price 19 | .mul(tokenADeposit) 20 | .div(new BN(10).pow(tokenAPrice.precision)); 21 | const depositBValue = tokenBPrice 22 | .price 23 | .mul(tokenBDeposit) 24 | .div(new BN(10).pow(tokenBPrice.precision)); 25 | 26 | const totalDepositValue = depositAValue.add(depositBValue); 27 | 28 | if (lpTokenSupply.isZero()) { 29 | return totalDepositValue; 30 | } 31 | 32 | const tokenALiquidityValue = tokenAPrice 33 | .price 34 | .mul(tokenALiquidity) 35 | .div( 36 | new BN(10).pow(tokenAPrice.precision) 37 | ); 38 | 39 | const tokenBLiquidityValue = tokenBPrice 40 | .price 41 | .mul(tokenBLiquidity) 42 | .div( 43 | new BN(10).pow(tokenBPrice.precision) 44 | ); 45 | 46 | const totalLpValue = tokenALiquidityValue.add(tokenBLiquidityValue); 47 | 48 | const valuePerLpToken = totalLpValue.div(lpTokenSupply); 49 | const lpTokenToMint = totalDepositValue.div(valuePerLpToken); 50 | 51 | return lpTokenToMint; 52 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/calculateReceiptToken.ts: -------------------------------------------------------------------------------- 1 | import BN from 'bn.js'; 2 | 3 | export default function calculateReceiptToken( 4 | receiptTokenMintSupply: BN, 5 | deposit: BN, 6 | totalDeposits: BN 7 | ): BN { 8 | if (receiptTokenMintSupply.isZero()) { 9 | return deposit; 10 | } else { 11 | const result = deposit.mul(totalDeposits).div(receiptTokenMintSupply); 12 | return result; 13 | } 14 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/comparePubkeys.ts: -------------------------------------------------------------------------------- 1 | import {PublicKey} from "@solana/web3.js"; 2 | 3 | function comparePubkeys(a: PublicKey, b: PublicKey): number { 4 | return a.toBase58().localeCompare(b.toBase58()); 5 | } 6 | export default comparePubkeys; -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/createToken.ts: -------------------------------------------------------------------------------- 1 | import {Connection, Keypair, SystemProgram, Transaction} from "@solana/web3.js"; 2 | import {AnchorProvider} from "@coral-xyz/anchor"; 3 | import {createInitializeMintInstruction, MINT_SIZE, TOKEN_PROGRAM_ID} from "@solana/spl-token"; 4 | 5 | async function createToken( 6 | connection: Connection, 7 | payer: AnchorProvider 8 | ) { 9 | const keypair = Keypair.generate(); 10 | 11 | const lamports = await connection.getMinimumBalanceForRentExemption(MINT_SIZE); 12 | const createAccountIx = SystemProgram.createAccount({ 13 | newAccountPubkey: keypair.publicKey, 14 | fromPubkey: payer.publicKey, 15 | lamports, 16 | programId: TOKEN_PROGRAM_ID, 17 | space: MINT_SIZE 18 | }); 19 | 20 | const ix = createInitializeMintInstruction( 21 | keypair.publicKey, 22 | 9, 23 | payer.publicKey, 24 | payer.publicKey 25 | ); 26 | 27 | const tx = new Transaction(); 28 | tx.add(createAccountIx, ix); 29 | 30 | const { 31 | lastValidBlockHeight, 32 | blockhash 33 | } = await connection.getLatestBlockhash(); 34 | 35 | tx.feePayer = payer.publicKey; 36 | tx.recentBlockhash = blockhash; 37 | 38 | tx.partialSign(keypair); 39 | const signed = await payer.wallet.signTransaction(tx); 40 | 41 | const sent = await connection.sendRawTransaction(signed.serialize()); 42 | await connection.confirmTransaction({ 43 | blockhash, 44 | lastValidBlockHeight, 45 | signature: sent 46 | }, "confirmed"); 47 | 48 | return keypair.publicKey; 49 | } 50 | 51 | export default createToken; -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/debugLogs.ts: -------------------------------------------------------------------------------- 1 | import {Connection} from "@solana/web3.js"; 2 | 3 | export default async function debugLogs( 4 | connection: Connection, 5 | signature: string, 6 | ) { 7 | 8 | const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash(); 9 | await connection.confirmTransaction({ 10 | blockhash, 11 | lastValidBlockHeight, 12 | signature 13 | }, "confirmed"); 14 | 15 | const { 16 | meta: { 17 | logMessages, 18 | err 19 | } 20 | } = await connection.getParsedTransaction( 21 | signature, 22 | "confirmed" 23 | ); 24 | 25 | return logMessages; 26 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/getOraclePrice.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import BN from "bn.js"; 3 | 4 | type Response = { 5 | id: "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d", 6 | price: { 7 | price: `${number}`, 8 | conf: `${number}`, 9 | expo: number, 10 | publish_time: number 11 | }, 12 | ema_price: { 13 | price: `${number}`, 14 | conf: `${number}`, 15 | expo: number, 16 | publish_time: number 17 | } 18 | }[] 19 | 20 | export default async function getOraclePrice(feed: string = "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d") { 21 | const { 22 | data 23 | } = await axios.get(`https://hermes.pyth.network/api/latest_price_feeds?ids[]=${feed}`); 24 | 25 | const { 26 | price: { 27 | price, 28 | expo 29 | } 30 | } = data[0]; 31 | 32 | return { 33 | price: new BN(price), 34 | precision: new BN(expo).abs() 35 | } 36 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/getOraclePriceFromAccount.ts: -------------------------------------------------------------------------------- 1 | import getOraclePrice from "./getOraclePrice"; 2 | 3 | const feeds: Map = new Map([ 4 | ["7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE", "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"], 5 | ["Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX", "eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a"], 6 | ]); 7 | 8 | export default function getOraclePriceFromAccount(account: string) { 9 | return getOraclePrice(feeds.get(account)); 10 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/mintTokens.ts: -------------------------------------------------------------------------------- 1 | import {PublicKey, Transaction} from "@solana/web3.js"; 2 | import {AnchorProvider} from "@coral-xyz/anchor"; 3 | import { 4 | createAssociatedTokenAccountIdempotentInstruction, 5 | createMintToInstruction, 6 | getAssociatedTokenAddressSync 7 | } from "@solana/spl-token"; 8 | 9 | export default async function mintTokens( 10 | mint: PublicKey, 11 | payer: AnchorProvider, 12 | amount: number, 13 | recipient?: PublicKey 14 | ) { 15 | 16 | const ata = getAssociatedTokenAddressSync( 17 | mint, 18 | recipient || payer.publicKey, 19 | true 20 | ); 21 | 22 | const ataIx = createAssociatedTokenAccountIdempotentInstruction( 23 | payer.publicKey, 24 | ata, 25 | recipient || payer.publicKey, 26 | mint, 27 | ); 28 | 29 | const ix = createMintToInstruction( 30 | mint, 31 | ata, 32 | payer.publicKey, 33 | amount, 34 | ); 35 | 36 | const tx = new Transaction(); 37 | tx.add(ataIx, ix); 38 | 39 | const { 40 | lastValidBlockHeight, 41 | blockhash 42 | } = await payer.connection.getLatestBlockhash(); 43 | 44 | tx.feePayer = payer.publicKey; 45 | tx.recentBlockhash = blockhash; 46 | 47 | const signed = await payer.wallet.signTransaction(tx); 48 | 49 | const sent = await payer.connection.sendRawTransaction(signed.serialize()); 50 | await payer.connection.confirmTransaction({ 51 | blockhash, 52 | lastValidBlockHeight, 53 | signature: sent 54 | }, "confirmed"); 55 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/signAndSendTransaction.ts: -------------------------------------------------------------------------------- 1 | import {Connection, Keypair, MessageV0, TransactionMessage, VersionedTransaction} from "@solana/web3.js"; 2 | import {AnchorProvider} from "@coral-xyz/anchor"; 3 | 4 | export default async function signAndSendTransaction( 5 | message: MessageV0, 6 | connection: Connection, 7 | skipPreflight?: boolean, 8 | signers?: Keypair[] 9 | ) { 10 | const { 11 | lastValidBlockHeight, 12 | blockhash 13 | } = await connection.getLatestBlockhash(); 14 | 15 | const transaction = new VersionedTransaction(message); 16 | 17 | if (signers && signers.length) transaction.sign(signers); 18 | 19 | const txid = await connection.sendRawTransaction( 20 | transaction.serialize(), 21 | { skipPreflight } 22 | ); 23 | 24 | await connection.confirmTransaction({ 25 | lastValidBlockHeight, 26 | blockhash, 27 | signature: txid 28 | }, "confirmed"); 29 | // 30 | // const { 31 | // meta: { 32 | // err, 33 | // logMessages 34 | // } 35 | // } = await provider.connection.getParsedTransaction(txid, "confirmed"); 36 | // 37 | // console.log({ 38 | // logMessages, 39 | // err 40 | // }); 41 | // 42 | // if (err) throw err; 43 | 44 | return txid; 45 | } -------------------------------------------------------------------------------- /insurance-fund/tests/helpers/sleep.ts: -------------------------------------------------------------------------------- 1 | export default function sleep(s: number) { 2 | return new Promise((resolve) => setTimeout(resolve, s * 1000)); 3 | } -------------------------------------------------------------------------------- /insurance-fund/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 | } -------------------------------------------------------------------------------- /reflect-single-pool/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palindrome-eng/reflect-program-library/5f4f49df98017fb85ec8a75b3626b7aaabdf203f/reflect-single-pool/.DS_Store -------------------------------------------------------------------------------- /reflect-single-pool/.gitignore: -------------------------------------------------------------------------------- 1 | program-id-key/ 2 | -------------------------------------------------------------------------------- /reflect-single-pool/README.md: -------------------------------------------------------------------------------- 1 | ## ⚠️ Warning - This is a FORK maintained by the Reflect Protocol. 2 | 3 | ### Solana Program Library Single-Validator Stake Pool 4 | 5 | The single-validator stake pool program is an upcoming SPL program that enables liquid staking with zero fees, no counterparty, and 100% capital efficiency. 6 | 7 | The program defines a canonical pool for every vote account, which can be initialized permissionlessly, and mints tokens in exchange for stake delegated to its designated validator. 8 | 9 | The program is a stripped-down adaptation of the existing multi-validator stake pool program, with approximately 80% less code, to minimize execution risk. 10 | 11 | On launch, users will only be able to deposit and withdraw active stake, but pending future stake program development, we hope to support instant sol deposits and withdrawals as well. 12 | 13 | 14 | -------------------------------------------------------------------------------- /reflect-single-pool/cli/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palindrome-eng/reflect-program-library/5f4f49df98017fb85ec8a75b3626b7aaabdf203f/reflect-single-pool/cli/.DS_Store -------------------------------------------------------------------------------- /reflect-single-pool/cli/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb -------------------------------------------------------------------------------- /reflect-single-pool/cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reflect-single-pool-cli" 3 | version = "1.0.0" 4 | description = "Solana Program Library Single-Validator Stake Pool Command-line Utility" 5 | authors = ["Solana Labs Maintainers "] 6 | repository = "https://github.com/solana-labs/solana-program-library" 7 | license = "Apache-2.0" 8 | edition = "2021" 9 | 10 | [dependencies] 11 | tokio = "1.37" 12 | clap = { version = "3.2.23", features = ["derive"] } 13 | console = "0.15.8" 14 | borsh = "1.5.0" 15 | bincode = "1.3.1" 16 | serde = "1.0.199" 17 | serde_derive = "1.0.103" 18 | serde_json = "1.0.116" 19 | serde_with = "3.8.1" 20 | solana-account-decoder = "1.18.12" 21 | solana-clap-v3-utils = "1.18.12" 22 | solana-cli-config = "1.18.12" 23 | solana-cli-output = "1.18.12" 24 | solana-client = "1.18.12" 25 | solana-logger = "1.18.12" 26 | solana-remote-wallet = "1.18.12" 27 | solana-sdk = "1.18.12" 28 | solana-transaction-status = "1.18.12" 29 | solana-vote-program = "1.18.12" 30 | spl-token = { version = "4.0", features = [ 31 | "no-entrypoint", 32 | ] } 33 | spl-token-client = "0.10.0" 34 | spl-associated-token-account = { version = "2.3.0", features = [ 35 | "no-entrypoint", 36 | ] } 37 | reflect-single-pool = { version = "1.0.0", path = "../program", features = [ 38 | "no-entrypoint", 39 | ] } 40 | 41 | [dev-dependencies] 42 | solana-test-validator = "1.18.12" 43 | serial_test = "3.1.1" 44 | test-case = "3.3" 45 | tempfile = "3.10.1" 46 | 47 | [[bin]] 48 | name = "reflect-single-pool" 49 | path = "src/main.rs" 50 | -------------------------------------------------------------------------------- /reflect-single-pool/cli/src/quarantine.rs: -------------------------------------------------------------------------------- 1 | // XXX this file will be deleted and replaced with a stake program client once i 2 | // write one 3 | 4 | use { 5 | crate::config::*, 6 | solana_sdk::{ 7 | instruction::Instruction, 8 | native_token::LAMPORTS_PER_SOL, 9 | pubkey::Pubkey, 10 | stake::{ 11 | self, 12 | state::{Meta, Stake, StakeStateV2}, 13 | }, 14 | system_instruction, 15 | sysvar::{self, rent::Rent}, 16 | }, 17 | }; 18 | 19 | pub async fn get_rent(config: &Config) -> Result { 20 | let rent_data = config 21 | .program_client 22 | .get_account(sysvar::rent::id()) 23 | .await? 24 | .unwrap(); 25 | let rent = bincode::deserialize::(&rent_data.data)?; 26 | 27 | Ok(rent) 28 | } 29 | 30 | pub async fn get_minimum_delegation(config: &Config) -> Result { 31 | Ok(std::cmp::max( 32 | config.rpc_client.get_stake_minimum_delegation().await?, 33 | LAMPORTS_PER_SOL, 34 | )) 35 | } 36 | 37 | pub async fn get_stake_info( 38 | config: &Config, 39 | stake_account_address: &Pubkey, 40 | ) -> Result, Error> { 41 | if let Some(stake_account) = config 42 | .program_client 43 | .get_account(*stake_account_address) 44 | .await? 45 | { 46 | match bincode::deserialize::(&stake_account.data)? { 47 | StakeStateV2::Stake(meta, stake, _) => Ok(Some((meta, stake))), 48 | StakeStateV2::Initialized(_) => { 49 | Err(format!("Stake account {} is undelegated", stake_account_address).into()) 50 | } 51 | StakeStateV2::Uninitialized => { 52 | Err(format!("Stake account {} is uninitialized", stake_account_address).into()) 53 | } 54 | StakeStateV2::RewardsPool => unimplemented!(), 55 | } 56 | } else { 57 | Ok(None) 58 | } 59 | } 60 | 61 | pub async fn create_uninitialized_stake_account_instruction( 62 | config: &Config, 63 | payer: &Pubkey, 64 | stake_account: &Pubkey, 65 | ) -> Result { 66 | let rent_amount = config 67 | .program_client 68 | .get_minimum_balance_for_rent_exemption(std::mem::size_of::()) 69 | .await?; 70 | 71 | Ok(system_instruction::create_account( 72 | payer, 73 | stake_account, 74 | rent_amount, 75 | std::mem::size_of::() as u64, 76 | &stake::program::id(), 77 | )) 78 | } 79 | -------------------------------------------------------------------------------- /reflect-single-pool/js/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .vscode 4 | .idea 5 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | es6: true, 5 | node: true, 6 | jest: true, 7 | }, 8 | extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'], 9 | plugins: ['@typescript-eslint/eslint-plugin'], 10 | parser: '@typescript-eslint/parser', 11 | parserOptions: { 12 | sourceType: 'module', 13 | }, 14 | rules: { 15 | '@typescript-eslint/interface-name-prefix': 'off', 16 | '@typescript-eslint/explicit-function-return-type': 'off', 17 | '@typescript-eslint/explicit-module-boundary-types': 'off', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | '@typescript-eslint/ban-ts-comment': 'off', 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | trailingComma: 'all', 4 | printWidth: 100, 5 | endOfLine: 'lf', 6 | semi: true, 7 | }; 8 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/README.md: -------------------------------------------------------------------------------- 1 | # `@solana/spl-single-pool-classic` 2 | 3 | A TypeScript library for interacting with the SPL Single-Validator Stake Pool program, targeting `@solana/web3.js` 1.x. 4 | **If you are working on the new, bleeding-edge web3.js, you want `@solana/spl-single-pool`.** 5 | 6 | For information on installation and usage, see [SPL docs](https://spl.solana.com/single-pool). 7 | 8 | For support, please ask questions on the [Solana Stack Exchange](https://solana.stackexchange.com). 9 | 10 | If you've found a bug or you'd like to request a feature, please 11 | [open an issue](https://github.com/solana-labs/solana-program-library/issues/new). 12 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@solana/spl-single-pool-classic", 3 | "version": "1.0.2", 4 | "main": "dist/cjs/index.js", 5 | "module": "dist/mjs/index.js", 6 | "exports": { 7 | ".": { 8 | "import": "./dist/mjs/index.js", 9 | "require": "./dist/cjs/index.js" 10 | } 11 | }, 12 | "scripts": { 13 | "clean": "rm -rf dist/*", 14 | "build": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./ts-fixup.sh", 15 | "build:program": "cargo build-sbf --manifest-path=../../../program/Cargo.toml", 16 | "lint": "eslint --max-warnings 0 .", 17 | "lint:fix": "eslint . --fix", 18 | "test": "sed -i '1s/.*/{ \"type\": \"module\",/' package.json && NODE_OPTIONS='--loader=tsx' ava ; ret=$?; sed -i '1s/.*/{/' package.json && exit $ret" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "^20.12.7", 22 | "@ava/typescript": "^4.1.0", 23 | "@typescript-eslint/eslint-plugin": "^7.8.0", 24 | "ava": "^6.1.2", 25 | "eslint": "^8.57.0", 26 | "eslint-config-prettier": "^9.1.0", 27 | "eslint-plugin-prettier": "^5.1.3", 28 | "solana-bankrun": "^0.2.0", 29 | "tsx": "^4.7.3", 30 | "typescript": "^5.4.5" 31 | }, 32 | "dependencies": { 33 | "@solana/web3.js": "^1.91.7", 34 | "@solana/spl-single-pool": "1.0.0" 35 | }, 36 | "ava": { 37 | "extensions": { 38 | "ts": "module" 39 | }, 40 | "nodeArguments": [ 41 | "--import=tsx" 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/src/addresses.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | import { 3 | findPoolAddress as findPoolModern, 4 | findPoolStakeAddress as findStakeModern, 5 | findPoolMintAddress as findMintModern, 6 | findPoolStakeAuthorityAddress as findStakeAuthorityModern, 7 | findPoolMintAuthorityAddress as findMintAuthorityModern, 8 | findPoolMplAuthorityAddress as findMplAuthorityModern, 9 | findDefaultDepositAccountAddress as findDefaultDepositModern, 10 | } from '@solana/spl-single-pool'; 11 | 12 | export async function findPoolAddress(programId: PublicKey, voteAccountAddress: PublicKey) { 13 | return new PublicKey(await findPoolModern(programId.toBase58(), voteAccountAddress.toBase58())); 14 | } 15 | 16 | export async function findPoolStakeAddress(programId: PublicKey, poolAddress: PublicKey) { 17 | return new PublicKey(await findStakeModern(programId.toBase58(), poolAddress.toBase58())); 18 | } 19 | 20 | export async function findPoolMintAddress(programId: PublicKey, poolAddress: PublicKey) { 21 | return new PublicKey(await findMintModern(programId.toBase58(), poolAddress.toBase58())); 22 | } 23 | 24 | export async function findPoolStakeAuthorityAddress(programId: PublicKey, poolAddress: PublicKey) { 25 | return new PublicKey( 26 | await findStakeAuthorityModern(programId.toBase58(), poolAddress.toBase58()), 27 | ); 28 | } 29 | 30 | export async function findPoolMintAuthorityAddress(programId: PublicKey, poolAddress: PublicKey) { 31 | return new PublicKey(await findMintAuthorityModern(programId.toBase58(), poolAddress.toBase58())); 32 | } 33 | 34 | export async function findPoolMplAuthorityAddress(programId: PublicKey, poolAddress: PublicKey) { 35 | return new PublicKey(await findMplAuthorityModern(programId.toBase58(), poolAddress.toBase58())); 36 | } 37 | 38 | export async function findDefaultDepositAccountAddress( 39 | poolAddress: PublicKey, 40 | userWallet: PublicKey, 41 | ) { 42 | return new PublicKey( 43 | await findDefaultDepositModern(poolAddress.toBase58(), userWallet.toBase58()), 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Connection, PublicKey } from '@solana/web3.js'; 2 | import { getVoteAccountAddressForPool as getVoteModern } from '@solana/spl-single-pool'; 3 | 4 | import { rpc } from './internal.js'; 5 | 6 | export * from './mpl_metadata.js'; 7 | export * from './addresses.js'; 8 | export * from './instructions.js'; 9 | export * from './transactions.js'; 10 | 11 | export async function getVoteAccountAddressForPool(connection: Connection, poolAddress: PublicKey) { 12 | const voteAccountModern = await getVoteModern(rpc(connection), poolAddress.toBase58()); 13 | 14 | return new PublicKey(voteAccountModern); 15 | } 16 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/src/instructions.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey, TransactionInstruction } from '@solana/web3.js'; 2 | import { SinglePoolInstruction as PoolInstructionModern } from '@solana/spl-single-pool'; 3 | 4 | import { modernInstructionToLegacy } from './internal.js'; 5 | 6 | export class SinglePoolInstruction { 7 | static async initializePool(voteAccount: PublicKey): Promise { 8 | const instruction = await PoolInstructionModern.initializePool(voteAccount.toBase58()); 9 | return modernInstructionToLegacy(instruction); 10 | } 11 | 12 | static async reactivatePoolStake(voteAccount: PublicKey): Promise { 13 | const instruction = await PoolInstructionModern.reactivatePoolStake(voteAccount.toBase58()); 14 | return modernInstructionToLegacy(instruction); 15 | } 16 | 17 | static async depositStake( 18 | pool: PublicKey, 19 | userStakeAccount: PublicKey, 20 | userTokenAccount: PublicKey, 21 | userLamportAccount: PublicKey, 22 | ): Promise { 23 | const instruction = await PoolInstructionModern.depositStake( 24 | pool.toBase58(), 25 | userStakeAccount.toBase58(), 26 | userTokenAccount.toBase58(), 27 | userLamportAccount.toBase58(), 28 | ); 29 | return modernInstructionToLegacy(instruction); 30 | } 31 | 32 | static async withdrawStake( 33 | pool: PublicKey, 34 | userStakeAccount: PublicKey, 35 | userStakeAuthority: PublicKey, 36 | userTokenAccount: PublicKey, 37 | tokenAmount: number | bigint, 38 | ): Promise { 39 | const instruction = await PoolInstructionModern.withdrawStake( 40 | pool.toBase58(), 41 | userStakeAccount.toBase58(), 42 | userStakeAuthority.toBase58(), 43 | userTokenAccount.toBase58(), 44 | BigInt(tokenAmount), 45 | ); 46 | return modernInstructionToLegacy(instruction); 47 | } 48 | 49 | static async createTokenMetadata( 50 | pool: PublicKey, 51 | payer: PublicKey, 52 | ): Promise { 53 | const instruction = await PoolInstructionModern.createTokenMetadata( 54 | pool.toBase58(), 55 | payer.toBase58(), 56 | ); 57 | return modernInstructionToLegacy(instruction); 58 | } 59 | 60 | static async updateTokenMetadata( 61 | voteAccount: PublicKey, 62 | authorizedWithdrawer: PublicKey, 63 | tokenName: string, 64 | tokenSymbol: string, 65 | tokenUri?: string, 66 | ): Promise { 67 | const instruction = await PoolInstructionModern.updateTokenMetadata( 68 | voteAccount.toBase58(), 69 | authorizedWithdrawer.toBase58(), 70 | tokenName, 71 | tokenSymbol, 72 | tokenUri, 73 | ); 74 | return modernInstructionToLegacy(instruction); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/src/internal.ts: -------------------------------------------------------------------------------- 1 | import { Connection, Transaction, TransactionInstruction, PublicKey } from '@solana/web3.js'; 2 | import { Buffer } from 'buffer'; 3 | 4 | export function rpc(connection: Connection) { 5 | return { 6 | getAccountInfo(address: string) { 7 | return { 8 | async send() { 9 | const pubkey = new PublicKey(address); 10 | return await connection.getAccountInfo(pubkey); 11 | }, 12 | }; 13 | }, 14 | getMinimumBalanceForRentExemption(size: bigint) { 15 | return { 16 | async send() { 17 | return BigInt(await connection.getMinimumBalanceForRentExemption(Number(size))); 18 | }, 19 | }; 20 | }, 21 | getStakeMinimumDelegation() { 22 | return { 23 | async send() { 24 | const minimumDelegation = await connection.getStakeMinimumDelegation(); 25 | return { value: BigInt(minimumDelegation.value) }; 26 | }, 27 | }; 28 | }, 29 | }; 30 | } 31 | 32 | export function modernInstructionToLegacy(modernInstruction: any): TransactionInstruction { 33 | const keys = []; 34 | for (const account of modernInstruction.accounts) { 35 | keys.push({ 36 | pubkey: new PublicKey(account.address), 37 | isSigner: !!(account.role & 2), 38 | isWritable: !!(account.role & 1), 39 | }); 40 | } 41 | 42 | return new TransactionInstruction({ 43 | programId: new PublicKey(modernInstruction.programAddress), 44 | keys, 45 | data: Buffer.from(modernInstruction.data), 46 | }); 47 | } 48 | 49 | export function modernTransactionToLegacy(modernTransaction: any): Transaction { 50 | const legacyTransaction = new Transaction(); 51 | legacyTransaction.add(...modernTransaction.instructions.map(modernInstructionToLegacy)); 52 | 53 | return legacyTransaction; 54 | } 55 | 56 | export function paramsToModern(params: any) { 57 | const modernParams = {} as any; 58 | for (const k of Object.keys(params)) { 59 | if (k == 'connection') { 60 | modernParams.rpc = rpc(params[k]); 61 | } else if (params[k] instanceof PublicKey || params[k].constructor.name == 'PublicKey') { 62 | modernParams[k] = params[k].toBase58(); 63 | } else if (typeof params[k] == 'number') { 64 | modernParams[k] = BigInt(params[k]); 65 | } else { 66 | modernParams[k] = params[k]; 67 | } 68 | } 69 | 70 | return modernParams; 71 | } 72 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/src/mpl_metadata.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | import { Buffer } from 'buffer'; 3 | 4 | export const MPL_METADATA_PROGRAM_ID = new PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); 5 | 6 | export function findMplMetadataAddress(poolMintAddress: PublicKey) { 7 | const [publicKey] = PublicKey.findProgramAddressSync( 8 | [Buffer.from('metadata'), MPL_METADATA_PROGRAM_ID.toBuffer(), poolMintAddress.toBuffer()], 9 | MPL_METADATA_PROGRAM_ID, 10 | ); 11 | return publicKey; 12 | } 13 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/tests/fixtures/mpl_token_metadata.so: -------------------------------------------------------------------------------- 1 | ../../../../../../stake-pool/program/tests/fixtures/mpl_token_metadata.so -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/tests/fixtures/spl_single_pool.so: -------------------------------------------------------------------------------- 1 | ../../../../../../target/deploy/spl_single_pool.so -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/ts-fixup.sh: -------------------------------------------------------------------------------- 1 | ../../ts-fixup.sh -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/tsconfig-base.json: -------------------------------------------------------------------------------- 1 | ../../tsconfig-base.json -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/tsconfig-cjs.json: -------------------------------------------------------------------------------- 1 | ../../tsconfig-cjs.json -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/classic/tsconfig.json: -------------------------------------------------------------------------------- 1 | ../../tsconfig.json -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .vscode 4 | .idea 5 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | es6: true, 5 | node: true, 6 | jest: true, 7 | }, 8 | extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'], 9 | plugins: ['@typescript-eslint/eslint-plugin'], 10 | parser: '@typescript-eslint/parser', 11 | parserOptions: { 12 | sourceType: 'module', 13 | }, 14 | rules: { 15 | '@typescript-eslint/interface-name-prefix': 'off', 16 | '@typescript-eslint/explicit-function-return-type': 'off', 17 | '@typescript-eslint/explicit-module-boundary-types': 'off', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | '@typescript-eslint/ban-ts-comment': 'off', 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | trailingComma: 'all', 4 | printWidth: 100, 5 | endOfLine: 'lf', 6 | semi: true, 7 | }; 8 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/README.md: -------------------------------------------------------------------------------- 1 | # `@solana/spl-single-pool` 2 | 3 | A TypeScript library for interacting with the SPL Single-Validator Stake Pool program, targeting `@solana/web3.js` 2.0. 4 | **If you are working on the legacy web3.js (if you're not sure, you probably are!), you want `@solana/spl-single-pool-classic`.** 5 | 6 | For information on installation and usage, see [SPL docs](https://spl.solana.com/single-pool). 7 | 8 | For support, please ask questions on the [Solana Stack Exchange](https://solana.stackexchange.com). 9 | 10 | If you've found a bug or you'd like to request a feature, please 11 | [open an issue](https://github.com/solana-labs/solana-program-library/issues/new). 12 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@solana/spl-single-pool", 3 | "version": "1.0.0", 4 | "main": "dist/cjs/index.js", 5 | "module": "dist/mjs/index.js", 6 | "exports": { 7 | ".": { 8 | "import": "./dist/mjs/index.js", 9 | "require": "./dist/cjs/index.js" 10 | } 11 | }, 12 | "scripts": { 13 | "clean": "rm -fr dist/*", 14 | "build": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./ts-fixup.sh", 15 | "lint": "eslint --max-warnings 0 .", 16 | "lint:fix": "eslint . --fix" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^20.12.7", 20 | "@typescript-eslint/eslint-plugin": "^7.8.0", 21 | "eslint": "^8.57.0", 22 | "eslint-config-prettier": "^9.1.0", 23 | "eslint-plugin-prettier": "^5.1.3", 24 | "typescript": "^5.4.5" 25 | }, 26 | "dependencies": { 27 | "@solana/web3.js": "=2.0.0-experimental.21e994f" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/src/index.ts: -------------------------------------------------------------------------------- 1 | import { getAddressCodec } from '@solana/web3.js'; 2 | 3 | import { PoolAddress, VoteAccountAddress } from './addresses.js'; 4 | 5 | export * from './addresses.js'; 6 | export * from './instructions.js'; 7 | export * from './transactions.js'; 8 | 9 | export async function getVoteAccountAddressForPool( 10 | rpc: any, // XXX not exported: Rpc, 11 | poolAddress: PoolAddress, 12 | abortSignal?: AbortSignal, 13 | ): Promise { 14 | const poolAccount = await rpc.getAccountInfo(poolAddress).send(abortSignal); 15 | if (!(poolAccount && poolAccount.data[0] === 1)) { 16 | throw 'invalid pool address'; 17 | } 18 | return getAddressCodec().deserialize(poolAccount.data.slice(1))[0] as VoteAccountAddress; 19 | } 20 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/src/internal.ts: -------------------------------------------------------------------------------- 1 | import { address } from '@solana/web3.js'; 2 | 3 | export const MPL_METADATA_PROGRAM_ID = address('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s'); 4 | -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/ts-fixup.sh: -------------------------------------------------------------------------------- 1 | ../../ts-fixup.sh -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/tsconfig-base.json: -------------------------------------------------------------------------------- 1 | ../../tsconfig-base.json -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/tsconfig-cjs.json: -------------------------------------------------------------------------------- 1 | ../../tsconfig-cjs.json -------------------------------------------------------------------------------- /reflect-single-pool/js/packages/modern/tsconfig.json: -------------------------------------------------------------------------------- 1 | ../../tsconfig.json -------------------------------------------------------------------------------- /reflect-single-pool/js/ts-fixup.sh: -------------------------------------------------------------------------------- 1 | cat >dist/cjs/package.json <dist/mjs/package.json <"] 6 | repository = "https://github.com/solana-labs/solana-program-library" 7 | license = "Apache-2.0" 8 | edition = "2021" 9 | 10 | [features] 11 | no-entrypoint = [] 12 | test-sbf = [] 13 | 14 | [dependencies] 15 | arrayref = "0.3.7" 16 | borsh = "1.5.0" 17 | num-derive = "0.4" 18 | num-traits = "0.2" 19 | num_enum = "0.7.2" 20 | solana-program = ">=1.18.11,<=2" 21 | solana-security-txt = "1.1.1" 22 | spl-token = { version = "4.0", features = [ 23 | "no-entrypoint", 24 | ] } 25 | spl-associated-token-account = { version = "3.0.2", features = [ 26 | "no-entrypoint", 27 | ] } 28 | thiserror = "1.0" 29 | 30 | [dev-dependencies] 31 | solana-program-test = ">=1.18.11,<=2" 32 | solana-sdk = ">=1.18.11,<=2" 33 | solana-vote-program = ">=1.18.11,<=2" 34 | test-case = "3.3" 35 | bincode = "1.3.1" 36 | rand = "0.8.5" 37 | approx = "0.5.1" 38 | 39 | [lib] 40 | crate-type = ["cdylib", "lib"] -------------------------------------------------------------------------------- /reflect-single-pool/program/program-id.md: -------------------------------------------------------------------------------- 1 | rFLUicC93hnZMVZc2hhd4oetXEDG4ja6TaFVSAftsVe -------------------------------------------------------------------------------- /reflect-single-pool/program/src/entrypoint.rs: -------------------------------------------------------------------------------- 1 | //! Program entrypoint 2 | 3 | #![cfg(all(target_os = "solana", not(feature = "no-entrypoint")))] 4 | 5 | use { 6 | crate::{error::ReflectPoolError, processor::Processor}, 7 | solana_program::{ 8 | account_info::AccountInfo, entrypoint::ProgramResult, program_error::PrintProgramError, 9 | pubkey::Pubkey, 10 | }, 11 | solana_security_txt::security_txt, 12 | }; 13 | 14 | solana_program::entrypoint!(process_instruction); 15 | fn process_instruction( 16 | program_id: &Pubkey, 17 | accounts: &[AccountInfo], 18 | instruction_data: &[u8], 19 | ) -> ProgramResult { 20 | if let Err(error) = Processor::process(program_id, accounts, instruction_data) { 21 | // catch the error so we can print it 22 | error.print::(); 23 | Err(error) 24 | } else { 25 | Ok(()) 26 | } 27 | } 28 | 29 | security_txt! { 30 | // Required fields 31 | name: "SPL Single-Validator Stake Pool", 32 | project_url: "https://spl.solana.com/single-pool", 33 | contacts: "link:https://github.com/solana-labs/solana-program-library/security/advisories/new,mailto:security@solana.com,discord:https://discord.gg/solana", 34 | policy: "https://github.com/solana-labs/solana-program-library/blob/master/SECURITY.md", 35 | 36 | // Optional Fields 37 | preferred_languages: "en", 38 | source_code: "https://github.com/solana-labs/solana-program-library/tree/master/single-pool/program", 39 | source_revision: "ef44df985e76a697ee9a8aabb3a223610e4cf1dc", 40 | source_release: "single-pool-v1.0.0", 41 | auditors: "https://github.com/solana-labs/security-audits#single-stake-pool" 42 | } 43 | -------------------------------------------------------------------------------- /reflect-single-pool/program/src/state.rs: -------------------------------------------------------------------------------- 1 | //! State transition types 2 | 3 | use { 4 | crate::{error::ReflectPoolError, find_pool_address}, 5 | borsh::{BorshDeserialize, BorshSchema, BorshSerialize}, 6 | solana_program::{ 7 | account_info::AccountInfo, borsh1::try_from_slice_unchecked, program_error::ProgramError, 8 | pubkey::Pubkey, 9 | }, 10 | }; 11 | 12 | /// Single-Validator Stake Pool account type 13 | #[derive(Clone, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)] 14 | pub enum ReflectPoolAccountType { 15 | /// Uninitialized account 16 | #[default] 17 | Uninitialized, 18 | /// Main pool account 19 | Pool, 20 | } 21 | 22 | /// Single-Validator Stake Pool account, used to derive all PDAs 23 | #[derive(Clone, Debug, Default, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)] 24 | pub struct ReflectPool { 25 | /// Pool account type, reserved for future compat 26 | pub account_type: ReflectPoolAccountType, 27 | /// The vote account this pool is mapped to 28 | pub vote_account_address: Pubkey, 29 | } 30 | impl ReflectPool { 31 | /// Create a ReflectPool struct from its account info 32 | pub fn from_account_info( 33 | account_info: &AccountInfo, 34 | program_id: &Pubkey, 35 | ) -> Result { 36 | // pool is allocated and owned by this program 37 | if account_info.data_len() == 0 || account_info.owner != program_id { 38 | return Err(ReflectPoolError::InvalidPoolAccount.into()); 39 | } 40 | 41 | let pool = try_from_slice_unchecked::(&account_info.data.borrow())?; 42 | 43 | // pool is well-typed 44 | if pool.account_type != ReflectPoolAccountType::Pool { 45 | return Err(ReflectPoolError::InvalidPoolAccount.into()); 46 | } 47 | 48 | // pool vote account address is properly configured. in practice this is 49 | // irrefutable because the pool is initialized from the address that 50 | // derives it, and never modified 51 | if *account_info.key != find_pool_address(program_id, &pool.vote_account_address) { 52 | return Err(ReflectPoolError::InvalidPoolAccount.into()); 53 | } 54 | 55 | Ok(pool) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /reflect-single-pool/program/tests/create_pool_token_metadata.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::arithmetic_side_effects)] 2 | #![cfg(feature = "test-sbf")] 3 | 4 | mod helpers; 5 | 6 | use { 7 | helpers::*, 8 | solana_program_test::*, 9 | solana_sdk::{ 10 | instruction::InstructionError, pubkey::Pubkey, signature::Signer, 11 | system_instruction::SystemError, transaction::Transaction, 12 | }, 13 | reflect_single_pool::{id, instruction}, 14 | }; 15 | 16 | fn assert_metadata(vote_account: &Pubkey, metadata: &Metadata) { 17 | let vote_address_str = vote_account.to_string(); 18 | let name = format!("SPL Single Pool (via Reflect Program) {}", &vote_address_str[0..15]); 19 | let symbol = format!("st{}", &vote_address_str[0..7]); 20 | 21 | assert!(metadata.name.starts_with(&name)); 22 | assert!(metadata.symbol.starts_with(&symbol)); 23 | } 24 | 25 | #[tokio::test] 26 | async fn success() { 27 | let mut context = program_test(false).start_with_context().await; 28 | let accounts = ReflectPoolAccounts::default(); 29 | accounts.initialize(&mut context).await; 30 | 31 | let metadata = get_metadata_account(&mut context.banks_client, &accounts.mint).await; 32 | assert_metadata(&accounts.vote_account.pubkey(), &metadata); 33 | } 34 | 35 | #[tokio::test] 36 | async fn fail_double_init() { 37 | let mut context = program_test(false).start_with_context().await; 38 | let accounts = ReflectPoolAccounts::default(); 39 | accounts.initialize(&mut context).await; 40 | refresh_blockhash(&mut context).await; 41 | 42 | let instruction = 43 | instruction::create_token_metadata(&id(), &accounts.pool, &context.payer.pubkey()); 44 | let transaction = Transaction::new_signed_with_payer( 45 | &[instruction], 46 | Some(&context.payer.pubkey()), 47 | &[&context.payer], 48 | context.last_blockhash, 49 | ); 50 | 51 | let e = context 52 | .banks_client 53 | .process_transaction(transaction) 54 | .await 55 | .unwrap_err(); 56 | check_error::(e, SystemError::AccountAlreadyInUse.into()); 57 | } 58 | -------------------------------------------------------------------------------- /reflect-single-pool/program/tests/fixtures/mpl_token_metadata.so: -------------------------------------------------------------------------------- 1 | ../../../../stake-pool/program/tests/fixtures/mpl_token_metadata.so -------------------------------------------------------------------------------- /reflect-single-pool/program/tests/helpers/token.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | use { 4 | borsh::BorshDeserialize, 5 | solana_program_test::BanksClient, 6 | solana_sdk::{ 7 | borsh1::try_from_slice_unchecked, 8 | hash::Hash, 9 | program_pack::Pack, 10 | pubkey::Pubkey, 11 | signature::{Keypair, Signer}, 12 | transaction::Transaction, 13 | }, 14 | spl_associated_token_account as atoken, 15 | reflect_single_pool::inline_mpl_token_metadata::pda::find_metadata_account, 16 | spl_token::state::{Account, Mint}, 17 | }; 18 | 19 | pub async fn create_ata( 20 | banks_client: &mut BanksClient, 21 | payer: &Keypair, 22 | owner: &Pubkey, 23 | recent_blockhash: &Hash, 24 | pool_mint: &Pubkey, 25 | ) { 26 | let instruction = atoken::instruction::create_associated_token_account( 27 | &payer.pubkey(), 28 | owner, 29 | pool_mint, 30 | &spl_token::id(), 31 | ); 32 | let transaction = Transaction::new_signed_with_payer( 33 | &[instruction], 34 | Some(&payer.pubkey()), 35 | &[payer], 36 | *recent_blockhash, 37 | ); 38 | 39 | banks_client.process_transaction(transaction).await.unwrap(); 40 | } 41 | 42 | pub async fn get_token_balance(banks_client: &mut BanksClient, token: &Pubkey) -> u64 { 43 | let token_account = banks_client.get_account(*token).await.unwrap().unwrap(); 44 | let account_info = Account::unpack_from_slice(&token_account.data).unwrap(); 45 | account_info.amount 46 | } 47 | 48 | pub async fn get_token_supply(banks_client: &mut BanksClient, mint: &Pubkey) -> u64 { 49 | let mint_account = banks_client.get_account(*mint).await.unwrap().unwrap(); 50 | let account_info = Mint::unpack_from_slice(&mint_account.data).unwrap(); 51 | account_info.supply 52 | } 53 | 54 | #[derive(Clone, BorshDeserialize, Debug, PartialEq, Eq)] 55 | pub struct Metadata { 56 | pub key: u8, 57 | pub update_authority: Pubkey, 58 | pub mint: Pubkey, 59 | pub name: String, 60 | pub symbol: String, 61 | pub uri: String, 62 | pub seller_fee_basis_points: u16, 63 | pub creators: Option>, 64 | pub primary_sale_happened: bool, 65 | pub is_mutable: bool, 66 | } 67 | 68 | pub async fn get_metadata_account(banks_client: &mut BanksClient, token_mint: &Pubkey) -> Metadata { 69 | let (token_metadata, _) = find_metadata_account(token_mint); 70 | let token_metadata_account = banks_client 71 | .get_account(token_metadata) 72 | .await 73 | .unwrap() 74 | .unwrap(); 75 | try_from_slice_unchecked(token_metadata_account.data.as_slice()).unwrap() 76 | } 77 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/.gitignore: -------------------------------------------------------------------------------- 1 | .crates 2 | .anchor 3 | .DS_Store 4 | .idea 5 | target 6 | **/*.rs.bk 7 | node_modules 8 | test-ledger 9 | .yarn 10 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/.prettierignore: -------------------------------------------------------------------------------- 1 | 2 | .anchor 3 | .DS_Store 4 | target 5 | node_modules 6 | dist 7 | build 8 | test-ledger 9 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/.solitarc.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const programDir = path.join(__dirname, '.', 'programs/reflect-tokenised-bonds'); 3 | const idlDir = path.join(__dirname, 'idl'); 4 | const sdkDir = path.join(__dirname, 'sdk/src'); 5 | const binaryInstallDir = path.join(__dirname, '.crates'); 6 | 7 | module.exports = { 8 | idlGenerator: 'anchor', 9 | programName: 'reflect_tokenised_bonds', 10 | programId: '6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop', 11 | idlDir, 12 | sdkDir, 13 | binaryInstallDir, 14 | programDir, 15 | }; -------------------------------------------------------------------------------- /reflect-tokenised-bonds/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | 3 | [features] 4 | seeds = false 5 | skip-lint = false 6 | 7 | [programs.localnet] 8 | reflect_tokenised_bonds = "6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop" 9 | 10 | [registry] 11 | url = "https://api.apr.dev" 12 | 13 | [provider] 14 | cluster = "Localnet" 15 | #wallet = "/Users/nico/.config/solana/id.json" 16 | wallet = "/Users/kubaplata/.config/solana/id.json" 17 | 18 | [scripts] 19 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 20 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | 6 | [profile.release] 7 | overflow-checks = true 8 | lto = "fat" 9 | codegen-units = 1 10 | [profile.release.build-override] 11 | opt-level = 3 12 | incremental = false 13 | codegen-units = 1 14 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/README.md: -------------------------------------------------------------------------------- 1 | # 🏦 2 | # Tokenised Bonds 3 | The 'Reflect-Tokenised-Bonds' or **RTB** program is designed to provide a permissionless primitive for protocols or communities wishing to issue composable *'liquid staked'* bonds. 4 | 5 | ### ⚙️ Features of an Internet Bond 6 | 7 | - Secured Deposits (only the depositor can manage their funds) 8 | - A Liquid Receipt Token (representing your deposit & accrued yield) 9 | - A Public Target Interest Rate (determined by the treasurer, and ensured by depositors experience of yield.) 10 | - The Interest Pool (reward pool) which is a one-way distribution pool meaning treasurer cannot reduce accrued yield. 11 | 12 | ### Composable & Permissionless Primitive 🤝 13 | 14 | The RTB program can be used by anyone who wishes to launch a vault. Simply call the two initialize instructions to get started {create_vault, init_vault_pools} 15 | 16 | *the program takes zero fees to operate, for treasurers or depositors.* 17 | 18 | ### Read More 19 | 20 | [📚 GitBook - Tokenised Yield Bonds](https://linktodocumentation) 21 | 22 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/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 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/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.29.0", 8 | "@metaplex-foundation/solita": "^0.20.1", 9 | "@solana/spl-token": "^0.4.6", 10 | "@solana/web3.js": "^1.91.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 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reflect-tokenised-bonds" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "reflect_tokenised_bonds" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | 18 | [dependencies] 19 | anchor-lang = { version = "0.29.0", features = [ "init-if-needed" ] } 20 | anchor-spl = "0.29.0" 21 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/constants/mod.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[constant] 4 | pub const CONFIG_SEED: &str = "config"; 5 | 6 | #[constant] 7 | pub const ADMIN_SEED: &str = "admin"; 8 | 9 | #[constant] 10 | pub const VAULT_SEED: &str = "vault"; 11 | 12 | #[constant] 13 | pub const VAULT_POOL_SEED: &str = "vault_pool"; -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/errors/errors.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[error_code] 4 | pub enum ReflectError { 5 | #[msg("Invalid transaction signer.")] 6 | InvalidSigner, 7 | 8 | #[msg("ProgramAccountsMismatch")] 9 | ProgramAccountsMismatch, 10 | 11 | #[msg("InvalidReceiptTokenSupply")] 12 | InvalidReceiptTokenSupply, 13 | 14 | #[msg("InvalidReceiptTokenMintAuthority")] 15 | InvalidReceiptTokenMintAuthority, 16 | 17 | #[msg("InvalidReceiptTokenFreezeAuthority")] 18 | InvalidReceiptTokenFreezeAuthority, 19 | 20 | #[msg("InvalidReceiptTokenSetup")] 21 | InvalidReceiptTokenSetup, 22 | 23 | #[msg("InvalidReceiptTokenDecimals")] 24 | InvalidReceiptTokenDecimals, 25 | 26 | #[msg("ZeroDivision")] 27 | ZeroDivision, 28 | 29 | #[msg("MathOverflow")] 30 | MathOverflow, 31 | 32 | #[msg("MissingAccounts")] 33 | MissingAccounts, 34 | 35 | #[msg("AmountTooLow")] 36 | AmountTooLow 37 | } 38 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/errors/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod errors; 2 | pub use errors::*; -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/instructions/initialize.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::constants::{ 3 | CONFIG_SEED, 4 | ADMIN_SEED 5 | }; 6 | use crate::program::ReflectTokenisedBonds; 7 | use crate::state::{ 8 | Admin, 9 | Config, 10 | Permissions 11 | }; 12 | use crate::errors::ReflectError; 13 | 14 | pub fn initialize( 15 | ctx: Context 16 | ) -> Result<()> { 17 | let Initialize { 18 | signer, 19 | admin, 20 | config, 21 | program: _, 22 | program_data: __, 23 | system_program: ___ 24 | } = ctx.accounts; 25 | 26 | config.set_inner(Config { 27 | bump: ctx.bumps.config, 28 | vaults: 0, 29 | frozen: false, 30 | }); 31 | 32 | admin.set_inner(Admin { 33 | pubkey: signer.key(), 34 | permissions: vec![ 35 | Permissions::Superadmin 36 | ] 37 | }); 38 | 39 | Ok(()) 40 | } 41 | 42 | #[derive(Accounts)] 43 | pub struct Initialize<'info> { 44 | #[account( 45 | mut 46 | )] 47 | pub signer: Signer<'info>, 48 | 49 | #[account( 50 | init, 51 | payer = signer, 52 | space = Admin::INIT_SPACE, 53 | seeds = [ 54 | ADMIN_SEED.as_bytes(), 55 | signer.key().as_ref() 56 | ], 57 | bump 58 | )] 59 | pub admin: Account<'info, Admin>, 60 | 61 | #[account( 62 | init, 63 | seeds = [ 64 | CONFIG_SEED.as_bytes() 65 | ], 66 | bump, 67 | space = 8 + Config::INIT_SPACE, 68 | payer = signer, 69 | )] 70 | pub config: Account<'info, Config>, 71 | 72 | #[account()] 73 | pub system_program: Program<'info, System>, 74 | 75 | #[account()] 76 | pub program: Program<'info, ReflectTokenisedBonds>, 77 | 78 | #[account( 79 | constraint = program 80 | .programdata_address()? 81 | .is_some_and(|result| result.eq(&program_data.key())) @ ReflectError::ProgramAccountsMismatch, 82 | 83 | constraint = program_data.upgrade_authority_address.eq(&Some(signer.key())) @ ReflectError::InvalidSigner 84 | )] 85 | pub program_data: Account<'info, ProgramData>, 86 | } -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod initialize; 2 | pub use initialize::*; 3 | 4 | pub mod create_vault; 5 | pub use create_vault::*; 6 | 7 | pub mod deposit; 8 | pub use deposit::*; 9 | 10 | pub mod withdraw; 11 | pub use withdraw::*; 12 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | pub mod errors; 4 | pub mod instructions; 5 | pub mod state; 6 | pub mod constants; 7 | 8 | use instructions::*; 9 | 10 | declare_id!("6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop"); 11 | 12 | #[program] 13 | mod reflect_tokenised_bonds { 14 | use super::*; 15 | 16 | pub fn initialize( 17 | ctx: Context 18 | ) -> Result<()> { 19 | instructions::initialize(ctx) 20 | } 21 | 22 | pub fn create_vault( 23 | ctx: Context, 24 | ) -> Result<()> { 25 | instructions::create_vault(ctx) 26 | } 27 | 28 | pub fn deposit( 29 | ctx: Context, 30 | args: DepositArgs 31 | ) -> Result<()> { 32 | instructions::deposit(ctx, args) 33 | } 34 | 35 | pub fn withdraw( 36 | ctx: Context, 37 | args: WithdrawArgs 38 | ) -> Result<()> { 39 | instructions::withdraw(ctx, args) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/state/admin.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[derive(AnchorDeserialize, AnchorSerialize, Clone, InitSpace)] 4 | pub enum Permissions { 5 | InitializeVaults, 6 | Freeze, 7 | // FreezeReceiptToken, 8 | Superadmin 9 | } 10 | 11 | #[account] 12 | #[derive(InitSpace)] 13 | pub struct Admin { 14 | pub pubkey: Pubkey, 15 | #[max_len(5)] 16 | pub permissions: Vec 17 | } -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/state/config.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[account] 4 | #[derive(InitSpace)] 5 | pub struct Config { 6 | pub bump: u8, 7 | pub vaults: u64, 8 | pub frozen: bool, 9 | } -------------------------------------------------------------------------------- /reflect-tokenised-bonds/programs/reflect-tokenised-bonds/src/state/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod vault; 2 | pub use vault::*; 3 | 4 | pub mod config; 5 | pub use config::*; 6 | 7 | pub mod admin; 8 | pub use admin::*; 9 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .env 3 | yarn.lock 4 | ./src 5 | package-lock.json 6 | ./src/setup 7 | /node_modules -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/accounts/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './LockupState'; 2 | export * from './RTBProtocol'; 3 | export * from './UserAccount'; 4 | export * from './Vault'; 5 | import { LockupState } from './LockupState'; 6 | import { RTBProtocol } from './RTBProtocol'; 7 | import { UserAccount } from './UserAccount'; 8 | import { Vault } from './Vault'; 9 | export declare const accountProviders: { 10 | LockupState: typeof LockupState; 11 | RTBProtocol: typeof RTBProtocol; 12 | UserAccount: typeof UserAccount; 13 | Vault: typeof Vault; 14 | }; 15 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/accounts/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.accountProviders = void 0; 18 | __exportStar(require("./LockupState"), exports); 19 | __exportStar(require("./RTBProtocol"), exports); 20 | __exportStar(require("./UserAccount"), exports); 21 | __exportStar(require("./Vault"), exports); 22 | const LockupState_1 = require("./LockupState"); 23 | const RTBProtocol_1 = require("./RTBProtocol"); 24 | const UserAccount_1 = require("./UserAccount"); 25 | const Vault_1 = require("./Vault"); 26 | exports.accountProviders = { LockupState: LockupState_1.LockupState, RTBProtocol: RTBProtocol_1.RTBProtocol, UserAccount: UserAccount_1.UserAccount, Vault: Vault_1.Vault }; 27 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/errors/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | type ErrorWithCode = Error & { 8 | code: number; 9 | }; 10 | type MaybeErrorWithCode = ErrorWithCode | null | undefined; 11 | /** 12 | * InvalidVaultSeed: 'Vault PDA is derived with invalid vault seed.' 13 | * 14 | * @category Errors 15 | * @category generated 16 | */ 17 | export declare class InvalidVaultSeedError extends Error { 18 | readonly code: number; 19 | readonly name: string; 20 | constructor(); 21 | } 22 | /** 23 | * InsufficientDeposit: 'Insufficient deposit amount.' 24 | * 25 | * @category Errors 26 | * @category generated 27 | */ 28 | export declare class InsufficientDepositError extends Error { 29 | readonly code: number; 30 | readonly name: string; 31 | constructor(); 32 | } 33 | /** 34 | * LockupNotExpired: 'Lockup period has not expired.' 35 | * 36 | * @category Errors 37 | * @category generated 38 | */ 39 | export declare class LockupNotExpiredError extends Error { 40 | readonly code: number; 41 | readonly name: string; 42 | constructor(); 43 | } 44 | /** 45 | * InvalidMintAuthority: 'Invalid mint authority. Move mint authority of the receipt token to the vault PDA.' 46 | * 47 | * @category Errors 48 | * @category generated 49 | */ 50 | export declare class InvalidMintAuthorityError extends Error { 51 | readonly code: number; 52 | readonly name: string; 53 | constructor(); 54 | } 55 | /** 56 | * InvalidFreezeAuthority: 'Invalid freeze authority. Move freeze authority of the receipt token to the vault PDA, or remove it completely.' 57 | * 58 | * @category Errors 59 | * @category generated 60 | */ 61 | export declare class InvalidFreezeAuthorityError extends Error { 62 | readonly code: number; 63 | readonly name: string; 64 | constructor(); 65 | } 66 | /** 67 | * NonZeroReceiptSupply: 'Supply of the receipt token has to be 0. Pre-minting is not allowed.' 68 | * 69 | * @category Errors 70 | * @category generated 71 | */ 72 | export declare class NonZeroReceiptSupplyError extends Error { 73 | readonly code: number; 74 | readonly name: string; 75 | constructor(); 76 | } 77 | /** 78 | * Attempts to resolve a custom program error from the provided error code. 79 | * @category Errors 80 | * @category generated 81 | */ 82 | export declare function errorFromCode(code: number): MaybeErrorWithCode; 83 | /** 84 | * Attempts to resolve a custom program error from the provided error name, i.e. 'Unauthorized'. 85 | * @category Errors 86 | * @category generated 87 | */ 88 | export declare function errorFromName(name: string): MaybeErrorWithCode; 89 | export {}; 90 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js'; 2 | export * from './accounts'; 3 | export * from './errors'; 4 | export * from './instructions'; 5 | /** 6 | * Program address 7 | * 8 | * @category constants 9 | * @category generated 10 | */ 11 | export declare const PROGRAM_ADDRESS = "6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop"; 12 | /** 13 | * Program public key 14 | * 15 | * @category constants 16 | * @category generated 17 | */ 18 | export declare const PROGRAM_ID: PublicKey; 19 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.PROGRAM_ID = exports.PROGRAM_ADDRESS = void 0; 18 | const web3_js_1 = require("@solana/web3.js"); 19 | __exportStar(require("./accounts"), exports); 20 | __exportStar(require("./errors"), exports); 21 | __exportStar(require("./instructions"), exports); 22 | /** 23 | * Program address 24 | * 25 | * @category constants 26 | * @category generated 27 | */ 28 | exports.PROGRAM_ADDRESS = '6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop'; 29 | /** 30 | * Program public key 31 | * 32 | * @category constants 33 | * @category generated 34 | */ 35 | exports.PROGRAM_ID = new web3_js_1.PublicKey(exports.PROGRAM_ADDRESS); 36 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/createVault.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category CreateVault 12 | * @category generated 13 | */ 14 | export type CreateVaultInstructionArgs = { 15 | minDeposit: beet.bignum; 16 | minLockup: beet.bignum; 17 | targetYieldRate: beet.bignum; 18 | vaultSeed: beet.bignum; 19 | }; 20 | /** 21 | * @category Instructions 22 | * @category CreateVault 23 | * @category generated 24 | */ 25 | export declare const createVaultStruct: beet.BeetArgsStruct; 28 | /** 29 | * Accounts required by the _createVault_ instruction 30 | * 31 | * @property [_writable_, **signer**] admin 32 | * @property [_writable_] rtbProtocol 33 | * @property [_writable_] vault 34 | * @category Instructions 35 | * @category CreateVault 36 | * @category generated 37 | */ 38 | export type CreateVaultInstructionAccounts = { 39 | admin: web3.PublicKey; 40 | rtbProtocol: web3.PublicKey; 41 | vault: web3.PublicKey; 42 | systemProgram?: web3.PublicKey; 43 | rent?: web3.PublicKey; 44 | anchorRemainingAccounts?: web3.AccountMeta[]; 45 | }; 46 | export declare const createVaultInstructionDiscriminator: number[]; 47 | /** 48 | * Creates a _CreateVault_ instruction. 49 | * 50 | * @param accounts that will be accessed while the instruction is processed 51 | * @param args to provide as instruction data to the program 52 | * 53 | * @category Instructions 54 | * @category CreateVault 55 | * @category generated 56 | */ 57 | export declare function createCreateVaultInstruction(accounts: CreateVaultInstructionAccounts, args: CreateVaultInstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction; 58 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/deposit.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category Deposit 12 | * @category generated 13 | */ 14 | export type DepositInstructionArgs = { 15 | amount: beet.bignum; 16 | vaultId: beet.bignum; 17 | }; 18 | /** 19 | * @category Instructions 20 | * @category Deposit 21 | * @category generated 22 | */ 23 | export declare const depositStruct: beet.BeetArgsStruct; 26 | /** 27 | * Accounts required by the _deposit_ instruction 28 | * 29 | * @property [_writable_, **signer**] user 30 | * @property [_writable_] vault 31 | * @property [_writable_] depositTokenAccount 32 | * @property [_writable_] receiptTokenAccount 33 | * @property [_writable_] rewardPool 34 | * @property [_writable_] depositPool 35 | * @property [_writable_] receiptTokenMint 36 | * @category Instructions 37 | * @category Deposit 38 | * @category generated 39 | */ 40 | export type DepositInstructionAccounts = { 41 | user: web3.PublicKey; 42 | vault: web3.PublicKey; 43 | depositTokenAccount: web3.PublicKey; 44 | receiptTokenAccount: web3.PublicKey; 45 | rewardPool: web3.PublicKey; 46 | depositPool: web3.PublicKey; 47 | receiptTokenMint: web3.PublicKey; 48 | tokenProgram?: web3.PublicKey; 49 | anchorRemainingAccounts?: web3.AccountMeta[]; 50 | }; 51 | export declare const depositInstructionDiscriminator: number[]; 52 | /** 53 | * Creates a _Deposit_ instruction. 54 | * 55 | * @param accounts that will be accessed while the instruction is processed 56 | * @param args to provide as instruction data to the program 57 | * 58 | * @category Instructions 59 | * @category Deposit 60 | * @category generated 61 | */ 62 | export declare function createDepositInstruction(accounts: DepositInstructionAccounts, args: DepositInstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction; 63 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './createVault'; 2 | export * from './deposit'; 3 | export * from './initVaultPools'; 4 | export * from './initializeProtocol'; 5 | export * from './lockup'; 6 | export * from './withdraw'; 7 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./createVault"), exports); 18 | __exportStar(require("./deposit"), exports); 19 | __exportStar(require("./initVaultPools"), exports); 20 | __exportStar(require("./initializeProtocol"), exports); 21 | __exportStar(require("./lockup"), exports); 22 | __exportStar(require("./withdraw"), exports); 23 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/initVaultPools.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category InitVaultPools 12 | * @category generated 13 | */ 14 | export type InitVaultPoolsInstructionArgs = { 15 | vaultSeed: beet.bignum; 16 | }; 17 | /** 18 | * @category Instructions 19 | * @category InitVaultPools 20 | * @category generated 21 | */ 22 | export declare const initVaultPoolsStruct: beet.BeetArgsStruct; 25 | /** 26 | * Accounts required by the _initVaultPools_ instruction 27 | * 28 | * @property [_writable_, **signer**] admin 29 | * @property [_writable_] vault 30 | * @property [_writable_] depositPool 31 | * @property [_writable_] rewardPool 32 | * @property [_writable_] depositTokenMint 33 | * @property [_writable_] receiptTokenMint 34 | * @category Instructions 35 | * @category InitVaultPools 36 | * @category generated 37 | */ 38 | export type InitVaultPoolsInstructionAccounts = { 39 | admin: web3.PublicKey; 40 | vault: web3.PublicKey; 41 | depositPool: web3.PublicKey; 42 | rewardPool: web3.PublicKey; 43 | depositTokenMint: web3.PublicKey; 44 | receiptTokenMint: web3.PublicKey; 45 | systemProgram?: web3.PublicKey; 46 | tokenProgram?: web3.PublicKey; 47 | rent?: web3.PublicKey; 48 | anchorRemainingAccounts?: web3.AccountMeta[]; 49 | }; 50 | export declare const initVaultPoolsInstructionDiscriminator: number[]; 51 | /** 52 | * Creates a _InitVaultPools_ instruction. 53 | * 54 | * @param accounts that will be accessed while the instruction is processed 55 | * @param args to provide as instruction data to the program 56 | * 57 | * @category Instructions 58 | * @category InitVaultPools 59 | * @category generated 60 | */ 61 | export declare function createInitVaultPoolsInstruction(accounts: InitVaultPoolsInstructionAccounts, args: InitVaultPoolsInstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction; 62 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/initializeProtocol.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category InitializeProtocol 12 | * @category generated 13 | */ 14 | export declare const initializeProtocolStruct: beet.BeetArgsStruct<{ 15 | instructionDiscriminator: number[]; 16 | }>; 17 | /** 18 | * Accounts required by the _initializeProtocol_ instruction 19 | * 20 | * @property [_writable_, **signer**] payer 21 | * @property [_writable_] rtbProtocol 22 | * @category Instructions 23 | * @category InitializeProtocol 24 | * @category generated 25 | */ 26 | export type InitializeProtocolInstructionAccounts = { 27 | payer: web3.PublicKey; 28 | rtbProtocol: web3.PublicKey; 29 | systemProgram?: web3.PublicKey; 30 | anchorRemainingAccounts?: web3.AccountMeta[]; 31 | }; 32 | export declare const initializeProtocolInstructionDiscriminator: number[]; 33 | /** 34 | * Creates a _InitializeProtocol_ instruction. 35 | * 36 | * @param accounts that will be accessed while the instruction is processed 37 | * @category Instructions 38 | * @category InitializeProtocol 39 | * @category generated 40 | */ 41 | export declare function createInitializeProtocolInstruction(accounts: InitializeProtocolInstructionAccounts, programId?: web3.PublicKey): web3.TransactionInstruction; 42 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/lockup.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category Lockup 12 | * @category generated 13 | */ 14 | export type LockupInstructionArgs = { 15 | receiptAmount: beet.bignum; 16 | }; 17 | /** 18 | * @category Instructions 19 | * @category Lockup 20 | * @category generated 21 | */ 22 | export declare const lockupStruct: beet.BeetArgsStruct; 25 | /** 26 | * Accounts required by the _lockup_ instruction 27 | * 28 | * @property [_writable_, **signer**] user 29 | * @property [_writable_] userAccount 30 | * @property [_writable_] vault 31 | * @property [_writable_] lockup 32 | * @property [_writable_] userReceiptTokenAccount 33 | * @property [_writable_] lockupReceiptTokenAccount 34 | * @property [] clock 35 | * @category Instructions 36 | * @category Lockup 37 | * @category generated 38 | */ 39 | export type LockupInstructionAccounts = { 40 | user: web3.PublicKey; 41 | userAccount: web3.PublicKey; 42 | vault: web3.PublicKey; 43 | lockup: web3.PublicKey; 44 | userReceiptTokenAccount: web3.PublicKey; 45 | lockupReceiptTokenAccount: web3.PublicKey; 46 | tokenProgram?: web3.PublicKey; 47 | systemProgram?: web3.PublicKey; 48 | clock: web3.PublicKey; 49 | anchorRemainingAccounts?: web3.AccountMeta[]; 50 | }; 51 | export declare const lockupInstructionDiscriminator: number[]; 52 | /** 53 | * Creates a _Lockup_ instruction. 54 | * 55 | * @param accounts that will be accessed while the instruction is processed 56 | * @param args to provide as instruction data to the program 57 | * 58 | * @category Instructions 59 | * @category Lockup 60 | * @category generated 61 | */ 62 | export declare function createLockupInstruction(accounts: LockupInstructionAccounts, args: LockupInstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction; 63 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/dist/instructions/withdraw.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | import * as beet from '@metaplex-foundation/beet'; 8 | import * as web3 from '@solana/web3.js'; 9 | /** 10 | * @category Instructions 11 | * @category Withdraw 12 | * @category generated 13 | */ 14 | export type WithdrawInstructionArgs = { 15 | lockupId: beet.bignum; 16 | vaultId: beet.bignum; 17 | }; 18 | /** 19 | * @category Instructions 20 | * @category Withdraw 21 | * @category generated 22 | */ 23 | export declare const withdrawStruct: beet.BeetArgsStruct; 26 | /** 27 | * Accounts required by the _withdraw_ instruction 28 | * 29 | * @property [_writable_, **signer**] user 30 | * @property [_writable_] lockup 31 | * @property [_writable_] vault 32 | * @property [_writable_] lockupReceiptTokenAccount 33 | * @property [_writable_] userDepositTokenAccount 34 | * @property [_writable_] depositPool 35 | * @property [_writable_] rewardPool 36 | * @property [_writable_] receiptMint 37 | * @category Instructions 38 | * @category Withdraw 39 | * @category generated 40 | */ 41 | export type WithdrawInstructionAccounts = { 42 | user: web3.PublicKey; 43 | lockup: web3.PublicKey; 44 | vault: web3.PublicKey; 45 | lockupReceiptTokenAccount: web3.PublicKey; 46 | userDepositTokenAccount: web3.PublicKey; 47 | depositPool: web3.PublicKey; 48 | rewardPool: web3.PublicKey; 49 | receiptMint: web3.PublicKey; 50 | tokenProgram?: web3.PublicKey; 51 | anchorRemainingAccounts?: web3.AccountMeta[]; 52 | }; 53 | export declare const withdrawInstructionDiscriminator: number[]; 54 | /** 55 | * Creates a _Withdraw_ instruction. 56 | * 57 | * @param accounts that will be accessed while the instruction is processed 58 | * @param args to provide as instruction data to the program 59 | * 60 | * @category Instructions 61 | * @category Withdraw 62 | * @category generated 63 | */ 64 | export declare function createWithdrawInstruction(accounts: WithdrawInstructionAccounts, args: WithdrawInstructionArgs, programId?: web3.PublicKey): web3.TransactionInstruction; 65 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reflectcx/tokenised-bond", 3 | "version": "1.0.1", 4 | "author": "zkchakra @ Palindrome Engineering", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/palindrome-eng/reflect-program-library.git" 8 | }, 9 | "dependencies": { 10 | "@metaplex-foundation/beet": "^0.7.2", 11 | "@metaplex-foundation/beet-solana": "^0.4.1", 12 | "@solana/web3.js": "1.97.0" 13 | }, 14 | "license": "MIT", 15 | "main": "./src/index.js", 16 | "module": "./dist/index.js", 17 | "types": "./dist/index.d.ts", 18 | "files": [ 19 | "/dist" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/src/accounts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LockupState' 2 | export * from './RTBProtocol' 3 | export * from './UserAccount' 4 | export * from './Vault' 5 | 6 | import { LockupState } from './LockupState' 7 | import { RTBProtocol } from './RTBProtocol' 8 | import { UserAccount } from './UserAccount' 9 | import { Vault } from './Vault' 10 | 11 | export const accountProviders = { LockupState, RTBProtocol, UserAccount, Vault } 12 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js' 2 | export * from './accounts' 3 | export * from './errors' 4 | export * from './instructions' 5 | 6 | /** 7 | * Program address 8 | * 9 | * @category constants 10 | * @category generated 11 | */ 12 | export const PROGRAM_ADDRESS = '6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop' 13 | 14 | /** 15 | * Program public key 16 | * 17 | * @category constants 18 | * @category generated 19 | */ 20 | export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS) 21 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/src/instructions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createVault' 2 | export * from './deposit' 3 | export * from './initVaultPools' 4 | export * from './initializeProtocol' 5 | export * from './lockup' 6 | export * from './withdraw' 7 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/src/instructions/initializeProtocol.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | import * as web3 from '@solana/web3.js' 10 | 11 | /** 12 | * @category Instructions 13 | * @category InitializeProtocol 14 | * @category generated 15 | */ 16 | export const initializeProtocolStruct = new beet.BeetArgsStruct<{ 17 | instructionDiscriminator: number[] /* size: 8 */ 18 | }>( 19 | [['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)]], 20 | 'InitializeProtocolInstructionArgs' 21 | ) 22 | /** 23 | * Accounts required by the _initializeProtocol_ instruction 24 | * 25 | * @property [_writable_, **signer**] payer 26 | * @property [_writable_] rtbProtocol 27 | * @category Instructions 28 | * @category InitializeProtocol 29 | * @category generated 30 | */ 31 | export type InitializeProtocolInstructionAccounts = { 32 | payer: web3.PublicKey 33 | rtbProtocol: web3.PublicKey 34 | systemProgram?: web3.PublicKey 35 | anchorRemainingAccounts?: web3.AccountMeta[] 36 | } 37 | 38 | export const initializeProtocolInstructionDiscriminator = [ 39 | 188, 233, 252, 106, 134, 146, 202, 91, 40 | ] 41 | 42 | /** 43 | * Creates a _InitializeProtocol_ instruction. 44 | * 45 | * @param accounts that will be accessed while the instruction is processed 46 | * @category Instructions 47 | * @category InitializeProtocol 48 | * @category generated 49 | */ 50 | export function createInitializeProtocolInstruction( 51 | accounts: InitializeProtocolInstructionAccounts, 52 | programId = new web3.PublicKey('6ZZ1sxKGuXUBL8HSsHqHaYCg92G9VhMNTcJv1gFURCop') 53 | ) { 54 | const [data] = initializeProtocolStruct.serialize({ 55 | instructionDiscriminator: initializeProtocolInstructionDiscriminator, 56 | }) 57 | const keys: web3.AccountMeta[] = [ 58 | { 59 | pubkey: accounts.payer, 60 | isWritable: true, 61 | isSigner: true, 62 | }, 63 | { 64 | pubkey: accounts.rtbProtocol, 65 | isWritable: true, 66 | isSigner: false, 67 | }, 68 | { 69 | pubkey: accounts.systemProgram ?? web3.SystemProgram.programId, 70 | isWritable: false, 71 | isSigner: false, 72 | }, 73 | ] 74 | 75 | if (accounts.anchorRemainingAccounts != null) { 76 | for (const acc of accounts.anchorRemainingAccounts) { 77 | keys.push(acc) 78 | } 79 | } 80 | 81 | const ix = new web3.TransactionInstruction({ 82 | programId, 83 | keys, 84 | data, 85 | }) 86 | return ix 87 | } 88 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": false, 6 | "skipLibCheck": true, 7 | "declaration": true, 8 | "typeRoots": ["./node_modules/@types"], 9 | "lib": ["es2015"], 10 | "module": "commonjs", 11 | "target": "es2016", 12 | "esModuleInterop": true 13 | }, 14 | "include": [ 15 | "./src/**/*" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /reflect-tokenised-bonds/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 | -------------------------------------------------------------------------------- /ssm/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palindrome-eng/reflect-program-library/5f4f49df98017fb85ec8a75b3626b7aaabdf203f/ssm/.DS_Store -------------------------------------------------------------------------------- /ssm/solana-stake-market/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palindrome-eng/reflect-program-library/5f4f49df98017fb85ec8a75b3626b7aaabdf203f/ssm/solana-stake-market/.DS_Store -------------------------------------------------------------------------------- /ssm/solana-stake-market/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | node_modules/ 3 | dist/ 4 | .idea/ 5 | target/ 6 | *~ 7 | *.swp 8 | *.swo 9 | .anchor 10 | test-ledger 11 | examples/*/Cargo.lock 12 | examples/**/Cargo.lock 13 | tests/*/Cargo.lock 14 | tests/**/Cargo.lock 15 | tests/*/yarn.lock 16 | tests/**/yarn.lock 17 | .DS_Store 18 | docs/yarn.lock 19 | ts/docs/ 20 | cli/npm-package/anchor 21 | cli/npm-package/*.tgz 22 | docker-target 23 | .rollup.cache/ 24 | test-keypair.json 25 | tsconfig.tsbuildinfo 26 | .vscode -------------------------------------------------------------------------------- /ssm/solana-stake-market/.solitarc.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const programDir = path.join(__dirname, '.', 'programs/solana-stake-market'); 3 | const idlDir = path.join(__dirname, 'idl'); 4 | const sdkDir = path.join(__dirname, 'sdk'); 5 | const binaryInstallDir = path.join(__dirname, '.crates'); 6 | 7 | module.exports = { 8 | idlGenerator: 'anchor', 9 | programName: 'solana_stake_market', 10 | programId: 'sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37', 11 | idlDir, 12 | sdkDir, 13 | binaryInstallDir, 14 | programDir, 15 | }; -------------------------------------------------------------------------------- /ssm/solana-stake-market/Anchor.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | anchor_version = "0.29.0" # `anchor-cli` version to use(requires `avm`) 3 | solana_version = "1.18.12" 4 | 5 | [features] 6 | seeds = false 7 | skip-lint = false 8 | 9 | [programs.localnet] 10 | solana_stake_market = "sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37" 11 | 12 | [registry] 13 | url = "https://api.apr.dev" 14 | 15 | [provider] 16 | cluster = "Localnet" 17 | #wallet = "/Users/nico/Downloads/wallet-keypair.json" 18 | wallet = "/Users/kubaplata/.config/solana/id.json" 19 | 20 | [scripts] 21 | test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 22 | 23 | [test.validator] 24 | slots_per_epoch = "32" 25 | 26 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "programs/*" 4 | ] 5 | 6 | [profile.release] 7 | overflow-checks = true 8 | lto = "fat" 9 | codegen-units = 1 10 | [profile.release.build-override] 11 | opt-level = 3 12 | incremental = false 13 | codegen-units = 1 14 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/README.md: -------------------------------------------------------------------------------- 1 | ### Solana-Stake-Markets (SSM) 2 | SSM is a simple and intuitive way to allow for order book style bids on natively staked solana. Specifically by specifying the premium rate you are willing to pay and funding this bid with X amount of liquid SOL you create an environment whereby stake account holders can instantly sell active stake. 3 | 4 | ⚠️ SSM is in active-development and is non-audited onchain software. It operates under a public source license available for public education, viewing and inspiration but not to be used for commercial purposes in any format. 5 | 6 | ### Potential bottlenecks 7 | SSM orderbook is designed to be crankless and requires users to 'manually' find matching bids. Since multiple parties can simultaneously try to utilize the same bids (to get the best possible price), during high demand 8 | there is a high risk of possible bottleneck - due to accounts write locks and frontrunning. Future versions of SSM should optimize for minimizing these bottlenecks by introducing more sophisticated 9 | orderbook design. 10 | 11 | ### Development pipeline 12 | 13 | - [x] implement the order_book statistics PDA for use in bid derivation. 14 | - [x] create a bid at X rate with Y amount of SOL funding. 15 | - [x] close a bid providing it does not own stake_accounts and receive remaining lamports. 16 | - [x] validate minimum rates and other bid safety assumptions. 17 | - [x] implement the ability to sell stake_account into a bid. 18 | - [x] allow client to supply remaining accounts (bids) in the event that stake_accounts need to be split to fulfill sell order. 19 | - [x] validate the transfer of stake authorisation - new auth owner, and the increase in SOL to seller. 20 | - [x] validate that arbitrary sale amounts can be sold into multiple bids via the split stake implementation. 21 | - [ ] check if selling stake will empty a bid and close the bid account for bidder. 22 | - [x] validate changes to the order_book statistics PDA on sale of stake_account. 23 | - [x] implement more extensive checks around the stake_account handling. 24 | - [x] finalise end-to-end testing file which runs through all-scenarios start to finish. 25 | - [ ] submit for audit. -------------------------------------------------------------------------------- /ssm/solana-stake-market/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/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 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/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.29.0", 8 | "@metaplex-foundation/solita": "^0.20.1", 9 | "@solana/web3.js": "^1.91.8" 10 | }, 11 | "devDependencies": { 12 | "@types/bn.js": "^5.1.0", 13 | "@types/chai": "^4.3.0", 14 | "@types/mocha": "^10.0.6", 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 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solana-stake-market" 3 | version = "0.1.0" 4 | description = "Created with Anchor" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "lib"] 9 | name = "solana_stake_market" 10 | 11 | [features] 12 | no-entrypoint = [] 13 | no-idl = [] 14 | no-log-ix-name = [] 15 | cpi = ["no-entrypoint"] 16 | default = [] 17 | 18 | [dependencies] 19 | anchor-lang = "0.29.0" 20 | anchor-spl = { version = "0.29.0", features = ["stake"] } 21 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/Xargo.toml: -------------------------------------------------------------------------------- 1 | [target.bpfel-unknown-unknown.dependencies.std] 2 | features = [] 3 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/program_key/sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37.json: -------------------------------------------------------------------------------- 1 | [40,166,149,146,226,250,20,73,181,85,209,68,244,163,247,121,106,117,210,78,142,133,215,202,187,8,23,3,54,61,30,77,12,236,45,42,162,123,165,40,212,12,36,105,68,63,126,236,30,221,143,242,34,73,203,212,243,147,128,33,102,3,10,150] -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/constants/mod.rs: -------------------------------------------------------------------------------- 1 | pub const VAULT_SEED: &str = "vault"; 2 | pub const BID_SEED: &str = "bid"; 3 | pub const ORDERBOOK_SEED: &str = "order_book"; -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/errors.rs: -------------------------------------------------------------------------------- 1 | //src/errors.rs 2 | use anchor_lang::prelude::*; 3 | 4 | #[error_code] 5 | pub enum SsmError { 6 | #[msg("Could not transfer liquidity to the bid.")] 7 | TransferFailed, 8 | #[msg("The deposit amount is insufficient to cover the rate.")] 9 | UnfundedBid, 10 | #[msg("Rate defined is below the orderbook secure minimum of 0.6:1")] 11 | BelowMinimumRate, 12 | #[msg("Signer is not authorised to modify this account.")] 13 | Unauthorized, 14 | #[msg("Bid account has stake_accounts, claim the stake accounts - or withdraw the staked sol to close bid.")] 15 | Uncloseable, 16 | #[msg("not enough bids to cover the sale of stake accounts.")] 17 | InsufficientBids, 18 | #[msg("Failed to create a public key with the provided seed.")] 19 | PublicKeyCreationFailed, 20 | #[msg("Cannot find Stake Account's lockup.")] 21 | StakeAccountLockupNotFound, 22 | #[msg("Cannot find Stake Account's authorization settings.")] 23 | StakeAccountAuthorizationNotFound, 24 | #[msg("Cannot find Stake Account's delegation.")] 25 | StakeAccountDelegationNotFound, 26 | #[msg("Stake is not yet activated.")] 27 | StakeNotActivated, 28 | #[msg("Provided schema of RemainingAccounts is invalid.")] 29 | InvalidRemainingAccountsSchema 30 | } 31 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/instructions/close_bid.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::system_program::{transfer, Transfer}; 2 | use anchor_lang::prelude::*; 3 | use crate::constants::{BID_SEED, VAULT_SEED, ORDERBOOK_SEED}; 4 | use crate::errors::SsmError; 5 | use crate::states::{Bid, OrderBook}; 6 | 7 | pub fn close_bid( 8 | ctx: Context, 9 | bid_index: u64 10 | ) -> Result<()> { 11 | let order_book = &mut ctx.accounts.order_book; 12 | let user = &mut ctx.accounts.user; 13 | let bid = &mut ctx.accounts.bid; 14 | let bid_vault = &mut ctx.accounts.bid_vault; 15 | let system_program = &mut ctx.accounts.system_program; 16 | let program_id = ctx.program_id; 17 | 18 | msg!( 19 | "Closing bid with remaining balance of {} SOL. Orderbook TVL before: {} SOL", 20 | (bid.amount as f64) / 10_f64.powf(9_f64), 21 | (order_book.tvl as f64) / 10_f64.powf(9_f64) 22 | ); 23 | 24 | order_book.close_bid(bid.amount); 25 | 26 | msg!( 27 | "Orderbook TVL after: {} SOL", 28 | (order_book.tvl as f64) / 10_f64.powf(9_f64) 29 | ); 30 | 31 | msg!("Transferring remaining balance from bid to bidder."); 32 | 33 | let seeds = &[ 34 | VAULT_SEED.as_bytes(), 35 | &bid.key().to_bytes(), 36 | ]; 37 | 38 | let (_, bump) = Pubkey::find_program_address( 39 | seeds, 40 | program_id 41 | ); 42 | 43 | let signer_seeds = &[ 44 | VAULT_SEED.as_bytes(), 45 | &bid.key().to_bytes(), 46 | &[bump] 47 | ]; 48 | 49 | transfer( 50 | CpiContext::new_with_signer( 51 | system_program.to_account_info(), 52 | Transfer { 53 | from: bid_vault.to_account_info(), 54 | to: user.to_account_info() 55 | }, 56 | &[signer_seeds] 57 | ), 58 | bid_vault.lamports() 59 | )?; 60 | 61 | Ok(()) 62 | } 63 | 64 | #[derive(Accounts)] 65 | #[instruction( 66 | bid_index: u64 67 | )] 68 | pub struct CloseBid<'info> { 69 | #[account( 70 | mut 71 | )] 72 | pub user: Signer<'info>, 73 | 74 | #[account( 75 | mut, 76 | seeds = [ 77 | BID_SEED.as_bytes(), 78 | &bid_index.to_le_bytes() 79 | ], 80 | bump, 81 | constraint = bid.bidder == user.key() @ SsmError::Unauthorized, 82 | close = user 83 | )] 84 | pub bid: Account<'info, Bid>, 85 | 86 | #[account( 87 | mut, 88 | seeds = [ 89 | VAULT_SEED.as_bytes(), 90 | &bid.key().to_bytes(), 91 | ], 92 | bump 93 | )] 94 | pub bid_vault: SystemAccount<'info>, 95 | 96 | #[account( 97 | mut, 98 | seeds = [ 99 | ORDERBOOK_SEED.as_bytes() 100 | ], 101 | bump 102 | )] 103 | pub order_book: Account<'info, OrderBook>, 104 | 105 | pub system_program: Program<'info, System>, 106 | } -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/instructions/initialize_order_book.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | use crate::{constants::ORDERBOOK_SEED, states::OrderBook}; 3 | 4 | #[derive(Accounts)] 5 | pub struct InitializeOrderBook<'info> { 6 | #[account( 7 | mut 8 | )] 9 | pub user: Signer<'info>, 10 | 11 | #[account( 12 | init, 13 | payer = user, 14 | space = 8 + 3 * 8, 15 | seeds = [ 16 | ORDERBOOK_SEED.as_bytes() 17 | ], 18 | bump 19 | )] 20 | pub order_book: Account<'info, OrderBook>, 21 | 22 | pub system_program: Program<'info, System>, 23 | } 24 | 25 | pub fn initialize_order_book(ctx: Context) -> Result<()> { 26 | let order_book = &mut ctx.accounts.order_book; 27 | 28 | order_book.tvl = 0; // Initialize with zero SOL tvl. 29 | order_book.bids = 0; // Initialize with no bids. 30 | order_book.global_nonce = 0; // initialize global_nonce with no bids. 31 | 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod place_bid; 2 | pub mod close_bid; 3 | pub mod sell_stake; 4 | pub mod initialize_order_book; 5 | 6 | pub use sell_stake::*; 7 | pub use place_bid::*; 8 | pub use close_bid::*; 9 | pub use initialize_order_book::*; 10 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/instructions/place_bid.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::system_program::{transfer, Transfer}; 2 | use anchor_lang::prelude::*; 3 | use crate::errors::SsmError; 4 | use crate::constants::{ 5 | VAULT_SEED, 6 | BID_SEED, 7 | ORDERBOOK_SEED 8 | }; 9 | use crate::states::{Bid, OrderBook}; 10 | 11 | pub fn place_bid( 12 | ctx: Context, 13 | rate: u64, 14 | amount: u64 15 | ) -> Result<()> { 16 | let order_book = &mut ctx.accounts.order_book; 17 | let bid = &mut ctx.accounts.bid; 18 | let bid_vault = &mut ctx.accounts.bid_vault; 19 | let system_program = &mut ctx.accounts.system_program; 20 | let user = &mut ctx.accounts.user; 21 | 22 | require!( 23 | rate >= 600_000_000, 24 | SsmError::BelowMinimumRate 25 | ); 26 | 27 | msg!( 28 | "Placing bid for {} staked SOL at rate of {} liquid SOL per 1 staked SOL.", 29 | (amount as f64) / 10_f64.powf(9_f64), 30 | (rate as f64) / 10_f64.powf(9_f64) 31 | ); 32 | 33 | // Amount / LAMPORTS_PER_SOL, otherwise double decimals. 34 | let deposit = ((amount as f64) / 10_f64.powf(9_f64) * (rate as f64)) as u64; 35 | 36 | // Deposit into bid vault. 37 | transfer( 38 | CpiContext::new( 39 | system_program.to_account_info(), 40 | Transfer { 41 | from: user.to_account_info(), 42 | to: bid_vault.to_account_info() 43 | } 44 | ), 45 | deposit 46 | )?; 47 | 48 | bid.index = order_book.global_nonce; 49 | bid.amount = amount; 50 | bid.rate = rate; 51 | bid.bidder = user.key(); 52 | bid.fulfilled = false; 53 | 54 | order_book.add_bid(amount); 55 | 56 | msg!("Bid created. New TVL: {}", ctx.accounts.order_book.tvl); 57 | 58 | Ok(()) 59 | } 60 | 61 | #[derive(Accounts)] 62 | pub struct PlaceBid<'info> { 63 | #[account( 64 | mut 65 | )] 66 | pub user: Signer<'info>, 67 | 68 | #[account( 69 | init, 70 | payer = user, 71 | space = 8 + 8 * 3 + 32 + 1, 72 | seeds = [ 73 | BID_SEED.as_bytes(), 74 | &order_book.global_nonce.to_le_bytes() 75 | ], 76 | bump, 77 | )] 78 | pub bid: Account<'info, Bid>, 79 | 80 | #[account( 81 | mut, 82 | seeds = [ 83 | VAULT_SEED.as_bytes(), 84 | &bid.key().to_bytes(), 85 | ], 86 | bump 87 | )] 88 | pub bid_vault: SystemAccount<'info>, 89 | 90 | #[account( 91 | mut, 92 | seeds = [ 93 | ORDERBOOK_SEED.as_bytes() 94 | ], 95 | bump 96 | )] 97 | pub order_book: Account<'info, OrderBook>, 98 | 99 | pub system_program: Program<'info, System>, 100 | } -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/lib.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | pub mod instructions; 3 | pub mod states; 4 | pub mod errors; 5 | pub mod utils; 6 | pub mod constants; 7 | pub use instructions::*; 8 | 9 | declare_id!("sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37"); 10 | 11 | #[program] 12 | pub mod solana_stake_market { 13 | use super::*; 14 | 15 | pub fn place_bid( 16 | ctx: Context, 17 | rate: u64, 18 | amount: u64 19 | ) -> Result<()> { 20 | instructions::place_bid(ctx, rate, amount) 21 | } 22 | 23 | pub fn close_bid( 24 | ctx: Context, 25 | bid_index: u64, 26 | ) -> Result<()> { 27 | instructions::close_bid(ctx, bid_index) 28 | } 29 | 30 | pub fn initialize_order_book_wrapper( 31 | ctx: Context 32 | ) -> Result<()> { 33 | instructions::initialize_order_book(ctx) 34 | } 35 | 36 | pub fn sell_stake<'a, 'b, 'c: 'info, 'info>( 37 | ctx: Context<'a, 'b, 'c, 'info, SellStake<'info>>, 38 | total_stake_amount: u64 39 | ) -> Result<()> { 40 | instructions::sell_stake(ctx, total_stake_amount) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/states/bid.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[account] 4 | pub struct Bid { 5 | pub index: u64, // 8 6 | pub amount: u64, // Amount of SOL offered in lamports, 8 7 | pub rate: u64, // Rate in lamports, 8 8 | pub bidder: Pubkey, // Public key of the bidder, 32 9 | pub fulfilled: bool, // Indicates if the bid is fulfilled, 1 10 | } 11 | 12 | impl Bid { 13 | // Maybe unsafe? Should panic if amount > self.amount. 14 | pub fn partial_fill( 15 | &mut self, 16 | amount: u64 17 | ) -> () { 18 | self.amount -= amount; 19 | 20 | if self.amount == 0 { 21 | self.fulfilled = true; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/states/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bid; 2 | pub mod order_book; 3 | 4 | pub use bid::*; 5 | pub use order_book::*; 6 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/states/order_book.rs: -------------------------------------------------------------------------------- 1 | use anchor_lang::prelude::*; 2 | 3 | #[account] 4 | pub struct OrderBook { 5 | pub tvl: u64, // total amount of actively deposited solana in bids. 6 | pub bids: u64, // amount of active bids in the program. 7 | pub global_nonce: u64, // historical bid counter used for bid pda seed generation. 8 | } 9 | 10 | impl OrderBook { 11 | pub fn add_bid( 12 | &mut self, 13 | amount: u64 14 | ) -> () { 15 | self.tvl += amount; 16 | self.global_nonce += 1; 17 | self.bids += 1; 18 | } 19 | 20 | pub fn subtract_ask( 21 | &mut self, 22 | amount: u64 23 | ) -> () { 24 | self.tvl -= amount; 25 | } 26 | 27 | pub fn close_bid( 28 | &mut self, 29 | remaining_funds: u64 30 | ) -> () { 31 | self.bids -= 1; 32 | self.subtract_ask(remaining_funds); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/programs/solana-stake-market/src/utils.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/palindrome-eng/reflect-program-library/5f4f49df98017fb85ec8a75b3626b7aaabdf203f/ssm/solana-stake-market/programs/solana-stake-market/src/utils.rs -------------------------------------------------------------------------------- /ssm/solana-stake-market/sdk/accounts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Bid' 2 | export * from './OrderBook' 3 | 4 | import { Bid } from './Bid' 5 | import { OrderBook } from './OrderBook' 6 | 7 | export const accountProviders = { Bid, OrderBook } 8 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/sdk/index.ts: -------------------------------------------------------------------------------- 1 | import { PublicKey } from '@solana/web3.js' 2 | export * from './accounts' 3 | export * from './errors' 4 | export * from './instructions' 5 | 6 | /** 7 | * Program address 8 | * 9 | * @category constants 10 | * @category generated 11 | */ 12 | export const PROGRAM_ADDRESS = 'sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37' 13 | 14 | /** 15 | * Program public key 16 | * 17 | * @category constants 18 | * @category generated 19 | */ 20 | export const PROGRAM_ID = new PublicKey(PROGRAM_ADDRESS) 21 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/sdk/instructions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './closeBid' 2 | export * from './initializeOrderBookWrapper' 3 | export * from './placeBid' 4 | export * from './sellStake' 5 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/sdk/instructions/initializeOrderBookWrapper.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was GENERATED using the solita package. 3 | * Please DO NOT EDIT THIS FILE, instead rerun solita to update it or write a wrapper to add functionality. 4 | * 5 | * See: https://github.com/metaplex-foundation/solita 6 | */ 7 | 8 | import * as beet from '@metaplex-foundation/beet' 9 | import * as web3 from '@solana/web3.js' 10 | 11 | /** 12 | * @category Instructions 13 | * @category InitializeOrderBookWrapper 14 | * @category generated 15 | */ 16 | export const initializeOrderBookWrapperStruct = new beet.BeetArgsStruct<{ 17 | instructionDiscriminator: number[] /* size: 8 */ 18 | }>( 19 | [['instructionDiscriminator', beet.uniformFixedSizeArray(beet.u8, 8)]], 20 | 'InitializeOrderBookWrapperInstructionArgs' 21 | ) 22 | /** 23 | * Accounts required by the _initializeOrderBookWrapper_ instruction 24 | * 25 | * @property [_writable_, **signer**] user 26 | * @property [_writable_] orderBook 27 | * @category Instructions 28 | * @category InitializeOrderBookWrapper 29 | * @category generated 30 | */ 31 | export type InitializeOrderBookWrapperInstructionAccounts = { 32 | user: web3.PublicKey 33 | orderBook: web3.PublicKey 34 | systemProgram?: web3.PublicKey 35 | anchorRemainingAccounts?: web3.AccountMeta[] 36 | } 37 | 38 | export const initializeOrderBookWrapperInstructionDiscriminator = [ 39 | 115, 77, 3, 192, 219, 103, 173, 226, 40 | ] 41 | 42 | /** 43 | * Creates a _InitializeOrderBookWrapper_ instruction. 44 | * 45 | * @param accounts that will be accessed while the instruction is processed 46 | * @category Instructions 47 | * @category InitializeOrderBookWrapper 48 | * @category generated 49 | */ 50 | export function createInitializeOrderBookWrapperInstruction( 51 | accounts: InitializeOrderBookWrapperInstructionAccounts, 52 | programId = new web3.PublicKey('sSmYaKe6tj5VKjPzHhpakpamw1PYoJFLQNyMJD3PU37') 53 | ) { 54 | const [data] = initializeOrderBookWrapperStruct.serialize({ 55 | instructionDiscriminator: 56 | initializeOrderBookWrapperInstructionDiscriminator, 57 | }) 58 | const keys: web3.AccountMeta[] = [ 59 | { 60 | pubkey: accounts.user, 61 | isWritable: true, 62 | isSigner: true, 63 | }, 64 | { 65 | pubkey: accounts.orderBook, 66 | isWritable: true, 67 | isSigner: false, 68 | }, 69 | { 70 | pubkey: accounts.systemProgram ?? web3.SystemProgram.programId, 71 | isWritable: false, 72 | isSigner: false, 73 | }, 74 | ] 75 | 76 | if (accounts.anchorRemainingAccounts != null) { 77 | for (const acc of accounts.anchorRemainingAccounts) { 78 | keys.push(acc) 79 | } 80 | } 81 | 82 | const ix = new web3.TransactionInstruction({ 83 | programId, 84 | keys, 85 | data, 86 | }) 87 | return ix 88 | } 89 | -------------------------------------------------------------------------------- /ssm/solana-stake-market/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 | --------------------------------------------------------------------------------