-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Automatic Redemption updates * Use pool authority instead of sentinel * Address comments * lint --------- Co-authored-by: shan-57blocks <[email protected]>
- Loading branch information
1 parent
109f130
commit d4756b7
Showing
16 changed files
with
547 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './hooks' | ||
export * from './solana' | ||
export * from './utils' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './hooks' | ||
export * from './types' | ||
export * from './utils' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './notEnabledAutoRedeem' |
14 changes: 14 additions & 0 deletions
14
packages/huma-web-shared/src/solana/utils/notEnabledAutoRedeem.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Account } from '@solana/spl-token' | ||
import { PublicKey } from '@solana/web3.js' | ||
|
||
export const notEnabledAutoRedeem = ( | ||
tokenAccount: Account | undefined, | ||
poolAuthorityPubkey: PublicKey, | ||
amount: bigint | undefined, | ||
): boolean => | ||
!!tokenAccount && | ||
!!amount && | ||
tokenAccount.amount > 0 && | ||
(tokenAccount.delegate == null || | ||
!poolAuthorityPubkey.equals(tokenAccount.delegate) || | ||
tokenAccount.delegatedAmount < amount) |
21 changes: 21 additions & 0 deletions
21
packages/huma-web-shared/src/utils/getLenderLockupDates.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export const getLenderLockupDates = ( | ||
withdrawalLockupPeriodDays: number, | ||
): { lockupEndTimeUnix: number; withdrawTimeUnix: number } => { | ||
const now = new Date() | ||
const lockupEndTime = new Date(now.getFullYear(), now.getMonth(), 1) | ||
lockupEndTime.setDate( | ||
lockupEndTime.getDate() + (withdrawalLockupPeriodDays ?? 0), | ||
) | ||
|
||
const withdrawTime = new Date( | ||
lockupEndTime.getFullYear(), | ||
lockupEndTime.getMonth() + 1, | ||
lockupEndTime.getDate(), | ||
) | ||
|
||
// Get Unix timestamps in seconds | ||
const lockupEndTimeUnix = Math.floor(lockupEndTime.getTime() / 1000) | ||
const withdrawTimeUnix = Math.floor(withdrawTime.getTime() / 1000) | ||
|
||
return { lockupEndTimeUnix, withdrawTimeUnix } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './getLenderLockupDates' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
packages/huma-widget/src/components/Lend/solanaEnableAutoRedemption/1-ApproveAllowance.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { timeUtil } from '@huma-finance/shared' | ||
import { SolanaPoolState } from '@huma-finance/web-shared' | ||
import dayjs from 'dayjs' | ||
import React, { useCallback } from 'react' | ||
import { Box, css, useTheme } from '@mui/material' | ||
import { useAppDispatch } from '../../../hooks/useRedux' | ||
import { WrapperModal } from '../../WrapperModal' | ||
import { WIDGET_STEP } from '../../../store/widgets.store' | ||
import { setStep } from '../../../store/widgets.reducers' | ||
import { BottomButton } from '../../BottomButton' | ||
import { AutoPaybackImg } from '../../images' | ||
|
||
type Props = { | ||
poolState: SolanaPoolState | ||
} | ||
|
||
export function ApproveAllowance({ poolState }: Props): React.ReactElement { | ||
const theme = useTheme() | ||
const dispatch = useAppDispatch() | ||
const handleNext = useCallback(() => { | ||
dispatch(setStep(WIDGET_STEP.Transfer)) | ||
}, [dispatch]) | ||
|
||
const styles = { | ||
iconWrapper: css` | ||
${theme.cssMixins.rowCentered}; | ||
margin-top: ${theme.spacing(6)}; | ||
& > img { | ||
width: 220px; | ||
} | ||
`, | ||
description: css` | ||
margin-top: ${theme.spacing(4)}; | ||
font-weight: 400; | ||
font-size: 16px; | ||
color: ${theme.palette.text.secondary}; | ||
padding: ${theme.spacing(0, 1)}; | ||
`, | ||
} | ||
|
||
const lockupEndTime = dayjs() | ||
.add(poolState.withdrawalLockupPeriodDays ?? 0, 'day') | ||
.date(1) | ||
const withdrawTime = lockupEndTime.add(1, 'month') | ||
|
||
return ( | ||
<WrapperModal title='Auto-Redemption'> | ||
<Box css={styles.iconWrapper}> | ||
<img src={AutoPaybackImg} alt='auto-payback' /> | ||
</Box> | ||
<Box css={styles.description}> | ||
This allowance transaction will enable auto-redemption for your existing | ||
tranche shares. Redemption requests will be automatically submitted on{' '} | ||
{timeUtil.timestampToLL(lockupEndTime.unix())}. Your deposit can be | ||
redeemed and yield rewards will stop on{' '} | ||
{timeUtil.timestampToLL(withdrawTime.unix())}. | ||
</Box> | ||
<BottomButton variant='contained' onClick={handleNext}> | ||
APPROVE ALLOWANCE | ||
</BottomButton> | ||
</WrapperModal> | ||
) | ||
} |
167 changes: 167 additions & 0 deletions
167
packages/huma-widget/src/components/Lend/solanaEnableAutoRedemption/2-Transfer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { | ||
getSentinelAddress, | ||
getTokenAccounts, | ||
SolanaPoolInfo, | ||
} from '@huma-finance/shared' | ||
import React, { useCallback, useEffect, useState } from 'react' | ||
|
||
import { | ||
notEnabledAutoRedeem, | ||
SolanaPoolState, | ||
useHumaProgram, | ||
useLenderAccounts, | ||
useTrancheTokenAccounts, | ||
} from '@huma-finance/web-shared' | ||
import { | ||
createApproveCheckedInstruction, | ||
TOKEN_2022_PROGRAM_ID, | ||
} from '@solana/spl-token' | ||
import { useWallet } from '@solana/wallet-adapter-react' | ||
import { PublicKey, Transaction } from '@solana/web3.js' | ||
import { useAppDispatch } from '../../../hooks/useRedux' | ||
import { setError, setStep } from '../../../store/widgets.reducers' | ||
import { WIDGET_STEP } from '../../../store/widgets.store' | ||
import { LoadingModal } from '../../LoadingModal' | ||
import { SolanaTxSendModal } from '../../SolanaTxSendModal' | ||
|
||
type Props = { | ||
poolInfo: SolanaPoolInfo | ||
poolState: SolanaPoolState | ||
} | ||
|
||
export function Transfer({ | ||
poolInfo, | ||
poolState, | ||
}: Props): React.ReactElement | null { | ||
const dispatch = useAppDispatch() | ||
const { publicKey } = useWallet() | ||
const sentinel = getSentinelAddress(poolInfo.chainId) | ||
const [transaction, setTransaction] = useState<Transaction>() | ||
const { | ||
juniorLenderApprovedAccountPDA, | ||
seniorLenderApprovedAccountPDA, | ||
seniorLenderStateAccount, | ||
juniorLenderStateAccount, | ||
seniorTrancheMintSupply, | ||
juniorTrancheMintSupply, | ||
loading: isLoadingLenderAccounts, | ||
} = useLenderAccounts(poolInfo.chainId, poolInfo.poolName) | ||
const { | ||
seniorTokenAccount, | ||
juniorTokenAccount, | ||
loading: isLoadingTrancheTokenAccounts, | ||
} = useTrancheTokenAccounts(poolInfo) | ||
const program = useHumaProgram(poolInfo.chainId) | ||
|
||
const handleSuccess = useCallback(() => { | ||
dispatch(setStep(WIDGET_STEP.Done)) | ||
}, [dispatch]) | ||
|
||
useEffect(() => { | ||
async function getTx() { | ||
if ( | ||
!publicKey || | ||
transaction || | ||
isLoadingLenderAccounts || | ||
isLoadingTrancheTokenAccounts | ||
) { | ||
return | ||
} | ||
|
||
const tx = new Transaction() | ||
|
||
const { seniorTrancheATA, juniorTrancheATA } = getTokenAccounts( | ||
poolInfo, | ||
publicKey, | ||
) | ||
const poolAuthorityPubkey = new PublicKey(poolInfo.poolAuthority) | ||
|
||
if (!seniorTokenAccount?.amount && !juniorTokenAccount?.amount) { | ||
dispatch( | ||
setError({ errorMessage: 'Error reading tranche token balance' }), | ||
) | ||
return | ||
} | ||
if ( | ||
notEnabledAutoRedeem( | ||
seniorTokenAccount, | ||
poolAuthorityPubkey, | ||
seniorTokenAccount?.amount, | ||
) | ||
) { | ||
tx.add( | ||
createApproveCheckedInstruction( | ||
seniorTrancheATA, | ||
new PublicKey(poolInfo.seniorTrancheMint), | ||
poolAuthorityPubkey, // delegate | ||
publicKey, // owner of the wallet | ||
BigInt(seniorTokenAccount?.amount.toString() ?? 0), // amount | ||
poolInfo.trancheDecimals, | ||
undefined, // multiSigners | ||
TOKEN_2022_PROGRAM_ID, | ||
), | ||
) | ||
} | ||
if ( | ||
notEnabledAutoRedeem( | ||
juniorTokenAccount, | ||
poolAuthorityPubkey, | ||
juniorTokenAccount?.amount, | ||
) | ||
) { | ||
tx.add( | ||
createApproveCheckedInstruction( | ||
juniorTrancheATA, | ||
new PublicKey(poolInfo.juniorTrancheMint), | ||
poolAuthorityPubkey, // delegate | ||
publicKey, // owner of the wallet | ||
BigInt(juniorTokenAccount?.amount.toString() ?? 0), // amount | ||
poolInfo.trancheDecimals, | ||
undefined, // multiSigners | ||
TOKEN_2022_PROGRAM_ID, | ||
), | ||
) | ||
} | ||
if (!tx.instructions.length) { | ||
dispatch( | ||
setError({ errorMessage: 'No tranches require Auto-Redemption' }), | ||
) | ||
return | ||
} | ||
|
||
setTransaction(tx) | ||
} | ||
getTx() | ||
}, [ | ||
dispatch, | ||
isLoadingLenderAccounts, | ||
isLoadingTrancheTokenAccounts, | ||
juniorLenderApprovedAccountPDA, | ||
juniorLenderStateAccount, | ||
juniorTokenAccount, | ||
juniorTrancheMintSupply, | ||
poolInfo, | ||
poolState.juniorTrancheAssets, | ||
poolState.seniorTrancheAssets, | ||
program.methods, | ||
publicKey, | ||
seniorLenderApprovedAccountPDA, | ||
seniorLenderStateAccount, | ||
seniorTokenAccount, | ||
seniorTrancheMintSupply, | ||
sentinel, | ||
transaction, | ||
]) | ||
|
||
if (isLoadingLenderAccounts || isLoadingTrancheTokenAccounts) { | ||
return <LoadingModal title='Auto-Redeem' /> | ||
} | ||
|
||
return ( | ||
<SolanaTxSendModal | ||
tx={transaction} | ||
chainId={poolInfo.chainId} | ||
handleSuccess={handleSuccess} | ||
/> | ||
) | ||
} |
Oops, something went wrong.