Skip to content

Commit

Permalink
Merge pull request #378 from 00labs/solana-autoredeem-upgrade
Browse files Browse the repository at this point in the history
Solana autoredeem upgrade [do not merge]
  • Loading branch information
mliu authored Dec 31, 2024
2 parents 9aa80fd + 8bd49c5 commit d51c0f4
Show file tree
Hide file tree
Showing 8 changed files with 1,528 additions and 1,299 deletions.
1 change: 1 addition & 0 deletions packages/examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"solanaFetchAvailableCredit": "ts-node src/solana/fetchAvailableCredit.ts",
"solanaFetchBorrowerDetails": "ts-node src/solana/fetchBorrowerDetails.ts",
"solanaDrawdown": "ts-node src/solana/drawdown.ts",
"solanaWithdrawYield": "ts-node src/solana/withdrawYield.ts",
"solanaPayback": "ts-node src/solana/payback.ts",
"lint-staged": "lint-staged"
},
Expand Down
46 changes: 46 additions & 0 deletions packages/examples/src/solana/withdrawYield.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Connection, Keypair, sendAndConfirmTransaction } from '@solana/web3.js'
import {
AnchorProvider,
BN,
setProvider,
Wallet,
web3,
} from '@coral-xyz/anchor'
import { POOL_NAME, SolanaChainEnum } from '@huma-finance/shared'
import { HumaSolanaContext, HumaSolanaProgramHelper } from '@huma-finance/sdk'

require('dotenv').config()

async function main() {
const TEST_PRIVATE_KEY = process.env.TEST_PRIVATE_KEY
const connection = new Connection(
'https://api.devnet.solana.com',
'confirmed',
)

const keypair = web3.Keypair.fromSecretKey(
Buffer.from(JSON.parse(TEST_PRIVATE_KEY)),
)
const wallet = new Wallet(keypair)
setProvider(new AnchorProvider(connection, wallet))

const solanaHumaContext = new HumaSolanaContext({
publicKey: wallet.publicKey,
connection: connection,
chainId: SolanaChainEnum.SolanaDevnet,
poolName: POOL_NAME.ArfCreditPool3Months,
})

const humaSolanaProgramHelper = new HumaSolanaProgramHelper({
solanaContext: solanaHumaContext,
})

const tx = await humaSolanaProgramHelper.buildWithdrawYieldsTransaction()

console.log(tx)

const txResult = await sendAndConfirmTransaction(connection, tx, [keypair])
console.log(txResult)
}

main()
97 changes: 96 additions & 1 deletion packages/huma-sdk/src/helpers/solana/HumaSolanaProgramHelper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BN } from '@coral-xyz/anchor'
import { BN, utils } from '@coral-xyz/anchor'
import {
getCreditAccounts,
getHumaProgram,
Expand All @@ -11,6 +11,7 @@ import {
createApproveCheckedInstruction,
createAssociatedTokenAccountInstruction,
getAccount,
TOKEN_2022_PROGRAM_ID,
TOKEN_PROGRAM_ID,
TokenAccountNotFoundError,
} from '@solana/spl-token'
Expand Down Expand Up @@ -127,6 +128,100 @@ export class HumaSolanaProgramHelper {
return tx
}

async buildWithdrawYieldsTransaction(): Promise<Transaction> {
const { publicKey, connection, chainId, poolName } = this.#solanaContext
const program = getHumaProgram(chainId, connection)
const poolInfo = getSolanaPoolInfo(chainId, poolName)

if (!poolInfo) {
throw new Error('Could not find pool')
}

const tx: Transaction = new Transaction()

const { underlyingTokenATA, seniorTrancheATA, juniorTrancheATA } =
getTokenAccounts(poolInfo, publicKey)
const [juniorYieldDistributingLenderAccount] =
PublicKey.findProgramAddressSync(
[
utils.bytes.utf8.encode('yield_distributing_lender'),
new PublicKey(poolInfo.juniorTrancheMint).toBuffer(),
publicKey.toBuffer(),
],
program.programId,
)
const programTx = await program.methods
.withdrawYields()
.accountsPartial({
lender: publicKey,
humaConfig: poolInfo.humaConfig,
poolConfig: poolInfo.poolConfig,
yieldDistributingLender: juniorYieldDistributingLenderAccount,
underlyingMint: poolInfo.underlyingMint.address,
poolUnderlyingToken: poolInfo.poolUnderlyingTokenAccount,
lenderUnderlyingToken: underlyingTokenATA,
trancheMint: poolInfo.juniorTrancheMint,
lenderTrancheToken: juniorTrancheATA,
underlyingTokenProgram: TOKEN_PROGRAM_ID,
trancheTokenProgram: TOKEN_2022_PROGRAM_ID,
})
.transaction()
const txAccounts: PublicKey[] = [
publicKey,
new PublicKey(poolInfo.humaConfig),
new PublicKey(poolInfo.poolConfig),
juniorYieldDistributingLenderAccount,
new PublicKey(poolInfo.underlyingMint.address),
new PublicKey(poolInfo.poolUnderlyingTokenAccount),
underlyingTokenATA,
new PublicKey(poolInfo.juniorTrancheMint),
juniorTrancheATA,
TOKEN_PROGRAM_ID,
TOKEN_2022_PROGRAM_ID,
]
tx.add(programTx)

if (poolInfo.seniorTrancheMint) {
const [seniorYieldDistributingLenderAccount] =
PublicKey.findProgramAddressSync(
[
utils.bytes.utf8.encode('yield_distributing_lender'),
new PublicKey(poolInfo.seniorTrancheMint).toBuffer(),
publicKey.toBuffer(),
],
program.programId,
)
const programTx = await program.methods
.withdrawYields()
.accountsPartial({
lender: publicKey,
humaConfig: poolInfo.humaConfig,
poolConfig: poolInfo.poolConfig,
yieldDistributingLender: seniorYieldDistributingLenderAccount,
underlyingMint: poolInfo.underlyingMint.address,
poolUnderlyingToken: poolInfo.poolUnderlyingTokenAccount,
lenderUnderlyingToken: underlyingTokenATA,
trancheMint: poolInfo.seniorTrancheMint,
lenderTrancheToken: seniorTrancheATA,
underlyingTokenProgram: TOKEN_PROGRAM_ID,
trancheTokenProgram: TOKEN_2022_PROGRAM_ID,
})
.transaction()
txAccounts.push(
...[
seniorYieldDistributingLenderAccount,
new PublicKey(poolInfo.seniorTrancheMint),
seniorTrancheATA,
],
)
tx.add(programTx)
}

await buildOptimalTransaction(tx, txAccounts, this.#solanaContext)

return tx
}

async buildDrawdownTransaction(amount: BN): Promise<Transaction> {
const { publicKey, connection, chainId, poolName } = this.#solanaContext
const program = getHumaProgram(chainId, connection)
Expand Down
Loading

0 comments on commit d51c0f4

Please sign in to comment.