diff --git a/src/contracts/definitions/index.ts b/src/contracts/definitions/index.ts index c2f88d0..628d1c7 100644 --- a/src/contracts/definitions/index.ts +++ b/src/contracts/definitions/index.ts @@ -7,3 +7,4 @@ export * from './derivativeScrt'; export * from './shadeStaking'; export * from './lend'; export * from './silkBasket'; +export * from './moneyMarket'; diff --git a/src/contracts/definitions/moneyMarket.ts b/src/contracts/definitions/moneyMarket.ts new file mode 100644 index 0000000..002d841 --- /dev/null +++ b/src/contracts/definitions/moneyMarket.ts @@ -0,0 +1,191 @@ +import { AccountPermit } from '~/types/permit'; +import { Pagination } from '~/types/contracts/moneyMarket/model'; +import { generatePadding } from '~/index'; +import { snip20 } from './snip20'; + +/** + * Query the contract status info + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +const msgQueryMoneyMarketConfig = () => ({ config: {} }); + +/** + * Query the collateral state and config info + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +const msgQueryMoneyMarketCollaterals = ( + pagination?: Pagination, +) => ({ + get_collateral: { + pagination, + }, +}); + +/** + * Query the markets' state and config info + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +const msgQueryMoneyMarketMarkets = ( + pagination?: Pagination, +) => ({ + get_markets: { + pagination, + }, +}); + +/** + * Query a user's collateral and debt positions + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +const msgQueryMoneyMarketUserPosition = ( + address: string, + permit: AccountPermit, +) => ({ + user_position: { + address, + authentication: { + permit: { + query_permit: permit, + }, + }, + }, +}); + +/** + * message to borrow a debt token against deposited collateral + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +function msgMoneyMarketBorrow({ + borrowAmount, + debtTokenAddress, +}: { + borrowAmount: string, + debtTokenAddress: string, +}) { + return { + borrow: { + token: debtTokenAddress, + amount: borrowAmount, + }, + }; +} + +/** + * message to withdraw collateral against an existing user position + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +function msgMoneyMarketWithdrawCollateral({ + withdrawAmount, + collateralTokenAddress, +}: { + withdrawAmount: string, + collateralTokenAddress: string, +}) { + return { + deposit_collateral: { + token: collateralTokenAddress, + amount: withdrawAmount, + }, + }; +} + +/** + * message to deposit collateral to borrow against + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +function msgMoneyMarketDepositCollateral({ + moneyMarketContractAddress, + moneyMarketCodeHash, + depositAmount, +}: { + moneyMarketContractAddress: string, + moneyMarketCodeHash?: string, + depositAmount: string, +}) { + return snip20.messages.send({ + recipient: moneyMarketContractAddress, + recipientCodeHash: moneyMarketCodeHash, + amount: depositAmount, + handleMsg: { deposit_collateral: {} }, + padding: generatePadding(), + }).msg; +} + +/** + * message to supply tokens to be lent out + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +function msgMoneyMarketSupply({ + moneyMarketContractAddress, + moneyMarketCodeHash, + supplyAmount, +}: { + moneyMarketContractAddress: string, + moneyMarketCodeHash?: string, + supplyAmount: string, +}) { + return snip20.messages.send({ + recipient: moneyMarketContractAddress, + recipientCodeHash: moneyMarketCodeHash, + amount: supplyAmount, + handleMsg: { supply: {} }, + padding: generatePadding(), + }).msg; +} + +/** + * message to withdraw supply by sending an ltoken amount + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +function msgMoneyMarketWithdrawSupply({ + moneyMarketContractAddress, + moneyMarketCodeHash, + withdrawAmount, +}: { + moneyMarketContractAddress: string, + moneyMarketCodeHash?: string, + withdrawAmount: string, +}) { + return snip20.messages.send({ + recipient: moneyMarketContractAddress, + recipientCodeHash: moneyMarketCodeHash, + amount: withdrawAmount, + handleMsg: { withdraw_supply: {} }, + padding: generatePadding(), + }).msg; +} + +/** + * message to repay a loan that has been taken out + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +function msgMoneyMarketRepay({ + moneyMarketContractAddress, + moneyMarketCodeHash, + repayAmount, +}: { + moneyMarketContractAddress: string, + moneyMarketCodeHash?: string, + repayAmount: string, +}) { + return snip20.messages.send({ + recipient: moneyMarketContractAddress, + recipientCodeHash: moneyMarketCodeHash, + amount: repayAmount, + handleMsg: { repay: {} }, + padding: generatePadding(), + }).msg; +} + +export { + msgQueryMoneyMarketConfig, + msgQueryMoneyMarketCollaterals, + msgQueryMoneyMarketMarkets, + msgQueryMoneyMarketUserPosition, + msgMoneyMarketBorrow, + msgMoneyMarketWithdrawCollateral, + msgMoneyMarketDepositCollateral, + msgMoneyMarketSupply, + msgMoneyMarketWithdrawSupply, + msgMoneyMarketRepay, +}; diff --git a/src/contracts/services/moneyMarket.ts b/src/contracts/services/moneyMarket.ts new file mode 100644 index 0000000..a3f759a --- /dev/null +++ b/src/contracts/services/moneyMarket.ts @@ -0,0 +1,41 @@ +import { getActiveQueryClient$ } from '~/client'; +import { + switchMap, + first, + map, + lastValueFrom, +} from 'rxjs'; +import { sendSecretClientContractQuery$ } from '~/client/services/clientServices'; +import { msgQueryMoneyMarketConfig } from '../definitions/moneyMarket'; + +const parseMoneyMarketConfig = ( + response: ConfigResponse +):ParsedConfigResponse + +/** + * query the money market config + * NOT FOR PRODUCTION USE, CONTRACT IS IN DEVELOPMENT ON TESTNET ONLY + */ +const queryMoneyMarketConfig$ = ({ + contractAddress, + codeHash, + lcdEndpoint, + chainId, +}: { + contractAddress: string, + codeHash?: string, + lcdEndpoint?: string, + chainId?: string, +}) => getActiveQueryClient$(lcdEndpoint, chainId).pipe( + switchMap(({ client }) => sendSecretClientContractQuery$({ + queryMsg: msgQueryMoneyMarketConfig(), + client, + contractAddress, + codeHash, + })), + map((response) => parseDerivativeShdStakingInfo(response as StakingInfoResponse)), + first(), +); + +export { +}; diff --git a/src/types/contracts/index.ts b/src/types/contracts/index.ts index 96a963d..08bac19 100644 --- a/src/types/contracts/index.ts +++ b/src/types/contracts/index.ts @@ -8,3 +8,4 @@ export * from './derivativeShd'; export * from './shadeStaking'; export * from './lend'; export * from './silkBasket'; +export * from './moneyMarket'; diff --git a/src/types/contracts/moneyMarket/index.ts b/src/types/contracts/moneyMarket/index.ts new file mode 100644 index 0000000..9f8ccad --- /dev/null +++ b/src/types/contracts/moneyMarket/index.ts @@ -0,0 +1 @@ +export * from './model'; diff --git a/src/types/contracts/moneyMarket/model.ts b/src/types/contracts/moneyMarket/model.ts new file mode 100644 index 0000000..b57e720 --- /dev/null +++ b/src/types/contracts/moneyMarket/model.ts @@ -0,0 +1,71 @@ +type Pagination = { + page: number, + page_size: number, +} + +type ParsedConfigResponse = { + adminAuth: { + contractAddress: string + codeHash: string, + }, + queryAuth: { + contractAddress: string, + codeHash: string, + }, + oracle: { + contractAddress: string, + codeHash: string, + }, + feeCollector: string, + lTokenId: number, + lTokenCodeHash: string, + lTokenBlockchainAdmin: string, + supplyEnabled: boolean, + borrowEnabled: boolean, + repayEnabled: boolean, + liquidationEnabled: boolean, + interestAccrualEnabled: boolean, + collateralDepositEnabled: boolean, +} + +type ParsedMarketResponse = { + marketToken: { + contractAddress: string, + codeHash: string, + }, + lToken: { + contractAddress: string, + codeHash: string, + }, + decimals: number, + oracleKey: string, + interest: { + linear?: { + base: string, + slope: string, + }, + piecewise_linear?: { + base: string, + slope1: string, + slope2: string, + optimalUtilisation: string, + } + }, + loanableAmount: string, + lentAmount: string, + lifetimeInterestPaid: string, + lifetimeInterestOwed: string, + interestPerUtoken: string, + lastInterestAccrued: Date, + maxSupplyAmount: string, + flashLoanInterest: string, + supplyEnabled: boolean, + borrowEnabled: boolean, + repayEnabled: boolean, + liquidationEnabled: boolean, + interestAccrualEnabled: boolean, +} + +export type { + Pagination, +}; diff --git a/src/types/contracts/moneyMarket/response.ts b/src/types/contracts/moneyMarket/response.ts new file mode 100644 index 0000000..8eec99c --- /dev/null +++ b/src/types/contracts/moneyMarket/response.ts @@ -0,0 +1,153 @@ +type ConfigResponse = { + config: { + admin_auth: { + address: string, + code_hash: string, + } + query_auth: { + address: string, + code_hash: string, + } + oracle: { + address: string, + code_hash: string, + } + fee_collector: string, + l_token_id: number, + l_token_code_hash: string, + l_token_blockchain_admin: string, + status: { + global_status: { + supply_enabled: boolean, + borrow_enabled: boolean, + repay_enabled: boolean, + liquidation_enabled: boolean, + interest_accrual_enabled: boolean, + collateral_deposit_enabled: boolean, + } + } + } +} + +type PaginatedResponse = { + paginated_response: { + page: number, + page_size: number, + total_pages: number, + total_items: number, + data: T[] + } +} + +type MarketReponse = { + market: { + market_token: { + address: string, + code_hash: string, + }, + l_token: { + address: string, + code_hash: string, + }, + decimals: number, + oracle_key: string, + interest: { + inner: { + interest: { + linear?: { + base: string, + slope: string, + }, + piecewise_linear?: { + base: string, + slope1: string, + slope2: string, + optimal_utilisation: string, + } + } + } + } + loanable: string, + lent_amount: string, + lifetime_interest_paid: string, + lifetime_interest_owed: string, + interest_per_utoken: string, + last_interest_accrued: number, + max_supply: string, + flash_loan_interest: string, + status: { + market_status: { + supply_enabled: boolean, + borrow_enabled: boolean, + repay_enabled: boolean, + liquidation_enabled: boolean, + interest_accrual_enabled: boolean, + } + } + } +} + +type GetMarketsResponse = PaginatedResponse; + +type CollateralReponse = { + collateral_state: { + token: { + address: string, + code_hash: string, + }, + amount: string, + decimals: number, + max_initial_ltv: string, + liquidation_threshold: string, + liquidation_discount: string, + oracle_key: string, + status: { + collateral_status: { + deposit_enabled: boolean, + liquidation_enabled: boolean, + } + } + } +} + +type GetCollateralResponse = PaginatedResponse; + +type CalculatedUserCollateralReponse = { + calculated_user_collateral: { + token: string, + amount: string, + price: string, + value: string, + } +} + +type CalculatedUserDebtResponse = { + calculated_user_debt: { + token: string, + price: string, + principal: string, + principal_value: string, + interest_accrued: string, + interest_accrued_value: string, + } +} + +type UserPositionResponse = { + calcualted_user_position: { + id: string, + collateral: CalculatedUserCollateralReponse[], + debt: CalculatedUserDebtResponse[], + total_collateral_value: string, + total_principal_value: string, + total_interest_accrued_value: string, + loan_max_point: string, + loan_liquidation_point: string, + } +} + +export type { + ConfigResponse, + GetMarketsResponse, + GetCollateralResponse, + UserPositionResponse, +};