-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #79 from Hipo/feat/folks-lending-pools
Create folks-lending-pool util function
- Loading branch information
Showing
17 changed files
with
537 additions
and
1 deletion.
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 |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Algodv2 } from "algosdk"; | ||
import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; | ||
import { FolksLendingAssetInfo } from "../types"; | ||
export declare function generateTxns({ client, network, poolAddress, poolTokenId, lendingManagerId, asset1In, asset2In, initiatorAddr }: { | ||
client: Algodv2; | ||
network: SupportedNetwork; | ||
poolAddress: string; | ||
poolTokenId: number; | ||
lendingManagerId: number; | ||
asset1In: FolksLendingAssetInfo; | ||
asset2In: FolksLendingAssetInfo; | ||
initiatorAddr: string; | ||
}): Promise<SignerTransaction[]>; | ||
export declare function getAddLiquidityTotalFee(wrapperAppOptInRequiredAssetIdCount?: number): number; |
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,7 @@ | ||
import { Algodv2 } from "algosdk"; | ||
import { SupportedNetwork } from "../../util/commonTypes"; | ||
export declare function getFolksWrapperAppOptInRequiredAssetIDs({ client, network, assetIDs }: { | ||
client: Algodv2; | ||
network: SupportedNetwork; | ||
assetIDs: number[]; | ||
}): Promise<number[]>; |
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,7 @@ | ||
import { SupportedNetwork } from "../util/commonTypes"; | ||
declare const SECONDS_IN_YEAR: bigint; | ||
declare const ONE_14_DP: bigint; | ||
declare const ONE_16_DP: bigint; | ||
declare const FOLKS_WRAPPER_APP_ID: Record<SupportedNetwork, number>; | ||
declare const FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT = 14; | ||
export { SECONDS_IN_YEAR, ONE_14_DP, ONE_16_DP, FOLKS_WRAPPER_APP_ID, FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT }; |
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,25 @@ | ||
import algosdk from "algosdk"; | ||
import * as AddLiquidity from "./add-liquidity"; | ||
import * as RemoveLiquidity from "./remove-liquidity"; | ||
import { getFolksWrapperAppOptInRequiredAssetIDs } from "./add-liquidity/utils"; | ||
import { FolksLendingPool } from "./types"; | ||
/** | ||
* Calculates the amount fAsset received when adding liquidity with original asset. | ||
*/ | ||
declare function calculateDepositReturn(depositAmount: number, depositInterestIndex: bigint, depositInterestRate: bigint, lastUpdate?: number): bigint; | ||
/** | ||
* Calculates the amount original asset received when removing liquidity from fAsset pool. | ||
*/ | ||
declare function calculateWithdrawReturn(withdrawAmount: number, depositInterestIndex: bigint, depositInterestRate: bigint, lastUpdate?: number): bigint; | ||
/** | ||
* Fetches Folks lending pool application info from the algod, parses the global state and builds FolksLendingPool object. | ||
*/ | ||
export declare function fetchFolksLendingPool(algod: algosdk.Algodv2, appId: number): Promise<FolksLendingPool>; | ||
export declare const LendingPool: { | ||
AddLiquidity: typeof AddLiquidity; | ||
RemoveLiquidity: typeof RemoveLiquidity; | ||
calculateWithdrawReturn: typeof calculateWithdrawReturn; | ||
calculateDepositReturn: typeof calculateDepositReturn; | ||
getFolksWrapperAppOptInRequiredAssetIDs: typeof getFolksWrapperAppOptInRequiredAssetIDs; | ||
}; | ||
export {}; |
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,15 @@ | ||
import { Algodv2 } from "algosdk"; | ||
import { V2PoolInfo } from "../../util/pool/poolTypes"; | ||
import { SignerTransaction, SupportedNetwork } from "../../util/commonTypes"; | ||
import { FolksLendingAssetInfo } from "../types"; | ||
export declare function generateTxns({ client, pool, poolTokenIn, initiatorAddr, asset1Out, asset2Out, lendingManagerId, network }: { | ||
client: Algodv2; | ||
pool: Pick<V2PoolInfo, "account" | "poolTokenID">; | ||
poolTokenIn: number | bigint; | ||
initiatorAddr: string; | ||
asset1Out: Omit<FolksLendingAssetInfo, "amount">; | ||
asset2Out: Omit<FolksLendingAssetInfo, "amount">; | ||
lendingManagerId: number; | ||
network: SupportedNetwork; | ||
}): Promise<SignerTransaction[]>; | ||
export declare function getRemoveLiquidityTotalFee(): number; |
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,12 @@ | ||
import { AssetWithIdAndAmount } from "../util/asset/assetModels"; | ||
export type FolksLendingAssetInfo = AssetWithIdAndAmount & { | ||
fAssetId: number; | ||
lendingAppId: number; | ||
}; | ||
export interface FolksLendingPool { | ||
appId: number; | ||
managerAppId: number; | ||
depositInterestRate: bigint; | ||
depositInterestIndex: bigint; | ||
lastUpdate: number; | ||
} |
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,13 @@ | ||
/** | ||
* Utility function for converting the Algorand key-value schema into a plain object. | ||
* | ||
* Algorand store keys in base64 encoding and store values as either bytes or unsigned integers depending | ||
* on the type. This function decodes this information into a more human friendly structure. | ||
* | ||
* @param kv Algorand key-value data structure to parse. | ||
* | ||
* @returns Key value dictionary parsed from the argument. | ||
*/ | ||
export declare function parseState(kv: any): any; | ||
export declare function mulScale(n1: bigint, n2: bigint, scale: bigint): bigint; | ||
export declare function divScale(n1: bigint, n2: bigint, scale: bigint): bigint; |
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
Large diffs are not rendered by default.
Oops, something went wrong.
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,148 @@ | ||
import algosdk, { | ||
ALGORAND_MIN_TX_FEE, | ||
Algodv2, | ||
decodeAddress, | ||
encodeUint64 | ||
} from "algosdk"; | ||
|
||
import {SignerTransaction, SupportedNetwork} from "../../util/commonTypes"; | ||
import {isAlgo} from "../../util/asset/assetUtils"; | ||
import { | ||
FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT, | ||
FOLKS_WRAPPER_APP_ID | ||
} from "../constants"; | ||
import {encodeString} from "../../util/util"; | ||
import {FolksLendingAssetInfo} from "../types"; | ||
import {CONTRACT_VERSION} from "../../contract/constants"; | ||
import {getValidatorAppID} from "../../validator"; | ||
import {getFolksWrapperAppOptInRequiredAssetIDs} from "./utils"; | ||
import {MINIMUM_BALANCE_REQUIRED_PER_ASSET} from "../../util/constant"; | ||
|
||
export async function generateTxns({ | ||
client, | ||
network, | ||
poolAddress, | ||
poolTokenId, | ||
lendingManagerId, | ||
asset1In, | ||
asset2In, | ||
initiatorAddr | ||
}: { | ||
client: Algodv2; | ||
network: SupportedNetwork; | ||
poolAddress: string; | ||
poolTokenId: number; | ||
lendingManagerId: number; | ||
asset1In: FolksLendingAssetInfo; | ||
asset2In: FolksLendingAssetInfo; | ||
initiatorAddr: string; | ||
}): Promise<SignerTransaction[]> { | ||
const wrapperAppAddress = algosdk.getApplicationAddress(FOLKS_WRAPPER_APP_ID[network]); | ||
const suggestedParams = await client.getTransactionParams().do(); | ||
|
||
// Make sure to sort the assets according to the fAssetIds | ||
const [asset1, asset2] = [asset1In, asset2In].sort((a, b) => b.fAssetId - a.fAssetId); | ||
|
||
const isAlgoPool = isAlgo(asset2.id); | ||
|
||
const asset1InTxn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({ | ||
from: initiatorAddr, | ||
to: wrapperAppAddress, | ||
assetIndex: asset1.id, | ||
amount: asset1.amount, | ||
suggestedParams | ||
}); | ||
|
||
const asset2InTxn = isAlgoPool | ||
? algosdk.makePaymentTxnWithSuggestedParamsFromObject({ | ||
from: initiatorAddr, | ||
to: wrapperAppAddress, | ||
amount: asset2.amount, | ||
suggestedParams | ||
}) | ||
: algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({ | ||
from: initiatorAddr, | ||
to: wrapperAppAddress, | ||
assetIndex: asset2.id, | ||
amount: asset2.amount, | ||
suggestedParams | ||
}); | ||
|
||
const appCallTxn1 = algosdk.makeApplicationNoOpTxnFromObject({ | ||
from: initiatorAddr, | ||
appIndex: FOLKS_WRAPPER_APP_ID[network], | ||
appArgs: [ | ||
encodeString("add_liquidity"), | ||
decodeAddress(poolAddress).publicKey, | ||
encodeUint64(asset1.lendingAppId), | ||
encodeUint64(asset2.lendingAppId) | ||
], | ||
foreignAssets: [asset1.id, asset2.id, asset1.fAssetId, asset2.fAssetId], | ||
foreignApps: [asset1.lendingAppId, asset2.lendingAppId, lendingManagerId], | ||
accounts: [poolAddress], | ||
suggestedParams | ||
}); | ||
|
||
appCallTxn1.fee = | ||
ALGORAND_MIN_TX_FEE * (FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT + 1); | ||
|
||
const validatorAppID = getValidatorAppID(network, CONTRACT_VERSION.V2); | ||
const appCallTxn2 = algosdk.makeApplicationNoOpTxnFromObject({ | ||
from: initiatorAddr, | ||
appIndex: FOLKS_WRAPPER_APP_ID[network], | ||
appArgs: [encodeString("noop")], | ||
foreignAssets: [poolTokenId], | ||
foreignApps: [validatorAppID], | ||
accounts: [poolAddress], | ||
suggestedParams | ||
}); | ||
|
||
let txns = [asset1InTxn, asset2InTxn, appCallTxn1, appCallTxn2]; | ||
|
||
const optInRequiredAssetIds = await getFolksWrapperAppOptInRequiredAssetIDs({ | ||
client, | ||
network, | ||
assetIDs: [asset1.id, asset2.id, asset1.fAssetId, asset2.fAssetId, poolTokenId] | ||
}); | ||
|
||
if (optInRequiredAssetIds.length) { | ||
const wrapperAppAssetOptInTxns = [ | ||
algosdk.makePaymentTxnWithSuggestedParamsFromObject({ | ||
from: initiatorAddr, | ||
to: wrapperAppAddress, | ||
amount: MINIMUM_BALANCE_REQUIRED_PER_ASSET * optInRequiredAssetIds.length, | ||
suggestedParams | ||
}), | ||
algosdk.makeApplicationNoOpTxnFromObject({ | ||
from: initiatorAddr, | ||
appIndex: FOLKS_WRAPPER_APP_ID[network], | ||
appArgs: [ | ||
encodeString("asset_optin"), | ||
...optInRequiredAssetIds.map((assetId) => encodeUint64(assetId)) | ||
], | ||
foreignAssets: [...optInRequiredAssetIds], | ||
suggestedParams | ||
}) | ||
]; | ||
|
||
wrapperAppAssetOptInTxns[1].fee = | ||
(optInRequiredAssetIds.length + 1) * ALGORAND_MIN_TX_FEE; | ||
|
||
txns.unshift(...wrapperAppAssetOptInTxns); | ||
} | ||
|
||
return algosdk.assignGroupID(txns).map((txn) => { | ||
return {txn, signers: [initiatorAddr]}; | ||
}); | ||
} | ||
|
||
export function getAddLiquidityTotalFee(wrapperAppOptInRequiredAssetIdCount?: number) { | ||
// 1 asset transfer txn, 1 payment/asset transfer txn, 1 app call txn and 1 app call txn with inner txns | ||
return ( | ||
ALGORAND_MIN_TX_FEE * (4 + FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT) + | ||
(wrapperAppOptInRequiredAssetIdCount | ||
? (wrapperAppOptInRequiredAssetIdCount + 1) * ALGORAND_MIN_TX_FEE + | ||
wrapperAppOptInRequiredAssetIdCount * MINIMUM_BALANCE_REQUIRED_PER_ASSET | ||
: 0) | ||
); | ||
} |
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,26 @@ | ||
import {Algodv2, getApplicationAddress} from "algosdk"; | ||
|
||
import {SupportedNetwork} from "../../util/commonTypes"; | ||
import {FOLKS_WRAPPER_APP_ID} from "../constants"; | ||
import {getAccountInformation} from "../../util/account/accountUtils"; | ||
import {ALGO_ASSET_ID} from "../../util/asset/assetConstants"; | ||
|
||
export async function getFolksWrapperAppOptInRequiredAssetIDs({ | ||
client, | ||
network, | ||
assetIDs | ||
}: { | ||
client: Algodv2; | ||
network: SupportedNetwork; | ||
assetIDs: number[]; | ||
}) { | ||
const wrapperAppAddress = getApplicationAddress(FOLKS_WRAPPER_APP_ID[network]); | ||
const appOptedInAssetIDs = ( | ||
await getAccountInformation(client, wrapperAppAddress) | ||
).assets.map((asset) => asset["asset-id"]); | ||
|
||
return assetIDs.filter( | ||
(assetID: number) => | ||
assetID !== ALGO_ASSET_ID && !appOptedInAssetIDs.includes(assetID) | ||
); | ||
} |
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 @@ | ||
import {SupportedNetwork} from "../util/commonTypes"; | ||
|
||
// eslint-disable-next-line no-magic-numbers | ||
const SECONDS_IN_YEAR = BigInt(365 * 24 * 60 * 60); | ||
const ONE_14_DP = BigInt(1e14); | ||
const ONE_16_DP = BigInt(1e16); | ||
|
||
const FOLKS_WRAPPER_APP_ID: Record<SupportedNetwork, number> = { | ||
testnet: 548587153, | ||
mainnet: 1385499515 | ||
}; | ||
|
||
const FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT = 14; | ||
|
||
export { | ||
SECONDS_IN_YEAR, | ||
ONE_14_DP, | ||
ONE_16_DP, | ||
FOLKS_WRAPPER_APP_ID, | ||
FOLKS_LENDING_POOL_APP_CALL_INNER_TXN_COUNT | ||
}; |
Oops, something went wrong.