From e879b521bcc635c74e58a0a659ab16d81bbebac9 Mon Sep 17 00:00:00 2001 From: Danylo Moshenskyi Date: Mon, 6 Jan 2025 15:29:59 +0100 Subject: [PATCH] docs(examples): liquidation status check, PR comments --- examples/borrow-variable-rate.ts | 94 ------------------- examples/{borrow-stable-rate.ts => borrow.ts} | 31 ++---- examples/create-loan.ts | 35 ++----- ...eralise.ts => deposit-or-collateralise.ts} | 27 ++---- examples/link-address.ts | 37 +++----- examples/liquidate.ts | 62 ++++++++---- examples/read-write-account.ts | 21 ++--- examples/user-loan-info.ts | 8 +- 8 files changed, 98 insertions(+), 217 deletions(-) delete mode 100644 examples/borrow-variable-rate.ts rename examples/{borrow-stable-rate.ts => borrow.ts} (71%) rename examples/{deposit-collateralise.ts => deposit-or-collateralise.ts} (75%) diff --git a/examples/borrow-variable-rate.ts b/examples/borrow-variable-rate.ts deleted file mode 100644 index 5449cb9..0000000 --- a/examples/borrow-variable-rate.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { createClient, createWalletClient, http, parseUnits } from "viem"; -import { mnemonicToAccount } from "viem/accounts"; - -import { - NetworkType, - FolksCore, - FolksLoan, - FOLKS_CHAIN_ID, - getSupportedMessageAdapters, - Action, - MessageAdapterParamsType, - CHAIN_VIEM, - TESTNET_FOLKS_TOKEN_ID, -} from "../src/index.js"; - -import type { FolksCoreConfig, MessageAdapters, AccountId, LoanId } from "../src/index.js"; - -async function main() { - const chain = FOLKS_CHAIN_ID.AVALANCHE_FUJI; - const tokenId = TESTNET_FOLKS_TOKEN_ID.USDC; - const jsonRpcAddress = "https://my-rpc.avax-testnet.network/"; - - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { - evm: { - [chain]: createClient({ - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }), - }, - }, - }; - - FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); - - const MNEMONIC = "your mnemonic here"; - const account = mnemonicToAccount(MNEMONIC); - - const signer = createWalletClient({ - account, - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }); - - const { adapterIds, returnAdapterIds } = getSupportedMessageAdapters({ - action: Action.Borrow, - messageAdapterParamType: MessageAdapterParamsType.ReceiveToken, - network: NetworkType.TESTNET, - sourceFolksChainId: chain, - destFolksChainId: chain, - folksTokenId: tokenId, - }); - - const adapters: MessageAdapters = { - adapterId: adapterIds[0], - returnAdapterId: returnAdapterIds[0], - }; - - FolksCore.setFolksSigner({ signer, folksChainId: chain }); - - const accountId = "0x7d6...b66" as AccountId; // Your xChainApp account id - const loanId = "0x166...c12" as LoanId; // Your loan id - const amountToBorrow = parseUnits("1", 6); // 1 USDC (USDC has 6 decimals) - - const prepareBorrowCall = await FolksLoan.prepare.borrow( - accountId, - loanId, - tokenId, - amountToBorrow, - BigInt(0), - chain, - adapters, - ); - const createBorrowCallRes = await FolksLoan.write.borrow( - accountId, - loanId, - tokenId, - amountToBorrow, - BigInt(0), - chain, - prepareBorrowCall, - ); - console.log(`Transaction ID: ${createBorrowCallRes}`); -} - -main() - .then(() => { - console.log("done"); - }) - .catch((error: unknown) => { - console.error(error); - }); diff --git a/examples/borrow-stable-rate.ts b/examples/borrow.ts similarity index 71% rename from examples/borrow-stable-rate.ts rename to examples/borrow.ts index 4ef5a96..6e1c41d 100644 --- a/examples/borrow-stable-rate.ts +++ b/examples/borrow.ts @@ -1,5 +1,5 @@ -import { multiply, divide } from "dnum"; -import { createClient, createWalletClient, http, parseUnits } from "viem"; +import * as dn from "dnum"; +import { createWalletClient, http, parseUnits } from "viem"; import { mnemonicToAccount } from "viem/accounts"; import { @@ -18,24 +18,14 @@ import { import type { FolksCoreConfig, MessageAdapters, AccountId, LoanId } from "../src/index.js"; async function main() { + const network = NetworkType.TESTNET; const chain = FOLKS_CHAIN_ID.BSC_TESTNET; const tokenId = TESTNET_FOLKS_TOKEN_ID.BNB; - const jsonRpcAddress = "https://my-rpc.avax-testnet.network/"; - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { - evm: { - [chain]: createClient({ - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }), - }, - }, - }; + const folksConfig: FolksCoreConfig = { network, provider: { evm: {} } }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); const MNEMONIC = "your mnemonic here"; const account = mnemonicToAccount(MNEMONIC); @@ -43,13 +33,13 @@ async function main() { const signer = createWalletClient({ account, chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), + transport: http(), }); const { adapterIds, returnAdapterIds } = getSupportedMessageAdapters({ action: Action.Borrow, messageAdapterParamType: MessageAdapterParamsType.ReceiveToken, - network: NetworkType.TESTNET, + network, sourceFolksChainId: chain, destFolksChainId: chain, folksTokenId: tokenId, @@ -67,15 +57,14 @@ async function main() { const amountToBorrow = parseUnits("0.0005", 18); // 0.0005 BNB (BNB has 18 decimals) const poolInfo = await FolksPool.read.poolInfo(tokenId); const interestRate = poolInfo.stableBorrowData.interestRate[0]; - const stableRateSlippagePercent = 5; // 5% max deviation from current rate - const [maxStableRate] = divide(multiply(interestRate, 100 + stableRateSlippagePercent), 100); + const [maxStableRate] = dn.mul(interestRate, 1.05); // 5% max deviation from current rate const prepareBorrowCall = await FolksLoan.prepare.borrow( accountId, loanId, tokenId, amountToBorrow, - maxStableRate, + maxStableRate, // Use BigInt(0) for variable rate chain, adapters, ); @@ -84,7 +73,7 @@ async function main() { loanId, tokenId, amountToBorrow, - maxStableRate, + maxStableRate, // Use BigInt(0) for variable rate chain, prepareBorrowCall, ); diff --git a/examples/create-loan.ts b/examples/create-loan.ts index d72ad50..37bb0cc 100644 --- a/examples/create-loan.ts +++ b/examples/create-loan.ts @@ -1,4 +1,4 @@ -import { createClient, createWalletClient, http } from "viem"; +import { createWalletClient, http } from "viem"; import { mnemonicToAccount } from "viem/accounts"; import { convertStringToLoanName } from "../src/common/utils/lending.js"; @@ -19,23 +19,13 @@ import { import type { FolksCoreConfig, MessageAdapters, Nonce, AccountId } from "../src/index.js"; async function main() { + const network = NetworkType.TESTNET; const chain = FOLKS_CHAIN_ID.AVALANCHE_FUJI; - const jsonRpcAddress = "https://my-rpc.avax-testnet.network/"; - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { - evm: { - [chain]: createClient({ - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }), - }, - }, - }; + const folksConfig: FolksCoreConfig = { network, provider: { evm: {} } }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); const nonce: Nonce = getRandomBytes(BYTES4_LENGTH) as Nonce; @@ -45,13 +35,13 @@ async function main() { const signer = createWalletClient({ account, chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), + transport: http(), }); const { adapterIds, returnAdapterIds } = getSupportedMessageAdapters({ action: Action.CreateLoan, messageAdapterParamType: MessageAdapterParamsType.Data, - network: NetworkType.TESTNET, + network, sourceFolksChainId: chain, }); @@ -62,20 +52,15 @@ async function main() { FolksCore.setFolksSigner({ signer, folksChainId: chain }); - const accountId = "0x7d6...b66" as AccountId; //Your xChainApp account id + const accountId = "0x7d6...b66" as AccountId; // Your xChainApp account id + const loanType = LoanTypeId.GENERAL; // LoanTypeId.DEPOSIT for deposits const loanName = convertStringToLoanName("Test Loan"); - const prepareCreateLoanCall = await FolksLoan.prepare.createLoan( - accountId, - nonce, - LoanTypeId.GENERAL, // LoanTypeId.DEPOSIT for deposits - loanName, - adapters, - ); + const prepareCreateLoanCall = await FolksLoan.prepare.createLoan(accountId, nonce, loanType, loanName, adapters); const createLoanCallRes = await FolksLoan.write.createLoan( accountId, nonce, - LoanTypeId.GENERAL, // LoanTypeId.DEPOSIT for deposits + loanType, loanName, prepareCreateLoanCall, ); diff --git a/examples/deposit-collateralise.ts b/examples/deposit-or-collateralise.ts similarity index 75% rename from examples/deposit-collateralise.ts rename to examples/deposit-or-collateralise.ts index fd8c3ab..8b68923 100644 --- a/examples/deposit-collateralise.ts +++ b/examples/deposit-or-collateralise.ts @@ -1,4 +1,4 @@ -import { createClient, createWalletClient, http, parseUnits } from "viem"; +import { createWalletClient, http, parseUnits } from "viem"; import { mnemonicToAccount } from "viem/accounts"; import { @@ -17,24 +17,14 @@ import { import type { FolksCoreConfig, MessageAdapters, AccountId, LoanId } from "../src/index.js"; async function main() { + const network = NetworkType.TESTNET; const chain = FOLKS_CHAIN_ID.AVALANCHE_FUJI; const tokenId = TESTNET_FOLKS_TOKEN_ID.AVAX; - const jsonRpcAddress = "https://my-rpc.avax-testnet.network/"; - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { - evm: { - [chain]: createClient({ - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }), - }, - }, - }; + const folksConfig: FolksCoreConfig = { network, provider: { evm: {} } }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); const MNEMONIC = "your mnemonic here"; const account = mnemonicToAccount(MNEMONIC); @@ -42,13 +32,13 @@ async function main() { const signer = createWalletClient({ account, chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), + transport: http(), }); const { adapterIds, returnAdapterIds } = getSupportedMessageAdapters({ action: Action.Deposit, messageAdapterParamType: MessageAdapterParamsType.SendToken, - network: NetworkType.TESTNET, + network, sourceFolksChainId: chain, folksTokenId: tokenId, }); @@ -62,12 +52,13 @@ async function main() { const accountId = "0x7d6...b66" as AccountId; // Your xChainApp account id const loanId = "0x166...c12" as LoanId; // Your loan id + const loanType = LoanTypeId.GENERAL; // LoanTypeId.DEPOSIT for deposits const amountToDeposit = parseUnits("0.1", 18); // 0.1 AVAX (AVAX has 18 decimals) const prepareDepositCall = await FolksLoan.prepare.deposit( accountId, loanId, - LoanTypeId.GENERAL, // LoanTypeId.DEPOSIT for deposits + loanType, tokenId, amountToDeposit, adapters, @@ -76,7 +67,7 @@ async function main() { accountId, loanId, amountToDeposit, - false, + true, prepareDepositCall, ); console.log(`Transaction ID: ${createDepositCallRes}`); diff --git a/examples/link-address.ts b/examples/link-address.ts index 9e9b790..dd6cb88 100644 --- a/examples/link-address.ts +++ b/examples/link-address.ts @@ -1,4 +1,4 @@ -import { createClient, createWalletClient, http } from "viem"; +import { createWalletClient, http } from "viem"; import { mnemonicToAccount } from "viem/accounts"; import { @@ -17,29 +17,14 @@ import { import type { AccountId, EvmAddress, FolksCoreConfig, MessageAdapters } from "../src/index.js"; async function main() { + const network = NetworkType.TESTNET; const chain = FOLKS_CHAIN_ID.AVALANCHE_FUJI; const chainToLink = FOLKS_CHAIN_ID.BSC_TESTNET; - const jsonRpcAddress = "https://my-rpc.avax-testnet.network/"; - const jsonRpcAddressToLink = "https://my-rpc.bsc-testnet.network/"; - - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { - evm: { - [chain]: createClient({ - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }), - [chainToLink]: createClient({ - chain: CHAIN_VIEM[chainToLink], - transport: http(jsonRpcAddressToLink), - }), - }, - }, - }; + + const folksConfig: FolksCoreConfig = { network, provider: { evm: {} } }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); // invite const MNEMONIC = "your mnemonic here"; @@ -48,13 +33,13 @@ async function main() { const signer = createWalletClient({ account, chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), + transport: http(), }); const chainAdapters = getSupportedMessageAdapters({ action: Action.InviteAddress, messageAdapterParamType: MessageAdapterParamsType.Data, - network: NetworkType.TESTNET, + network, sourceFolksChainId: chain, }); @@ -82,13 +67,13 @@ async function main() { const signerToLink = createWalletClient({ account: accountToLink, chain: CHAIN_VIEM[chainToLink], - transport: http(jsonRpcAddressToLink), + transport: http(), }); const chainAdaptersToLink = getSupportedMessageAdapters({ action: Action.AcceptInviteAddress, messageAdapterParamType: MessageAdapterParamsType.Data, - network: NetworkType.TESTNET, + network, sourceFolksChainId: chainToLink, }); @@ -102,9 +87,9 @@ async function main() { folksChainId: chainToLink, }); - const acceptInviteCall = await FolksAccount.prepare.acceptInvite(accountId, adaptersToLink); + const prepareAcceptInviteCall = await FolksAccount.prepare.acceptInvite(accountId, adaptersToLink); - const acceptInviteRes = await FolksAccount.write.acceptInvite(accountId, acceptInviteCall); + const acceptInviteRes = await FolksAccount.write.acceptInvite(accountId, prepareAcceptInviteCall); console.log(`Accept transaction ID: ${acceptInviteRes}`); } diff --git a/examples/liquidate.ts b/examples/liquidate.ts index 8a8028c..3bfe308 100644 --- a/examples/liquidate.ts +++ b/examples/liquidate.ts @@ -1,28 +1,29 @@ -import { createClient, createWalletClient, http, parseUnits } from "viem"; +import * as dn from "dnum"; +import { createWalletClient, http, parseUnits } from "viem"; import { mnemonicToAccount } from "viem/accounts"; -import { NetworkType, FolksCore, FolksLoan, FOLKS_CHAIN_ID, CHAIN_VIEM, TESTNET_FOLKS_TOKEN_ID } from "../src/index.js"; +import { + NetworkType, + FolksCore, + FolksLoan, + FOLKS_CHAIN_ID, + CHAIN_VIEM, + TESTNET_FOLKS_TOKEN_ID, + FolksPool, + LoanTypeId, + FolksOracle, +} from "../src/index.js"; -import type { FolksCoreConfig, AccountId, LoanId } from "../src/index.js"; +import type { FolksCoreConfig, AccountId, LoanId, FolksTokenId, PoolInfo } from "../src/index.js"; async function main() { + const network = NetworkType.TESTNET; const chain = FOLKS_CHAIN_ID.AVALANCHE_FUJI; - const jsonRpcAddress = "https://my-rpc.avax-testnet.network/"; - - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { - evm: { - [chain]: createClient({ - chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), - }), - }, - }, - }; + + const folksConfig: FolksCoreConfig = { network, provider: { evm: {} } }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); const MNEMONIC = "your mnemonic here"; const account = mnemonicToAccount(MNEMONIC); @@ -30,7 +31,7 @@ async function main() { const signer = createWalletClient({ account, chain: CHAIN_VIEM[chain], - transport: http(jsonRpcAddress), + transport: http(), }); FolksCore.setFolksSigner({ signer, folksChainId: chain }); @@ -38,9 +39,32 @@ async function main() { const accountId = "0x7d6...b66" as AccountId; // Your xChainApp account id const liquidatorLoanId = "0x4c6...824" as LoanId; // Your loan id to transfer debt and collateral into const violatorLoanId = "0xcd1...632" as LoanId; // Loan to liquidate + + // check if loan can be liquidated + const poolsInfo: Partial> = {}; + await Promise.all( + Object.values(TESTNET_FOLKS_TOKEN_ID).map(async (folksTokenId) => { + const poolInfo = await FolksPool.read.poolInfo(folksTokenId); + poolsInfo[folksTokenId] = poolInfo; + }), + ); + const loanTypeInfo = { + [LoanTypeId.GENERAL]: await FolksLoan.read.loanTypeInfo(LoanTypeId.GENERAL), + }; + const oraclePrices = await FolksOracle.read.oraclePrices(); + + const userGeneralLoans = await FolksLoan.read.userLoans([violatorLoanId]); + const userGeneralLoansInfo = FolksLoan.util.userLoansInfo(userGeneralLoans, poolsInfo, loanTypeInfo, oraclePrices); + const violatorLoanInfo = userGeneralLoansInfo[violatorLoanId]; + + if (dn.lt(violatorLoanInfo.totalEffectiveBorrowBalanceValue, violatorLoanInfo.totalEffectiveCollateralBalanceValue)) { + console.log("Loan can't be liquidated."); + return; + } + + // liquidate const amountToRepay = parseUnits("0.01", 18); const minAmountToSeize = parseUnits("0.5", 18); - const prepareLiquidationCall = await FolksLoan.prepare.liquidate( accountId, liquidatorLoanId, diff --git a/examples/read-write-account.ts b/examples/read-write-account.ts index b110381..3f797cb 100644 --- a/examples/read-write-account.ts +++ b/examples/read-write-account.ts @@ -14,18 +14,19 @@ import { buildAccountId, convertToGenericAddress, ChainType, + CHAIN_VIEM, } from "../src/index.js"; import type { EvmAddress, FolksCoreConfig, MessageAdapters, Nonce } from "../src/index.js"; async function main() { - const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, - provider: { evm: {} }, - }; + const network = NetworkType.TESTNET; + const chain = FOLKS_CHAIN_ID.AVALANCHE_FUJI; + + const folksConfig: FolksCoreConfig = { network, provider: { evm: {} } }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); const nonce: Nonce = getRandomBytes(BYTES4_LENGTH) as Nonce; @@ -35,14 +36,15 @@ async function main() { const signer = createWalletClient({ account, + chain: CHAIN_VIEM[chain], transport: http(), }); const { adapterIds, returnAdapterIds } = getSupportedMessageAdapters({ action: Action.CreateAccount, messageAdapterParamType: MessageAdapterParamsType.Data, - network: NetworkType.TESTNET, - sourceFolksChainId: FOLKS_CHAIN_ID.AVALANCHE_FUJI, + network, + sourceFolksChainId: chain, }); const adapters: MessageAdapters = { @@ -50,10 +52,7 @@ async function main() { returnAdapterId: returnAdapterIds[0], }; - FolksCore.setFolksSigner({ - signer, - folksChainId: FOLKS_CHAIN_ID.AVALANCHE_FUJI, - }); + FolksCore.setFolksSigner({ signer, folksChainId: chain }); // read const folksChain = FolksCore.getSelectedFolksChain(); diff --git a/examples/user-loan-info.ts b/examples/user-loan-info.ts index 7a83ded..3c28643 100644 --- a/examples/user-loan-info.ts +++ b/examples/user-loan-info.ts @@ -15,8 +15,10 @@ import { import type { AccountId, FolksCoreConfig, PoolInfo, FolksTokenId } from "../src/index.js"; async function main() { + const network = NetworkType.TESTNET; + const folksConfig: FolksCoreConfig = { - network: NetworkType.TESTNET, + network, provider: { evm: { [FOLKS_CHAIN_ID.AVALANCHE_FUJI]: createClient({ @@ -28,7 +30,7 @@ async function main() { }; FolksCore.init(folksConfig); - FolksCore.setNetwork(NetworkType.TESTNET); + FolksCore.setNetwork(network); const poolsInfo: Partial> = {}; await Promise.all( @@ -42,7 +44,7 @@ async function main() { }; const oraclePrices = await FolksOracle.read.oraclePrices(); - const accountId: AccountId = "my account id" as AccountId; + const accountId: AccountId = "0x7d6...b66" as AccountId; const loanIds = await FolksLoan.read.userLoansIds(accountId, [LoanTypeId.GENERAL]); const generalLoansIds = loanIds.get(LoanTypeId.GENERAL);