From e0a436536ea94a03b1937284d49b10a53c3b1f10 Mon Sep 17 00:00:00 2001 From: fum-is-chum Date: Fri, 10 May 2024 12:00:27 +0700 Subject: [PATCH] feat: expose get binded obligation and get binded vesca for borrow incentive --- src/builders/borrowIncentiveBuilder.ts | 61 ++--------------- src/models/scallopQuery.ts | 20 ++++++ src/queries/borrowIncentiveQuery.ts | 95 ++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 55 deletions(-) diff --git a/src/builders/borrowIncentiveBuilder.ts b/src/builders/borrowIncentiveBuilder.ts index fff332a..6313083 100644 --- a/src/builders/borrowIncentiveBuilder.ts +++ b/src/builders/borrowIncentiveBuilder.ts @@ -2,7 +2,11 @@ import { TransactionBlock } from '@mysten/sui.js/transactions'; import { SUI_CLOCK_OBJECT_ID } from '@mysten/sui.js/utils'; import { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit'; import { borrowIncentiveRewardCoins } from '../constants/enum'; -import { getObligations, getObligationLocked } from '../queries'; +import { + getObligations, + getObligationLocked, + getBindedObligationId, +} from '../queries'; import { requireSender } from '../utils'; import type { SuiObjectArg } from '@scallop-io/sui-kit'; import type { ScallopBuilder } from '../models'; @@ -75,59 +79,6 @@ const requireObligationInfo = async ( }; }; -/** - * Check veSca bind status - * @param query - * @param veScaKey - * @returns - */ -export const getBindedObligationId = async ( - builder: ScallopBuilder, - veScaKey: string -) => { - const borrowIncentiveObjectId = builder.address.get('borrowIncentive.object'); - const incentivePoolsId = builder.address.get( - 'borrowIncentive.incentivePools' - ); - const veScaPkgId = IS_VE_SCA_TEST - ? '0xb220d034bdf335d77ae5bfbf6daf059c2cc7a1f719b12bfed75d1736fac038c8' - : builder.address.get('vesca.id'); - - const client = builder.suiKit.client(); - - // get incentive pools - const incentivePoolsResponse = await client.getObject({ - id: incentivePoolsId, - options: { - showContent: true, - }, - }); - - if (incentivePoolsResponse.data?.content?.dataType !== 'moveObject') - return false; - const incentivePoolFields = incentivePoolsResponse.data.content.fields as any; - const veScaBindTableId = incentivePoolFields.ve_sca_bind.fields.id - .id as string; - - // check if veSca is inside the bind table - const keyType = `${borrowIncentiveObjectId}::typed_id::TypedID<${veScaPkgId}::ve_sca::VeScaKey>`; - const veScaBindTableResponse = await client.getDynamicFieldObject({ - parentId: veScaBindTableId, - name: { - type: keyType, - value: veScaKey, - }, - }); - - if (veScaBindTableResponse.data?.content?.dataType !== 'moveObject') - return false; - const veScaBindTableFields = veScaBindTableResponse.data.content - .fields as any; - // get obligationId pair - const obligationId = veScaBindTableFields.value.fields.id as string; - - return obligationId; -}; /** * Generate borrow incentive normal methods. * @@ -322,7 +273,7 @@ const generateBorrowIncentiveQuickMethod: GenerateBorrowIncentiveQuickMethod = const veSca = await requireVeSca(builder, txBlock, veScaKey); if (veSca) { const bindedObligationId = await getBindedObligationId( - builder, + builder.query, veSca.keyId ); // if bindedObligationId is equal to obligationId, then use it again diff --git a/src/models/scallopQuery.ts b/src/models/scallopQuery.ts index 638c338..df32f6b 100644 --- a/src/models/scallopQuery.ts +++ b/src/models/scallopQuery.ts @@ -25,6 +25,8 @@ import { getObligationAccounts, getObligationAccount, getTotalValueLocked, + getBindedObligationId, + getBindedVeScaKey, } from '../queries'; import { ScallopQueryParams, @@ -512,4 +514,22 @@ export class ScallopQuery { public async getTvl(indexer: boolean = false) { return await getTotalValueLocked(this, indexer); } + + /** + * Get binded obligationId from a veScaKey if it exists. + * @param veScaKey + * @returns obligationId + */ + public async getBindedObligationId(veScaKey: string) { + return await getBindedObligationId(this, veScaKey); + } + + /** + * Get binded veSCA key from a obligationId if it exists. + * @param obligationId + * @returns veScaKey + */ + public async getBindedVeScaKey(obligationId: string) { + return await getBindedVeScaKey(this, obligationId); + } } diff --git a/src/queries/borrowIncentiveQuery.ts b/src/queries/borrowIncentiveQuery.ts index 3f2bd6e..7f8f81e 100644 --- a/src/queries/borrowIncentiveQuery.ts +++ b/src/queries/borrowIncentiveQuery.ts @@ -1,6 +1,7 @@ import { normalizeStructTag } from '@mysten/sui.js/utils'; import { SuiTxBlock as SuiKitTxBlock } from '@scallop-io/sui-kit'; import { + IS_VE_SCA_TEST, SUPPORT_BORROW_INCENTIVE_POOLS, SUPPORT_BORROW_INCENTIVE_REWARDS, } from '../constants'; @@ -197,3 +198,97 @@ export const queryBorrowIncentiveAccounts = async ( return borrowIncentiveAccounts; }; + +/** + * Check veSca bind status + * @param query + * @param veScaKey + * @returns + */ +export const getBindedObligationId = async ( + query: ScallopQuery, + veScaKey: string +): Promise => { + const borrowIncentiveObjectId = query.address.get('borrowIncentive.object'); + const incentivePoolsId = query.address.get('borrowIncentive.incentivePools'); + const veScaPkgId = IS_VE_SCA_TEST + ? '0xb220d034bdf335d77ae5bfbf6daf059c2cc7a1f719b12bfed75d1736fac038c8' + : query.address.get('vesca.id'); + + const client = query.suiKit.client(); + + // get incentive pools + const incentivePoolsResponse = await client.getObject({ + id: incentivePoolsId, + options: { + showContent: true, + }, + }); + + if (incentivePoolsResponse.data?.content?.dataType !== 'moveObject') + return null; + const incentivePoolFields = incentivePoolsResponse.data.content.fields as any; + const veScaBindTableId = incentivePoolFields.ve_sca_bind.fields.id + .id as string; + + // check if veSca is inside the bind table + const keyType = `${borrowIncentiveObjectId}::typed_id::TypedID<${veScaPkgId}::ve_sca::VeScaKey>`; + const veScaBindTableResponse = await client.getDynamicFieldObject({ + parentId: veScaBindTableId, + name: { + type: keyType, + value: veScaKey, + }, + }); + + if (veScaBindTableResponse.data?.content?.dataType !== 'moveObject') + return null; + const veScaBindTableFields = veScaBindTableResponse.data.content + .fields as any; + // get obligationId pair + const obligationId = veScaBindTableFields.value.fields.id as string; + + return obligationId; +}; + +export const getBindedVeScaKey = async ( + query: ScallopQuery, + obliationId: string +): Promise => { + const borrowIncentiveObjectId = query.address.get('borrowIncentive.object'); + const incentiveAccountsId = query.address.get( + 'borrowIncentive.incentiveAccounts' + ); + const corePkg = query.address.get('core.object'); + const client = query.suiKit.client(); + + // get IncentiveAccounts object + const incentiveAccountsObject = await client.getObject({ + id: incentiveAccountsId, + options: { + showContent: true, + }, + }); + if (incentiveAccountsObject.data?.content?.dataType !== 'moveObject') + return null; + const incentiveAccountsTableId = ( + incentiveAccountsObject.data.content.fields as any + ).accounts.fields.id.id; + + // Search in the table + const bindedIncentiveAcc = await client.getDynamicFieldObject({ + parentId: incentiveAccountsTableId, + name: { + type: `${borrowIncentiveObjectId}::typed_id::TypedID<${corePkg}::obligation::Obligation>`, + value: obliationId, + }, + }); + + if (bindedIncentiveAcc.data?.content?.dataType !== 'moveObject') return null; + const bindedIncentiveAccFields = bindedIncentiveAcc.data.content + .fields as any; + + return ( + bindedIncentiveAccFields.value.fields.binded_ve_sca_key?.fields.id ?? null + ); +};