diff --git a/src/apps/spool-v2/assets/logo.png b/src/apps/spool-v2/assets/logo.png new file mode 100644 index 000000000..154bed7a3 Binary files /dev/null and b/src/apps/spool-v2/assets/logo.png differ diff --git a/src/apps/spool-v2/contracts/abis/spool-staking.json b/src/apps/spool-v2/contracts/abis/spool-staking.json new file mode 100644 index 000000000..cec171051 --- /dev/null +++ b/src/apps/spool-v2/contracts/abis/spool-staking.json @@ -0,0 +1,810 @@ +[ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_stakingToken", + "type": "address" + }, + { + "internalType": "contract IVoSPOOL", + "name": "_voSpool", + "type": "address" + }, + { + "internalType": "contract IVoSpoolRewards", + "name": "_voSpoolRewards", + "type": "address" + }, + { + "internalType": "contract IRewardDistributor", + "name": "_rewardDistributor", + "type": "address" + }, + { + "internalType": "contract ISpoolOwner", + "name": "_spoolOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "canStakeFor", + "type": "bool" + } + ], + "name": "CanStakeForSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "periodFinish", + "type": "uint32" + } + ], + "name": "PeriodFinishUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "RewardAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardCompounded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "RewardPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "RewardRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "leftover", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "periodFinish", + "type": "uint32" + } + ], + "name": "RewardUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Staked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "stakedFor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "stakedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakedFor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Unstaked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "VoRewardCompounded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "VoSpoolRewardPaid", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint32", + "name": "rewardsDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "addToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "allowFor", + "type": "address" + } + ], + "name": "allowUnstakeFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canStakeFor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "doCompoundVoSpoolRewards", + "type": "bool" + } + ], + "name": "compound", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "earned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "doClaimVoSpoolRewards", + "type": "bool" + } + ], + "name": "getActiveRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "doClaimVoSpoolRewards", + "type": "bool" + } + ], + "name": "getRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getUpdatedVoSpoolRewardAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "rewards", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "lastTimeRewardApplicable", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_rewardsDuration", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "reward", + "type": "uint256" + } + ], + "name": "notifyRewardAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recoverTo", + "type": "address" + } + ], + "name": "recoverERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "removeReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "name": "rewardConfiguration", + "outputs": [ + { + "internalType": "uint32", + "name": "rewardsDuration", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "periodFinish", + "type": "uint32" + }, + { + "internalType": "uint192", + "name": "rewardRate", + "type": "uint192" + }, + { + "internalType": "uint32", + "name": "lastUpdateTime", + "type": "uint32" + }, + { + "internalType": "uint224", + "name": "rewardPerTokenStored", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardDistributor", + "outputs": [ + { + "internalType": "contract IRewardDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + } + ], + "name": "rewardPerToken", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "rewardTokens", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardTokensCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "_canStakeFor", + "type": "bool" + } + ], + "name": "setCanStakeFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "stakeFor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "stakedBy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakingToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "name": "tokenBlacklist", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStaked", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "name": "updatePeriodFinish", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "voSpool", + "outputs": [ + { + "internalType": "contract IVoSPOOL", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "voSpoolRewards", + "outputs": [ + { + "internalType": "contract IVoSpoolRewards", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/apps/spool-v2/contracts/abis/spool-vault.json b/src/apps/spool-v2/contracts/abis/spool-vault.json new file mode 100644 index 000000000..5ac084cfe --- /dev/null +++ b/src/apps/spool-v2/contracts/abis/spool-vault.json @@ -0,0 +1,815 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "baseUri", + "type": "string" + } + ], + "name": "BaseURIChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "assetGroupId", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOfFractional", + "outputs": [ + { + "internalType": "uint256", + "name": "fractionalBalance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfFractionalBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "fractionalBalances", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "nftAmounts", + "type": "uint256[]" + } + ], + "name": "burnNFTs", + "outputs": [ + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vaultShares", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "strategies", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "shares", + "type": "uint256[]" + } + ], + "name": "burnVaultShares", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "claimer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claimShares", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "nftIds", + "type": "uint256[]" + } + ], + "name": "getMetadata", + "outputs": [ + { + "internalType": "bytes[]", + "name": "metadata", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256[]", + "name": "assets", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "initiated", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "flushIndex", + "type": "uint256" + } + ], + "internalType": "struct DepositMetadata", + "name": "metadata", + "type": "tuple" + } + ], + "name": "mintDepositNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "vaultShares", + "type": "uint256" + } + ], + "name": "mintVaultShares", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "vaultShares", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "flushIndex", + "type": "uint256" + } + ], + "internalType": "struct WithdrawalMetadata", + "name": "metadata", + "type": "tuple" + } + ], + "name": "mintWithdrawalNFT", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "uri_", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFromSpender", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultName", + "outputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/apps/spool-v2/contracts/abis/spool-vospool.json b/src/apps/spool-v2/contracts/abis/spool-vospool.json new file mode 100644 index 000000000..d8014ca64 --- /dev/null +++ b/src/apps/spool-v2/contracts/abis/spool-vospool.json @@ -0,0 +1,1173 @@ +[ + { + "inputs": [ + { + "internalType": "contract ISpoolOwner", + "name": "_spoolOwner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_firstTrancheEndTime", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint16", + "name": "lastUpdatedTrancheIndex", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "totalMaturedVotingPower", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "totalMaturingAmount", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint56", + "name": "totalRawUnmaturedVotingPower", + "type": "uint56" + } + ], + "name": "GlobalGradualUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "burnAll", + "type": "bool" + } + ], + "name": "GradualBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "GradualMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "set", + "type": "bool" + } + ], + "name": "GradualMinterSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "set", + "type": "bool" + } + ], + "name": "MinterSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint16", + "name": "lastUpdatedTrancheIndex", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "maturedVotingPower", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint48", + "name": "maturingAmount", + "type": "uint48" + }, + { + "indexed": false, + "internalType": "uint56", + "name": "rawUnmaturedVotingPower", + "type": "uint56" + } + ], + "name": "UserGradualUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "FULL_POWER_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FULL_POWER_TRANCHES_COUNT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANCHE_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "burnAll", + "type": "bool" + } + ], + "name": "burnGradual", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "firstTrancheStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentTrancheIndex", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGlobalGradual", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "totalMaturedVotingPower", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "totalMaturingAmount", + "type": "uint48" + }, + { + "internalType": "uint56", + "name": "totalRawUnmaturedVotingPower", + "type": "uint56" + }, + { + "internalType": "uint16", + "name": "lastUpdatedTrancheIndex", + "type": "uint16" + } + ], + "internalType": "struct GlobalGradual", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastFinishedTrancheIndex", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextTrancheEndTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNotUpdatedGlobalGradual", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "totalMaturedVotingPower", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "totalMaturingAmount", + "type": "uint48" + }, + { + "internalType": "uint56", + "name": "totalRawUnmaturedVotingPower", + "type": "uint56" + }, + { + "internalType": "uint16", + "name": "lastUpdatedTrancheIndex", + "type": "uint16" + } + ], + "internalType": "struct GlobalGradual", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getNotUpdatedUserGradual", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "maturedVotingPower", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "maturingAmount", + "type": "uint48" + }, + { + "internalType": "uint56", + "name": "rawUnmaturedVotingPower", + "type": "uint56" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "arrayIndex", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "position", + "type": "uint8" + } + ], + "internalType": "struct UserTranchePosition", + "name": "oldestTranchePosition", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "arrayIndex", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "position", + "type": "uint8" + } + ], + "internalType": "struct UserTranchePosition", + "name": "latestTranchePosition", + "type": "tuple" + }, + { + "internalType": "uint16", + "name": "lastUpdatedTrancheIndex", + "type": "uint16" + } + ], + "internalType": "struct UserGradual", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalGradualVotingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "trancheIndex", + "type": "uint256" + } + ], + "name": "getTrancheEndTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "getTrancheIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserGradual", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "maturedVotingPower", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "maturingAmount", + "type": "uint48" + }, + { + "internalType": "uint56", + "name": "rawUnmaturedVotingPower", + "type": "uint56" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "arrayIndex", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "position", + "type": "uint8" + } + ], + "internalType": "struct UserTranchePosition", + "name": "oldestTranchePosition", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "arrayIndex", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "position", + "type": "uint8" + } + ], + "internalType": "struct UserTranchePosition", + "name": "latestTranchePosition", + "type": "tuple" + }, + { + "internalType": "uint16", + "name": "lastUpdatedTrancheIndex", + "type": "uint16" + } + ], + "internalType": "struct UserGradual", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getUserGradualVotingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "gradualMinters", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "indexedGlobalTranches", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + } + ], + "internalType": "struct Tranche", + "name": "zero", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + } + ], + "internalType": "struct Tranche", + "name": "one", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + } + ], + "internalType": "struct Tranche", + "name": "two", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + } + ], + "internalType": "struct Tranche", + "name": "three", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + } + ], + "internalType": "struct Tranche", + "name": "four", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mintGradual", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "minters", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gradualMinter", + "type": "address" + }, + { + "internalType": "bool", + "name": "_set", + "type": "bool" + } + ], + "name": "setGradualMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_minter", + "type": "address" + }, + { + "internalType": "bool", + "name": "_set", + "type": "bool" + } + ], + "name": "setMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalInstantPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "updateUserVotingPower", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateVotingPower", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userInstantPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "userTranches", + "outputs": [ + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + }, + { + "internalType": "uint16", + "name": "index", + "type": "uint16" + } + ], + "internalType": "struct UserTranche", + "name": "zero", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + }, + { + "internalType": "uint16", + "name": "index", + "type": "uint16" + } + ], + "internalType": "struct UserTranche", + "name": "one", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + }, + { + "internalType": "uint16", + "name": "index", + "type": "uint16" + } + ], + "internalType": "struct UserTranche", + "name": "two", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint48", + "name": "amount", + "type": "uint48" + }, + { + "internalType": "uint16", + "name": "index", + "type": "uint16" + } + ], + "internalType": "struct UserTranche", + "name": "three", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/apps/spool-v2/contracts/index.ts b/src/apps/spool-v2/contracts/index.ts new file mode 100644 index 000000000..5dcfebdf6 --- /dev/null +++ b/src/apps/spool-v2/contracts/index.ts @@ -0,0 +1,4 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export * from './viem.contract-factory'; diff --git a/src/apps/spool-v2/contracts/viem.contract-factory.ts b/src/apps/spool-v2/contracts/viem.contract-factory.ts new file mode 100644 index 000000000..e3dce6ab9 --- /dev/null +++ b/src/apps/spool-v2/contracts/viem.contract-factory.ts @@ -0,0 +1,23 @@ +import { Injectable, Inject } from '@nestjs/common'; + +import { IAppToolkit, APP_TOOLKIT } from '../../../../../studio/src/app-toolkit/app-toolkit.interface'; +import { Network } from '../../../../../studio/src/types/network.interface'; + +import { SpoolStaking__factory, SpoolVault__factory, SpoolVospool__factory } from './viem'; + +type ContractOpts = { address: string; network: Network }; + +@Injectable() +export class SpoolV2ViemContractFactory { + constructor(@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit) {} + + spoolStaking({ address, network }: ContractOpts) { + return SpoolStaking__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); + } + spoolVault({ address, network }: ContractOpts) { + return SpoolVault__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); + } + spoolVospool({ address, network }: ContractOpts) { + return SpoolVospool__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); + } +} diff --git a/src/apps/spool-v2/contracts/viem/SpoolStaking.ts b/src/apps/spool-v2/contracts/viem/SpoolStaking.ts new file mode 100644 index 000000000..28c85b863 --- /dev/null +++ b/src/apps/spool-v2/contracts/viem/SpoolStaking.ts @@ -0,0 +1,824 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { getContract, GetContractReturnType, PublicClient } from 'viem'; + +export const spoolStakingAbi = [ + { + inputs: [ + { + internalType: 'contract IERC20', + name: '_stakingToken', + type: 'address', + }, + { + internalType: 'contract IVoSPOOL', + name: '_voSpool', + type: 'address', + }, + { + internalType: 'contract IVoSpoolRewards', + name: '_voSpoolRewards', + type: 'address', + }, + { + internalType: 'contract IRewardDistributor', + name: '_rewardDistributor', + type: 'address', + }, + { + internalType: 'contract ISpoolOwner', + name: '_spoolOwner', + type: 'address', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'canStakeFor', + type: 'bool', + }, + ], + name: 'CanStakeForSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + indexed: false, + internalType: 'uint32', + name: 'periodFinish', + type: 'uint32', + }, + ], + name: 'PeriodFinishUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'duration', + type: 'uint256', + }, + ], + name: 'RewardAdded', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'reward', + type: 'uint256', + }, + ], + name: 'RewardCompounded', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'reward', + type: 'uint256', + }, + ], + name: 'RewardPaid', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + ], + name: 'RewardRemoved', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'leftover', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'duration', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint32', + name: 'periodFinish', + type: 'uint32', + }, + ], + name: 'RewardUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Staked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'stakedFor', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'stakedBy', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'StakedFor', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Unstaked', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'reward', + type: 'uint256', + }, + ], + name: 'VoRewardCompounded', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'reward', + type: 'uint256', + }, + ], + name: 'VoSpoolRewardPaid', + type: 'event', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + internalType: 'uint32', + name: 'rewardsDuration', + type: 'uint32', + }, + { + internalType: 'uint256', + name: 'reward', + type: 'uint256', + }, + ], + name: 'addToken', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'allowFor', + type: 'address', + }, + ], + name: 'allowUnstakeFor', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'balances', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'canStakeFor', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bool', + name: 'doCompoundVoSpoolRewards', + type: 'bool', + }, + ], + name: 'compound', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'earned', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bool', + name: 'doClaimVoSpoolRewards', + type: 'bool', + }, + ], + name: 'getActiveRewards', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20[]', + name: 'tokens', + type: 'address[]', + }, + { + internalType: 'bool', + name: 'doClaimVoSpoolRewards', + type: 'bool', + }, + ], + name: 'getRewards', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'getUpdatedVoSpoolRewardAmount', + outputs: [ + { + internalType: 'uint256', + name: 'rewards', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + ], + name: 'lastTimeRewardApplicable', + outputs: [ + { + internalType: 'uint32', + name: '', + type: 'uint32', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + internalType: 'uint32', + name: '_rewardsDuration', + type: 'uint32', + }, + { + internalType: 'uint256', + name: 'reward', + type: 'uint256', + }, + ], + name: 'notifyRewardAmount', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'tokenAddress', + type: 'address', + }, + { + internalType: 'uint256', + name: 'tokenAmount', + type: 'uint256', + }, + { + internalType: 'address', + name: 'recoverTo', + type: 'address', + }, + ], + name: 'recoverERC20', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + ], + name: 'removeReward', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: '', + type: 'address', + }, + ], + name: 'rewardConfiguration', + outputs: [ + { + internalType: 'uint32', + name: 'rewardsDuration', + type: 'uint32', + }, + { + internalType: 'uint32', + name: 'periodFinish', + type: 'uint32', + }, + { + internalType: 'uint192', + name: 'rewardRate', + type: 'uint192', + }, + { + internalType: 'uint32', + name: 'lastUpdateTime', + type: 'uint32', + }, + { + internalType: 'uint224', + name: 'rewardPerTokenStored', + type: 'uint224', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rewardDistributor', + outputs: [ + { + internalType: 'contract IRewardDistributor', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + ], + name: 'rewardPerToken', + outputs: [ + { + internalType: 'uint224', + name: '', + type: 'uint224', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'rewardTokens', + outputs: [ + { + internalType: 'contract IERC20', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rewardTokensCount', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + { + internalType: 'bool', + name: '_canStakeFor', + type: 'bool', + }, + ], + name: 'setCanStakeFor', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'stake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'stakeFor', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'stakedBy', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'stakingToken', + outputs: [ + { + internalType: 'contract IERC20', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: '', + type: 'address', + }, + ], + name: 'tokenBlacklist', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalStaked', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'unstake', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'contract IERC20', + name: 'token', + type: 'address', + }, + { + internalType: 'uint32', + name: 'timestamp', + type: 'uint32', + }, + ], + name: 'updatePeriodFinish', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'voSpool', + outputs: [ + { + internalType: 'contract IVoSPOOL', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'voSpoolRewards', + outputs: [ + { + internalType: 'contract IVoSpoolRewards', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const; + +export type SpoolStaking = typeof spoolStakingAbi; +export type SpoolStakingContract = GetContractReturnType; + +export class SpoolStaking__factory { + static connect(address: string, client: PublicClient) { + return getContract({ address, abi: spoolStakingAbi, publicClient: client }); + } +} diff --git a/src/apps/spool-v2/contracts/viem/SpoolVault.ts b/src/apps/spool-v2/contracts/viem/SpoolVault.ts new file mode 100644 index 000000000..7c8fce631 --- /dev/null +++ b/src/apps/spool-v2/contracts/viem/SpoolVault.ts @@ -0,0 +1,829 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { getContract, GetContractReturnType, PublicClient } from 'viem'; + +export const spoolVaultAbi = [ + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'approved', + type: 'bool', + }, + ], + name: 'ApprovalForAll', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'baseUri', + type: 'string', + }, + ], + name: 'BaseURIChanged', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + indexed: false, + internalType: 'uint256[]', + name: 'values', + type: 'uint256[]', + }, + ], + name: 'TransferBatch', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'TransferSingle', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'string', + name: 'value', + type: 'string', + }, + { + indexed: true, + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'URI', + type: 'event', + }, + { + inputs: [ + { + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + ], + name: 'allowance', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'approve', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'assetGroupId', + outputs: [ + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'balanceOf', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'balanceOf', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address[]', + name: 'accounts', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + ], + name: 'balanceOfBatch', + outputs: [ + { + internalType: 'uint256[]', + name: '', + type: 'uint256[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'balanceOfFractional', + outputs: [ + { + internalType: 'uint256', + name: 'fractionalBalance', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + ], + name: 'balanceOfFractionalBatch', + outputs: [ + { + internalType: 'uint256[]', + name: 'fractionalBalances', + type: 'uint256[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + internalType: 'uint256[]', + name: 'nftIds', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'nftAmounts', + type: 'uint256[]', + }, + ], + name: 'burnNFTs', + outputs: [ + { + internalType: 'bytes[]', + name: 'metadata', + type: 'bytes[]', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + internalType: 'uint256', + name: 'vaultShares', + type: 'uint256', + }, + { + internalType: 'address[]', + name: 'strategies', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: 'shares', + type: 'uint256[]', + }, + ], + name: 'burnVaultShares', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'claimer', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'claimShares', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256[]', + name: 'nftIds', + type: 'uint256[]', + }, + ], + name: 'getMetadata', + outputs: [ + { + internalType: 'bytes[]', + name: 'metadata', + type: 'bytes[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + { + internalType: 'address', + name: 'operator', + type: 'address', + }, + ], + name: 'isApprovedForAll', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'receiver', + type: 'address', + }, + { + components: [ + { + internalType: 'uint256[]', + name: 'assets', + type: 'uint256[]', + }, + { + internalType: 'uint256', + name: 'initiated', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'flushIndex', + type: 'uint256', + }, + ], + internalType: 'struct DepositMetadata', + name: 'metadata', + type: 'tuple', + }, + ], + name: 'mintDepositNFT', + outputs: [ + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'receiver', + type: 'address', + }, + { + internalType: 'uint256', + name: 'vaultShares', + type: 'uint256', + }, + ], + name: 'mintVaultShares', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'receiver', + type: 'address', + }, + { + components: [ + { + internalType: 'uint256', + name: 'vaultShares', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'flushIndex', + type: 'uint256', + }, + ], + internalType: 'struct WithdrawalMetadata', + name: 'metadata', + type: 'tuple', + }, + ], + name: 'mintWithdrawalNFT', + outputs: [ + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256[]', + name: 'ids', + type: 'uint256[]', + }, + { + internalType: 'uint256[]', + name: 'amounts', + type: 'uint256[]', + }, + { + internalType: 'bytes', + name: 'data', + type: 'bytes', + }, + ], + name: 'safeBatchTransferFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'data', + type: 'bytes', + }, + ], + name: 'safeTransferFrom', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'operator', + type: 'address', + }, + { + internalType: 'bool', + name: 'approved', + type: 'bool', + }, + ], + name: 'setApprovalForAll', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'string', + name: 'uri_', + type: 'string', + }, + ], + name: 'setBaseURI', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'bytes4', + name: 'interfaceId', + type: 'bytes4', + }, + ], + name: 'supportsInterface', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'transferFrom', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'transferFromSpender', + outputs: [ + { + internalType: 'bool', + name: 'success', + type: 'bool', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'id', + type: 'uint256', + }, + ], + name: 'uri', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'vaultName', + outputs: [ + { + internalType: 'string', + name: 'name', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const; + +export type SpoolVault = typeof spoolVaultAbi; +export type SpoolVaultContract = GetContractReturnType; + +export class SpoolVault__factory { + static connect(address: string, client: PublicClient) { + return getContract({ address, abi: spoolVaultAbi, publicClient: client }); + } +} diff --git a/src/apps/spool-v2/contracts/viem/SpoolVospool.ts b/src/apps/spool-v2/contracts/viem/SpoolVospool.ts new file mode 100644 index 000000000..2f07b5b1c --- /dev/null +++ b/src/apps/spool-v2/contracts/viem/SpoolVospool.ts @@ -0,0 +1,1187 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { getContract, GetContractReturnType, PublicClient } from 'viem'; + +export const spoolVospoolAbi = [ + { + inputs: [ + { + internalType: 'contract ISpoolOwner', + name: '_spoolOwner', + type: 'address', + }, + { + internalType: 'uint256', + name: '_firstTrancheEndTime', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'constructor', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'owner', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'spender', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Approval', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'source', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Burned', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint16', + name: 'lastUpdatedTrancheIndex', + type: 'uint16', + }, + { + indexed: false, + internalType: 'uint48', + name: 'totalMaturedVotingPower', + type: 'uint48', + }, + { + indexed: false, + internalType: 'uint48', + name: 'totalMaturingAmount', + type: 'uint48', + }, + { + indexed: false, + internalType: 'uint56', + name: 'totalRawUnmaturedVotingPower', + type: 'uint56', + }, + ], + name: 'GlobalGradualUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'source', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'bool', + name: 'burnAll', + type: 'bool', + }, + ], + name: 'GradualBurned', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'recipient', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'GradualMinted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'minter', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'set', + type: 'bool', + }, + ], + name: 'GradualMinterSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'recipient', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'Minted', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'minter', + type: 'address', + }, + { + indexed: false, + internalType: 'bool', + name: 'set', + type: 'bool', + }, + ], + name: 'MinterSet', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'from', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'to', + type: 'address', + }, + { + indexed: false, + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + name: 'Transfer', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: 'user', + type: 'address', + }, + { + indexed: true, + internalType: 'uint16', + name: 'lastUpdatedTrancheIndex', + type: 'uint16', + }, + { + indexed: false, + internalType: 'uint48', + name: 'maturedVotingPower', + type: 'uint48', + }, + { + indexed: false, + internalType: 'uint48', + name: 'maturingAmount', + type: 'uint48', + }, + { + indexed: false, + internalType: 'uint56', + name: 'rawUnmaturedVotingPower', + type: 'uint56', + }, + ], + name: 'UserGradualUpdated', + type: 'event', + }, + { + inputs: [], + name: 'FULL_POWER_TIME', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'FULL_POWER_TRANCHES_COUNT', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'TRANCHE_TIME', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'allowance', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'approve', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'balanceOf', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'burn', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'from', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + { + internalType: 'bool', + name: 'burnAll', + type: 'bool', + }, + ], + name: 'burnGradual', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'decimals', + outputs: [ + { + internalType: 'uint8', + name: '', + type: 'uint8', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'firstTrancheStartTime', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getCurrentTrancheIndex', + outputs: [ + { + internalType: 'uint16', + name: '', + type: 'uint16', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getGlobalGradual', + outputs: [ + { + components: [ + { + internalType: 'uint48', + name: 'totalMaturedVotingPower', + type: 'uint48', + }, + { + internalType: 'uint48', + name: 'totalMaturingAmount', + type: 'uint48', + }, + { + internalType: 'uint56', + name: 'totalRawUnmaturedVotingPower', + type: 'uint56', + }, + { + internalType: 'uint16', + name: 'lastUpdatedTrancheIndex', + type: 'uint16', + }, + ], + internalType: 'struct GlobalGradual', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getLastFinishedTrancheIndex', + outputs: [ + { + internalType: 'uint16', + name: '', + type: 'uint16', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getNextTrancheEndTime', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getNotUpdatedGlobalGradual', + outputs: [ + { + components: [ + { + internalType: 'uint48', + name: 'totalMaturedVotingPower', + type: 'uint48', + }, + { + internalType: 'uint48', + name: 'totalMaturingAmount', + type: 'uint48', + }, + { + internalType: 'uint56', + name: 'totalRawUnmaturedVotingPower', + type: 'uint56', + }, + { + internalType: 'uint16', + name: 'lastUpdatedTrancheIndex', + type: 'uint16', + }, + ], + internalType: 'struct GlobalGradual', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'user', + type: 'address', + }, + ], + name: 'getNotUpdatedUserGradual', + outputs: [ + { + components: [ + { + internalType: 'uint48', + name: 'maturedVotingPower', + type: 'uint48', + }, + { + internalType: 'uint48', + name: 'maturingAmount', + type: 'uint48', + }, + { + internalType: 'uint56', + name: 'rawUnmaturedVotingPower', + type: 'uint56', + }, + { + components: [ + { + internalType: 'uint16', + name: 'arrayIndex', + type: 'uint16', + }, + { + internalType: 'uint8', + name: 'position', + type: 'uint8', + }, + ], + internalType: 'struct UserTranchePosition', + name: 'oldestTranchePosition', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint16', + name: 'arrayIndex', + type: 'uint16', + }, + { + internalType: 'uint8', + name: 'position', + type: 'uint8', + }, + ], + internalType: 'struct UserTranchePosition', + name: 'latestTranchePosition', + type: 'tuple', + }, + { + internalType: 'uint16', + name: 'lastUpdatedTrancheIndex', + type: 'uint16', + }, + ], + internalType: 'struct UserGradual', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getTotalGradualVotingPower', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'trancheIndex', + type: 'uint256', + }, + ], + name: 'getTrancheEndTime', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'time', + type: 'uint256', + }, + ], + name: 'getTrancheIndex', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'user', + type: 'address', + }, + ], + name: 'getUserGradual', + outputs: [ + { + components: [ + { + internalType: 'uint48', + name: 'maturedVotingPower', + type: 'uint48', + }, + { + internalType: 'uint48', + name: 'maturingAmount', + type: 'uint48', + }, + { + internalType: 'uint56', + name: 'rawUnmaturedVotingPower', + type: 'uint56', + }, + { + components: [ + { + internalType: 'uint16', + name: 'arrayIndex', + type: 'uint16', + }, + { + internalType: 'uint8', + name: 'position', + type: 'uint8', + }, + ], + internalType: 'struct UserTranchePosition', + name: 'oldestTranchePosition', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint16', + name: 'arrayIndex', + type: 'uint16', + }, + { + internalType: 'uint8', + name: 'position', + type: 'uint8', + }, + ], + internalType: 'struct UserTranchePosition', + name: 'latestTranchePosition', + type: 'tuple', + }, + { + internalType: 'uint16', + name: 'lastUpdatedTrancheIndex', + type: 'uint16', + }, + ], + internalType: 'struct UserGradual', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'user', + type: 'address', + }, + ], + name: 'getUserGradualVotingPower', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'gradualMinters', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'indexedGlobalTranches', + outputs: [ + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + ], + internalType: 'struct Tranche', + name: 'zero', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + ], + internalType: 'struct Tranche', + name: 'one', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + ], + internalType: 'struct Tranche', + name: 'two', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + ], + internalType: 'struct Tranche', + name: 'three', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + ], + internalType: 'struct Tranche', + name: 'four', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'mint', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'to', + type: 'address', + }, + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + name: 'mintGradual', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'minters', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'name', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_gradualMinter', + type: 'address', + }, + { + internalType: 'bool', + name: '_set', + type: 'bool', + }, + ], + name: 'setGradualMinter', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_minter', + type: 'address', + }, + { + internalType: 'bool', + name: '_set', + type: 'bool', + }, + ], + name: 'setMinter', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'symbol', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalInstantPower', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalSupply', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'transfer', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'transferFrom', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'user', + type: 'address', + }, + ], + name: 'updateUserVotingPower', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'updateVotingPower', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'userInstantPower', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + name: 'userTranches', + outputs: [ + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + { + internalType: 'uint16', + name: 'index', + type: 'uint16', + }, + ], + internalType: 'struct UserTranche', + name: 'zero', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + { + internalType: 'uint16', + name: 'index', + type: 'uint16', + }, + ], + internalType: 'struct UserTranche', + name: 'one', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + { + internalType: 'uint16', + name: 'index', + type: 'uint16', + }, + ], + internalType: 'struct UserTranche', + name: 'two', + type: 'tuple', + }, + { + components: [ + { + internalType: 'uint48', + name: 'amount', + type: 'uint48', + }, + { + internalType: 'uint16', + name: 'index', + type: 'uint16', + }, + ], + internalType: 'struct UserTranche', + name: 'three', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, +] as const; + +export type SpoolVospool = typeof spoolVospoolAbi; +export type SpoolVospoolContract = GetContractReturnType; + +export class SpoolVospool__factory { + static connect(address: string, client: PublicClient) { + return getContract({ address, abi: spoolVospoolAbi, publicClient: client }); + } +} diff --git a/src/apps/spool-v2/contracts/viem/index.ts b/src/apps/spool-v2/contracts/viem/index.ts new file mode 100644 index 000000000..e0379243c --- /dev/null +++ b/src/apps/spool-v2/contracts/viem/index.ts @@ -0,0 +1,11 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +export type { SpoolStaking } from './SpoolStaking'; +export type { SpoolVault } from './SpoolVault'; +export type { SpoolVospool } from './SpoolVospool'; + +export { SpoolStaking__factory } from './SpoolStaking'; +export { SpoolVault__factory } from './SpoolVault'; +export { SpoolVospool__factory } from './SpoolVospool'; diff --git a/src/apps/spool-v2/ethereum/spool-v2.constants.ts b/src/apps/spool-v2/ethereum/spool-v2.constants.ts new file mode 100644 index 000000000..9a2f6e572 --- /dev/null +++ b/src/apps/spool-v2/ethereum/spool-v2.constants.ts @@ -0,0 +1,109 @@ +import { gql } from 'graphql-request'; + +export const SPOOL_ADDRESS = '0x40803cea2b2a32bda1be61d3604af6a814e70976'; +export const VOSPOOL_ADDRESS = '0xaf56d16a7fe479f2fcd48ff567ff589cb2d2a0e9'; +export const STAKING_ADDRESS = '0xc3160c5cc63b6116dd182faa8393d3ad9313e213'; +export const SUBGRAPH_API_BASE_URL = 'https://api.studio.thegraph.com/query/41372/spool-v2_mainnet/version/latest'; +export const SUBGRAPH_V1_API_BASE_URL = "https://api.thegraph.com/subgraphs/name/spoolfi/spool?source=zapper" +export const ANALYTICS_API_BASE_URL = 'https://subgraph-api.58sa2u0osmd2c.eu-west-1.cs.amazonlightsail.com/mainnet'; +export const SPOOL_STAKED_QUERY = gql` + query getStaking($address: String!) { + userSpoolStaking(id: $address) { + id + spoolStaked + } + } +`; + +export const REWARDS_QUERY = gql` + query { + smartVaultRewardTokens { + id + token { + id + name + symbol + decimals + } + isRemoved + endTime + startTime + } + } +`; + + +export const FEES_QUERY = gql` + query { + globals { + treasuryFee + ecosystemFee + } + } +`; + +export const VAULTS_ANALYTICS_QUERY = gql` + query { + smartVaults { + id + tvr + baseApy + rewardsApy + adjustedApy + } + } +`; +export const VAULTS_QUERY = gql` + query { + smartVaults { + id + assetGroup { + assetGroupTokens { + token { + id + } + } + } + id + name + riskTolerance + riskProvider { + id + } + smartVaultFees { + id + depositFeePercentage + managementFeePercentage + performanceFeePercentage + } + smartVaultStrategies { + id + isRemoved + allocation + strategy { + id + riskScores { + riskScore + riskProvider { + id + } + } + } + } + smartVaultRewardTokens { + id + token { + id + name + symbol + decimals + } + rewardRate + startTime + endTime + totalAmount + isRemoved + } + } + } +`; diff --git a/src/apps/spool-v2/ethereum/spool-v2.staking.contract-position-fetcher.ts b/src/apps/spool-v2/ethereum/spool-v2.staking.contract-position-fetcher.ts new file mode 100644 index 000000000..0a06b92fa --- /dev/null +++ b/src/apps/spool-v2/ethereum/spool-v2.staking.contract-position-fetcher.ts @@ -0,0 +1,155 @@ +import { Inject } from '@nestjs/common'; +import { BigNumber } from 'ethers'; +import { parseEther } from 'ethers/lib/utils'; +import _ from 'lodash'; + +import { APP_TOOLKIT, IAppToolkit } from '../../../../../studio/src/app-toolkit/app-toolkit.interface'; +import { PositionTemplate } from '../../../../../studio/src/app-toolkit/decorators/position-template.decorator'; +import { + buildDollarDisplayItem, + buildNumberDisplayItem, +} from '../../../../../studio/src/app-toolkit/helpers/presentation/display-item.present'; +import { getLabelFromToken } from '../../../../../studio/src/app-toolkit/helpers/presentation/image.present'; +import { gqlFetch } from '../../../../../studio/src/app-toolkit/helpers/the-graph.helper'; +import { MetaType } from '../../../../../studio/src/position/position.interface'; +import { isClaimable, isSupplied } from '../../../../../studio/src/position/position.utils'; +import { ContractPositionTemplatePositionFetcher } from '../../../../../studio/src/position/template/contract-position.template.position-fetcher'; +import { + GetDataPropsParams, + GetDisplayPropsParams, + GetTokenBalancesParams, +} from '../../../../../studio/src/position/template/contract-position.template.types'; +import { SpoolV2ViemContractFactory } from '../contracts'; +import { SpoolStaking } from '../contracts/viem'; + +import { + REWARDS_QUERY, + SPOOL_ADDRESS, + SPOOL_STAKED_QUERY, + STAKING_ADDRESS, + SUBGRAPH_API_BASE_URL, + VOSPOOL_ADDRESS, +} from './spool-v2.constants'; +import { StakingReward, UserSpoolStaking } from './spool-v2.types'; + +type SpoolStakingDataProps = { + tvl: number; + spoolStaked: number; + totalAccVoSpool: number; +}; + +@PositionTemplate() +export class EthereumSpoolV2StakingContractPositionFetcher extends ContractPositionTemplatePositionFetcher< + SpoolStaking, + SpoolStakingDataProps +> { + groupLabel = 'Staking'; + + constructor( + @Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit, + @Inject(SpoolV2ViemContractFactory) protected readonly contractFactory: SpoolV2ViemContractFactory, + ) { + super(appToolkit); + } + + getContract(address: string) { + return this.contractFactory.spoolStaking({ address, network: this.network }); + } + + async getDefinitions() { + return [{ address: STAKING_ADDRESS }]; + } + + async getTokenDefinitions() { + const now = parseInt(String(new Date().getTime() / 1000)); + const stakingRewards = await gqlFetch({ + endpoint: SUBGRAPH_API_BASE_URL, + query: REWARDS_QUERY, + }); + + let rewardAddresses: string[] = []; + // SpoolStaking can emit arbitrary tokens; VoSpoolRewards always emits SPOOL + if (stakingRewards.stakingRewardTokens) { + rewardAddresses = _.uniq( + stakingRewards.stakingRewardTokens + .filter(reward => !reward.isRemoved && parseInt(reward.startTime) >= now && parseInt(reward.endTime) <= now) + .map(reward => reward.token.id) + .concat([SPOOL_ADDRESS]) + ); + } + + return [ + { metaType: MetaType.SUPPLIED, address: SPOOL_ADDRESS, network: this.network }, + { metaType: MetaType.VESTING, address: VOSPOOL_ADDRESS, network: this.network }, + ...rewardAddresses.map(address => ({ metaType: MetaType.CLAIMABLE, address, network: this.network })), + ]; + } + + async getDataProps({ multicall, contractPosition }: GetDataPropsParams) { + const [spoolToken, voSpoolToken] = contractPosition.tokens; + const spoolContract = this.appToolkit.globalViemContracts.erc20(spoolToken); + const voSpoolContract = this.contractFactory.spoolVospool(voSpoolToken); + + const totalStakedRaw = await multicall.wrap(spoolContract).read.balanceOf([STAKING_ADDRESS]); + const votingPowerRaw = await multicall.wrap(voSpoolContract).read.getTotalGradualVotingPower(); + + const totalAccVoSpool = Number(votingPowerRaw) / 10 ** voSpoolToken.decimals; + const spoolStaked = Number(totalStakedRaw) / 10 ** spoolToken.decimals; + const tvl = spoolStaked * spoolToken.price; + + return { tvl, spoolStaked, totalAccVoSpool }; + } + + async getLabel({ contractPosition }: GetDisplayPropsParams) { + return `${getLabelFromToken(contractPosition.tokens[0])} Staking`; + } + + async getStatsItems({ contractPosition }: GetDisplayPropsParams) { + return [ + { label: 'TVL', value: buildDollarDisplayItem(contractPosition.dataProps.tvl) }, + { label: 'SPOOL Staked', value: buildNumberDisplayItem(contractPosition.dataProps.spoolStaked) }, + { label: 'voSPOOL Accumulated', value: buildNumberDisplayItem(contractPosition.dataProps.totalAccVoSpool) }, + ]; + } + + async getTokenBalancesPerPosition({ + address, + contractPosition, + multicall, + }: GetTokenBalancesParams) { + const suppliedToken = contractPosition.tokens.find(isSupplied)!; + const rewardTokens = contractPosition.tokens.filter(isClaimable); + + const staking = this.contractFactory.spoolStaking({ address: STAKING_ADDRESS, network: this.network }); + const voSpool = this.contractFactory.spoolVospool({ address: VOSPOOL_ADDRESS, network: this.network }); + + const [votingPowerRaw, voSpoolRewards, ...tokenRewards] = await Promise.all([ + multicall.wrap(voSpool).read.getUserGradualVotingPower([address]), + multicall + .wrap(staking) + .simulate.getUpdatedVoSpoolRewardAmount({ account: address }) + .then(v => v.result), + ...rewardTokens.map(reward => multicall.wrap(staking).read.earned([reward.address, address])), + ]); + + const stakedSpool = await gqlFetch({ + endpoint: SUBGRAPH_API_BASE_URL, + query: SPOOL_STAKED_QUERY, + variables: { address }, + }); + + const stakedAmount = parseEther(stakedSpool?.userSpoolStaking?.spoolStaked || '0').toString(); + + const rewardBalances = rewardTokens.map((token, idx) => { + // Add voSPOOL rewards (always in SPOOL) + const rewards = + token.address.toLowerCase() == suppliedToken.address.toLowerCase() + ? BigNumber.from(tokenRewards[idx]).add(voSpoolRewards) + : BigNumber.from(tokenRewards[idx]); + + return rewards.toString(); + }); + + return [stakedAmount, votingPowerRaw.toString(), ...rewardBalances]; + } +} diff --git a/src/apps/spool-v2/ethereum/spool-v2.types.ts b/src/apps/spool-v2/ethereum/spool-v2.types.ts new file mode 100644 index 000000000..e95aab917 --- /dev/null +++ b/src/apps/spool-v2/ethereum/spool-v2.types.ts @@ -0,0 +1,137 @@ +import { IMulticallWrapper } from '../../../../../studio/src/multicall'; +import { ContractPosition } from '../../../../../studio/src/position/position.interface'; + +export type SpoolVaults = { + smartVaults: VaultDetails[]; +}; + +export type VaultDetails = { + id: string; + name: string; + riskTolerance: string; + riskProvider: { + id: string; + }; + assetGroup: { + assetGroupTokens: { + token: { + id: string; + }; + }[]; + }; + smartVaultFees: { + depositFeePercentage: string; + managementFeePercentage: string; + performanceFeePercentage: string; + }; + smartVaultStrategies: { + id: string; + allocation: string; + isRemoved: boolean; + strategy: { + id: string; + riskScores: { + riskScore: string; + riskProvider: { + id: string; + }; + }[]; + }; + }[]; + smartVaultRewardTokens: { + id: string; + token: { + id: string; + name: string; + symbol: string; + decimals: number; + }; + rewardRate: number; + totalAmount: string; + isRemoved: number; + }[]; +}; + +export type Globals = { + globals: { + treasuryFee: string; + ecosystemFee: string; + }; +}; + +export type VaultsAnalytics = { + smartVaults: { + id: string; + tvr: string; + baseApy: string; + rewardsApy: string[]; + adjustedApy: string; + incentivizedApy: string; + }[]; +}; + +export type Platform = { + platform: { + id: string; + treasuryFeeSize: string; + ecosystemFeeSize: string; + }; +}; + +export type StakingReward = { + stakingRewardTokens: { + id: string; + token: { + id: string; + name: string; + symbol: string; + decimals: number; + }; + isRemoved: boolean; + endTime: string; + startTime: string; + }[]; +}; + +export type UserSpoolStaking = { + userSpoolStaking: { + id: string; + spoolStaked: string; + }; +}; + +export type VaultDataProps = { + strategies: string[]; +}; + +export type VaultPosition = ContractPosition; + +export type SpoolVaultDefinition = { + address: string; + name: string; + riskModel: string; + suppliedTokenAddresses: string[]; + rewardTokenAddresses: string[] | null; + strategyAddresses: string[]; + stats: { + riskTolerance: number; + tvr: string; + fees: number; + adjustedApy: number; + incentivizedApy: number; + baseApy: number; + }; +}; + +export type SpoolVaultDataProps = { + totalValueRouted: number; + apy: number; + adjustedApy: number; + incentivizedApy: number; + fees: number; + strategies: string[]; + riskScore: string; + riskTolerance: number; +}; + +export type ResolveBalancesProps = { address: string; contractPosition: VaultPosition; multicall: IMulticallWrapper }; diff --git a/src/apps/spool-v2/ethereum/spool-v2.vault.contract-position-fetcher.ts b/src/apps/spool-v2/ethereum/spool-v2.vault.contract-position-fetcher.ts new file mode 100644 index 000000000..11089b10d --- /dev/null +++ b/src/apps/spool-v2/ethereum/spool-v2.vault.contract-position-fetcher.ts @@ -0,0 +1,209 @@ +import { Inject } from '@nestjs/common'; +import { BigNumberish, ethers } from 'ethers'; + +import { APP_TOOLKIT, IAppToolkit } from '../../../../../studio/src/app-toolkit/app-toolkit.interface'; +import { PositionTemplate } from '../../../../../studio/src/app-toolkit/decorators/position-template.decorator'; +import { + buildDollarDisplayItem, + buildPercentageDisplayItem, + buildStringDisplayItem, +} from '../../../../../studio/src/app-toolkit/helpers/presentation/display-item.present'; +import { getLabelFromToken } from '../../../../../studio/src/app-toolkit/helpers/presentation/image.present'; +import { gqlFetch } from '../../../../../studio/src/app-toolkit/helpers/the-graph.helper'; +import { SpoolV2ViemContractFactory } from '../contracts'; +import { SpoolVault } from '../contracts/viem'; +import { + ANALYTICS_API_BASE_URL, + FEES_QUERY, + SUBGRAPH_API_BASE_URL, + VAULTS_ANALYTICS_QUERY, + VAULTS_QUERY, +} from './spool-v2.constants'; +import { + Globals, + SpoolVaultDataProps, + SpoolVaultDefinition, + SpoolVaults, + VaultDetails, + VaultsAnalytics, +} from './spool-v2.types'; +import { MetaType } from '../../../../../studio/src/position/position.interface'; +import { ContractPositionTemplatePositionFetcher } from '../../../../../studio/src/position/template/contract-position.template.position-fetcher'; +import { + GetDisplayPropsParams, + GetTokenDefinitionsParams +} from "../../../../../studio/src/position/template/contract-position.template.types"; + +const riskModels = { '0xc216ad6280f4fa92a5159ef383a1206d432481c8': 'Spool Labs' }; + +@PositionTemplate() +export class EthereumSpoolV2VaultContractPositionFetcher extends ContractPositionTemplatePositionFetcher< + SpoolVault, + SpoolVaultDataProps, + SpoolVaultDefinition +> { + groupLabel = 'Vaults'; + + constructor( + @Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit, + @Inject(SpoolV2ViemContractFactory) protected readonly spoolV2ContractFactory: SpoolV2ViemContractFactory, + ) { + super(appToolkit); + } + + getContract(_address: string) { + return this.spoolV2ContractFactory.spoolVault({ address: _address, network: this.network }); + } + + async getDefinitions() { + // Request all vaults + const vaultsData = await gqlFetch({ + endpoint: SUBGRAPH_API_BASE_URL, + query: VAULTS_QUERY, + }); + + // Request platform fees + const fees = await gqlFetch({ + endpoint: SUBGRAPH_API_BASE_URL, + query: FEES_QUERY, + }); + + // Request strategy, vault, and reward analytics + const vaultAnalytics = await this.getVaultsAnalytics(); + + + return vaultsData.smartVaults.map(vault => ({ + address: vault.id.toLowerCase(), + name: vault.name, + riskModel: vault.riskProvider? vault.riskProvider.id : '', + suppliedTokenAddresses: vault.assetGroup.assetGroupTokens.map(agt => agt.token.id.toLowerCase()), + rewardTokenAddresses: + vault.smartVaultRewardTokens.length > 0 + ? vault.smartVaultRewardTokens.map(rt => rt.token.id.toLowerCase()) + : null, + strategyAddresses: vault.smartVaultStrategies.map(s => s.strategy.id.toLowerCase()), + stats: this.getVaultStats( + vault, + vaultAnalytics.smartVaults.find(va => va.id == vault.id), + fees, + ), + })); + } + getTokenBalancesPerPosition(_params): Promise { + throw new Error('Method not implemented.'); + } + + async getTokenDefinitions({ definition }: GetTokenDefinitionsParams) { + return [ + ...definition.suppliedTokenAddresses.map(address => ({ + metaType: MetaType.SUPPLIED, + address, + network: this.network, + })), + ]; + } + + async getLabel({ definition }: GetDisplayPropsParams) { + return definition.name; + } + + async getSecondaryLabel({ + contractPosition, + }: GetDisplayPropsParams) { + return contractPosition.tokens.map(token => getLabelFromToken(token)).join(', '); + } + async getStatsItems({ definition }: GetDisplayPropsParams) { + return [ + { label: 'APY', value: buildPercentageDisplayItem(definition.stats.adjustedApy) }, + { label: 'TVR', value: buildDollarDisplayItem(Number(definition.stats.tvr)) }, + { label: 'Risk Model', value: buildStringDisplayItem(riskModels[definition.riskModel]) }, + { + label: 'Risk Appetite', + value: buildStringDisplayItem( + `${this.getRiskScoreString(definition.stats.riskTolerance)} (${this.mapRiskToRange( + definition.stats.riskTolerance, + )})`, + ), + }, + { + label: 'Reward Tokens', + value: buildStringDisplayItem(definition.rewardTokenAddresses?.map(address => address.toString()).join(', ')), + }, + ]; + } + /** + * Calculate APY, TVR (total value routed) and fees. + * @param vault + * @param vaultAnalytics + * @param platformFees + */ + getVaultStats( + vault: VaultDetails, + vaultAnalytics: + | { + id: string; + tvr: string; + baseApy: string; + rewardsApy: string[]; + adjustedApy: string; + incentivizedApy: string; + } + | undefined, + platformFees: Globals, + ) { + const fees = + parseFloat(platformFees.globals.ecosystemFee) + + parseFloat(platformFees.globals.treasuryFee) + + parseFloat(vault.smartVaultFees.performanceFeePercentage) + + parseFloat(vault.smartVaultFees.managementFeePercentage); + + let tvr = '0'; + let adjustedApy = 0.0; + let incentivizedApy = 0.0; + let baseApy = 0.0; + + if (vaultAnalytics) { + tvr = ethers.utils.formatEther(vaultAnalytics.tvr); + adjustedApy = parseFloat(vaultAnalytics.adjustedApy) * 100; + incentivizedApy = parseFloat(vaultAnalytics.incentivizedApy) * 100; + baseApy = parseFloat(vaultAnalytics.baseApy) * 100; + } + + const riskTolerance = Number(vault.riskTolerance); + + return { + riskTolerance: riskTolerance, + tvr: tvr, + fees: fees, + adjustedApy: adjustedApy, + incentivizedApy: incentivizedApy, + baseApy: baseApy, + }; + } + + /** + * Fetch vault analytics + */ + async getVaultsAnalytics(): Promise { + return await gqlFetch({ + endpoint: ANALYTICS_API_BASE_URL, + query: VAULTS_ANALYTICS_QUERY, + }); + } + getRiskScoreString(riskTolerance: number) { + const risk = this.mapRiskToRange(riskTolerance); + switch (true) { + case risk > 5: + return 'Risk Seeking'; + case risk === 5: + return 'Risk Neutral'; + default: + return 'Risk Averse'; + } + } + mapRiskToRange(risk: number) { + const [inMin, inMax] = [-10, 10]; + const [outMin, outMax] = [0, 10]; + return ((risk - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin; + } +} diff --git a/src/apps/spool-v2/ethereum/spool-v2.vo-spool.token-fetcher.ts b/src/apps/spool-v2/ethereum/spool-v2.vo-spool.token-fetcher.ts new file mode 100644 index 000000000..6623e0010 --- /dev/null +++ b/src/apps/spool-v2/ethereum/spool-v2.vo-spool.token-fetcher.ts @@ -0,0 +1,44 @@ +import { Inject } from '@nestjs/common'; + +import { APP_TOOLKIT, IAppToolkit } from '../../../../../studio/src/app-toolkit/app-toolkit.interface'; +import { PositionTemplate } from '../../../../../studio/src/app-toolkit/decorators/position-template.decorator'; +import { AppTokenTemplatePositionFetcher } from '../../../../../studio/src/position/template/app-token.template.position-fetcher'; + +import { SpoolV2ViemContractFactory } from "../contracts"; +import { SpoolVospool } from '../contracts/viem'; + +import { VOSPOOL_ADDRESS } from './spool-v2.constants'; +@PositionTemplate() +export class EthereumSpoolV2VoSpoolTokenFetcher extends AppTokenTemplatePositionFetcher { + groupLabel = 'voSPOOL'; + isExcludedFromBalances = true; + isExcludedFromExplore = true; + isExcludedFromTvl = true; + + constructor( + @Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit, + @Inject(SpoolV2ViemContractFactory) protected readonly contractFactory: SpoolV2ViemContractFactory, + ) { + super(appToolkit); + } + + getContract(address: string) { + return this.contractFactory.spoolVospool({ address, network: this.network }); + } + + async getAddresses(): Promise { + return [VOSPOOL_ADDRESS]; + } + + async getUnderlyingTokenDefinitions() { + return []; + } + + async getPricePerShare() { + return [1]; + } + + async getPrice() { + return 0; // Valueless token + } +} diff --git a/src/apps/spool-v2/spool-v2.module.ts b/src/apps/spool-v2/spool-v2.module.ts new file mode 100644 index 000000000..663b05a63 --- /dev/null +++ b/src/apps/spool-v2/spool-v2.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; + +import { AbstractApp } from '../../../../studio/src/app/app.dynamic-module'; + +import { SpoolV2ViemContractFactory } from './contracts'; +import { EthereumSpoolV2StakingContractPositionFetcher } from './ethereum/spool-v2.staking.contract-position-fetcher'; +import { EthereumSpoolV2VaultContractPositionFetcher } from './ethereum/spool-v2.vault.contract-position-fetcher'; +import { EthereumSpoolV2VoSpoolTokenFetcher } from './ethereum/spool-v2.vo-spool.token-fetcher'; + +@Module({ + providers: [ + EthereumSpoolV2StakingContractPositionFetcher, + EthereumSpoolV2VaultContractPositionFetcher, + EthereumSpoolV2VoSpoolTokenFetcher, + SpoolV2ViemContractFactory, + ], +}) +export class SpoolV2AppModule extends AbstractApp() {}