@scallop-io/sui-scallop-sdk 0.45.0 → 0.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/builders/borrowIncentiveBuilder.d.ts +1 -1
  2. package/dist/builders/referralBuilder.d.ts +12 -0
  3. package/dist/constants/common.d.ts +1 -1
  4. package/dist/index.js +533 -279
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +587 -329
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/models/scallopCache.d.ts +6 -2
  9. package/dist/models/scallopQuery.d.ts +26 -28
  10. package/dist/queries/coreQuery.d.ts +3 -29
  11. package/dist/queries/index.d.ts +1 -0
  12. package/dist/queries/priceQuery.d.ts +3 -1
  13. package/dist/queries/referralQuery.d.ts +7 -0
  14. package/dist/queries/vescaQuery.d.ts +6 -2
  15. package/dist/types/address.d.ts +15 -0
  16. package/dist/types/builder/core.d.ts +2 -0
  17. package/dist/types/builder/index.d.ts +2 -1
  18. package/dist/types/builder/referral.d.ts +30 -0
  19. package/dist/types/builder/vesca.d.ts +1 -0
  20. package/package.json +7 -6
  21. package/src/builders/borrowIncentiveBuilder.ts +10 -19
  22. package/src/builders/coreBuilder.ts +54 -0
  23. package/src/builders/index.ts +5 -2
  24. package/src/builders/referralBuilder.ts +178 -0
  25. package/src/builders/vescaBuilder.ts +8 -6
  26. package/src/constants/common.ts +9 -2
  27. package/src/constants/vesca.ts +1 -3
  28. package/src/models/scallopAddress.ts +63 -19
  29. package/src/models/scallopCache.ts +42 -2
  30. package/src/models/scallopQuery.ts +40 -0
  31. package/src/models/scallopUtils.ts +35 -35
  32. package/src/queries/borrowIncentiveQuery.ts +2 -5
  33. package/src/queries/coreQuery.ts +33 -197
  34. package/src/queries/index.ts +1 -0
  35. package/src/queries/priceQuery.ts +48 -7
  36. package/src/queries/referralQuery.ts +27 -0
  37. package/src/queries/spoolQuery.ts +8 -12
  38. package/src/queries/vescaQuery.ts +94 -15
  39. package/src/types/address.ts +15 -0
  40. package/src/types/builder/core.ts +14 -0
  41. package/src/types/builder/index.ts +2 -0
  42. package/src/types/builder/referral.ts +51 -0
  43. package/src/types/builder/vesca.ts +1 -0
@@ -1,5 +1,4 @@
1
1
  import { normalizeStructTag } from '@mysten/sui.js/utils';
2
- import BigNumber from 'bignumber.js';
3
2
  import {
4
3
  SUPPORT_POOLS,
5
4
  PROTOCOL_OBJECT_ID,
@@ -32,10 +31,10 @@ import {
32
31
  BalanceSheet,
33
32
  RiskModel,
34
33
  CollateralStat,
35
- CoinAmounts,
36
- MarketCoinAmounts,
37
34
  SupportMarketCoins,
35
+ OptionalKeys,
38
36
  } from '../types';
37
+ import BigNumber from 'bignumber.js';
39
38
 
40
39
  /**
41
40
  * Query market data.
@@ -782,61 +781,16 @@ export const getCoinAmounts = async (
782
781
  ) => {
783
782
  assetCoinNames = assetCoinNames || [...SUPPORT_POOLS];
784
783
  const owner = ownerAddress || query.suiKit.currentAddress();
785
- const coinObjectsResponse: SuiObjectResponse[] = [];
786
- let hasNextPage = false;
787
- let nextCursor: string | null | undefined = null;
788
- do {
789
- const paginatedCoinObjectsResponse = await query.cache.queryGetOwnedObjects(
790
- {
791
- owner,
792
- filter: {
793
- MatchAny: assetCoinNames.map((assetCoinName) => {
794
- const coinType = query.utils.parseCoinType(assetCoinName);
795
- return { StructType: `0x2::coin::Coin<${coinType}>` };
796
- }),
797
- },
798
- options: {
799
- showType: true,
800
- showContent: true,
801
- },
802
- cursor: nextCursor,
803
- }
804
- );
805
-
806
- coinObjectsResponse.push(...paginatedCoinObjectsResponse.data);
807
- if (
808
- paginatedCoinObjectsResponse.hasNextPage &&
809
- paginatedCoinObjectsResponse.nextCursor
810
- ) {
811
- hasNextPage = true;
812
- nextCursor = paginatedCoinObjectsResponse.nextCursor;
813
- } else {
814
- hasNextPage = false;
815
- }
816
- } while (hasNextPage);
784
+ const assetCoins = {} as OptionalKeys<Record<SupportAssetCoins, number>>;
817
785
 
818
- const coinAmounts: CoinAmounts = {};
819
- const coinObjects = coinObjectsResponse
820
- .map((response) => {
821
- return response.data;
786
+ await Promise.allSettled(
787
+ assetCoinNames.map(async (assetCoinName) => {
788
+ const marketCoin = await getCoinAmount(query, assetCoinName, owner);
789
+ assetCoins[assetCoinName] = marketCoin;
822
790
  })
823
- .filter(
824
- (object: any) => object !== undefined && object !== null
825
- ) as SuiObjectData[];
826
- for (const coinObject of coinObjects) {
827
- const type = coinObject.type as string;
828
- if (coinObject.content && 'fields' in coinObject.content) {
829
- const fields = coinObject.content.fields as any;
830
- const poolCoinName =
831
- query.utils.parseCoinNameFromType<SupportPoolCoins>(type);
832
- if (poolCoinName) {
833
- coinAmounts[poolCoinName] = BigNumber(coinAmounts[poolCoinName] ?? 0)
834
- .plus(fields.balance)
835
- .toNumber();
836
- }
837
- }
838
- }
839
- return coinAmounts;
791
+ );
792
+
793
+ return assetCoins;
840
794
  };
841
795
 
842
796
  /**
@@ -854,48 +808,11 @@ export const getCoinAmount = async (
854
808
  ) => {
855
809
  const owner = ownerAddress || query.suiKit.currentAddress();
856
810
  const coinType = query.utils.parseCoinType(assetCoinName);
857
- const coinObjectsResponse: SuiObjectResponse[] = [];
858
- let hasNextPage = false;
859
- let nextCursor: string | null | undefined = null;
860
- do {
861
- const paginatedCoinObjectsResponse = await query.cache.queryGetOwnedObjects(
862
- {
863
- owner,
864
- filter: { StructType: `0x2::coin::Coin<${coinType}>` },
865
- options: {
866
- showContent: true,
867
- },
868
- cursor: nextCursor,
869
- }
870
- );
871
-
872
- coinObjectsResponse.push(...paginatedCoinObjectsResponse.data);
873
- if (
874
- paginatedCoinObjectsResponse.hasNextPage &&
875
- paginatedCoinObjectsResponse.nextCursor
876
- ) {
877
- hasNextPage = true;
878
- nextCursor = paginatedCoinObjectsResponse.nextCursor;
879
- } else {
880
- hasNextPage = false;
881
- }
882
- } while (hasNextPage);
883
-
884
- let coinAmount: number = 0;
885
- const coinObjects = coinObjectsResponse
886
- .map((response) => {
887
- return response.data;
888
- })
889
- .filter(
890
- (object: any) => object !== undefined && object !== null
891
- ) as SuiObjectData[];
892
- for (const coinObject of coinObjects) {
893
- if (coinObject.content && 'fields' in coinObject.content) {
894
- const fields = coinObject.content.fields as any;
895
- coinAmount = BigNumber(coinAmount).plus(fields.balance).toNumber();
896
- }
897
- }
898
- return coinAmount;
811
+ const amount = await query.cache.queryGetCoinBalance({
812
+ owner,
813
+ coinType: coinType,
814
+ });
815
+ return BigNumber(amount).toNumber();
899
816
  };
900
817
 
901
818
  /**
@@ -917,63 +834,20 @@ export const getMarketCoinAmounts = async (
917
834
  query.utils.parseMarketCoinName(poolCoinName)
918
835
  );
919
836
  const owner = ownerAddress || query.suiKit.currentAddress();
920
- const marketCoinObjectsResponse: SuiObjectResponse[] = [];
921
- let hasNextPage = false;
922
- let nextCursor: string | null | undefined = null;
923
- do {
924
- const paginatedMarketCoinObjectsResponse =
925
- await query.cache.queryGetOwnedObjects({
926
- owner,
927
- filter: {
928
- MatchAny: marketCoinNames.map((marketCoinName) => {
929
- const marketCoinType =
930
- query.utils.parseMarketCoinType(marketCoinName);
931
- return { StructType: `0x2::coin::Coin<${marketCoinType}>` };
932
- }),
933
- },
934
- options: {
935
- showType: true,
936
- showContent: true,
937
- },
938
- cursor: nextCursor,
939
- });
940
-
941
- marketCoinObjectsResponse.push(...paginatedMarketCoinObjectsResponse.data);
942
- if (
943
- paginatedMarketCoinObjectsResponse.hasNextPage &&
944
- paginatedMarketCoinObjectsResponse.nextCursor
945
- ) {
946
- hasNextPage = true;
947
- nextCursor = paginatedMarketCoinObjectsResponse.nextCursor;
948
- } else {
949
- hasNextPage = false;
950
- }
951
- } while (hasNextPage);
952
-
953
- const marketCoinAmounts: MarketCoinAmounts = {};
954
- const marketCoinObjects = marketCoinObjectsResponse
955
- .map((response) => {
956
- return response.data;
837
+ const marketCoins = {} as OptionalKeys<Record<SupportMarketCoins, number>>;
838
+
839
+ Promise.allSettled(
840
+ marketCoinNames.map(async (marketCoinName) => {
841
+ const marketCoin = await getMarketCoinAmount(
842
+ query,
843
+ marketCoinName,
844
+ owner
845
+ );
846
+ marketCoins[marketCoinName] = marketCoin;
957
847
  })
958
- .filter(
959
- (object: any) => object !== undefined && object !== null
960
- ) as SuiObjectData[];
961
- for (const marketCoinObject of marketCoinObjects) {
962
- const marketCoinType = marketCoinObject.type as string;
963
- if (marketCoinObject.content && 'fields' in marketCoinObject.content) {
964
- const fields = marketCoinObject.content.fields as any;
965
- const marketCoinName =
966
- query.utils.parseCoinNameFromType<SupportMarketCoins>(marketCoinType);
967
- if (marketCoinName) {
968
- marketCoinAmounts[marketCoinName] = BigNumber(
969
- marketCoinAmounts[marketCoinName] ?? 0
970
- )
971
- .plus(fields.balance)
972
- .toNumber();
973
- }
974
- }
975
- }
976
- return marketCoinAmounts;
848
+ );
849
+
850
+ return marketCoins;
977
851
  };
978
852
 
979
853
  /**
@@ -991,47 +865,9 @@ export const getMarketCoinAmount = async (
991
865
  ) => {
992
866
  const owner = ownerAddress || query.suiKit.currentAddress();
993
867
  const marketCoinType = query.utils.parseMarketCoinType(marketCoinName);
994
- const marketCoinObjectsResponse: SuiObjectResponse[] = [];
995
- let hasNextPage = false;
996
- let nextCursor: string | null | undefined = null;
997
- do {
998
- const paginatedMarketCoinObjectsResponse =
999
- await query.cache.queryGetOwnedObjects({
1000
- owner,
1001
- filter: { StructType: `0x2::coin::Coin<${marketCoinType}>` },
1002
- options: {
1003
- showContent: true,
1004
- },
1005
- cursor: nextCursor,
1006
- });
1007
-
1008
- marketCoinObjectsResponse.push(...paginatedMarketCoinObjectsResponse.data);
1009
- if (
1010
- paginatedMarketCoinObjectsResponse.hasNextPage &&
1011
- paginatedMarketCoinObjectsResponse.nextCursor
1012
- ) {
1013
- hasNextPage = true;
1014
- nextCursor = paginatedMarketCoinObjectsResponse.nextCursor;
1015
- } else {
1016
- hasNextPage = false;
1017
- }
1018
- } while (hasNextPage);
1019
-
1020
- let marketCoinAmount: number = 0;
1021
- const marketCoinObjects = marketCoinObjectsResponse
1022
- .map((response) => {
1023
- return response.data;
1024
- })
1025
- .filter(
1026
- (object: any) => object !== undefined && object !== null
1027
- ) as SuiObjectData[];
1028
- for (const marketCoinObject of marketCoinObjects) {
1029
- if (marketCoinObject.content && 'fields' in marketCoinObject.content) {
1030
- const fields = marketCoinObject.content.fields as any;
1031
- marketCoinAmount = BigNumber(marketCoinAmount)
1032
- .plus(fields.balance)
1033
- .toNumber();
1034
- }
1035
- }
1036
- return marketCoinAmount;
868
+ const amount = await query.cache.queryGetCoinBalance({
869
+ owner,
870
+ coinType: marketCoinType,
871
+ });
872
+ return BigNumber(amount).toNumber();
1037
873
  };
@@ -4,3 +4,4 @@ export * from './borrowIncentiveQuery';
4
4
  export * from './priceQuery';
5
5
  export * from './portfolioQuery';
6
6
  export * from './vescaQuery';
7
+ export * from './referralQuery';
@@ -1,3 +1,4 @@
1
+ import { SuiObjectData } from '@mysten/sui.js/src/client';
1
2
  import type { ScallopQuery } from '../models';
2
3
  import type { SupportAssetCoins } from '../types';
3
4
 
@@ -10,18 +11,19 @@ import type { SupportAssetCoins } from '../types';
10
11
  */
11
12
  export const getPythPrice = async (
12
13
  query: ScallopQuery,
13
- assetCoinName: SupportAssetCoins
14
+ assetCoinName: SupportAssetCoins,
15
+ priceFeedObject?: SuiObjectData | null
14
16
  ) => {
15
17
  const pythFeedObjectId = query.address.get(
16
18
  `core.coins.${assetCoinName}.oracle.pyth.feedObject`
17
19
  );
18
- const priceFeedObjectResponse = await query.cache.queryGetObject(
19
- pythFeedObjectId,
20
- { showContent: true }
21
- );
20
+ priceFeedObject =
21
+ priceFeedObject ||
22
+ (await query.cache.queryGetObject(pythFeedObjectId, { showContent: true }))
23
+ .data;
22
24
 
23
- if (priceFeedObjectResponse.data) {
24
- const priceFeedPoolObject = priceFeedObjectResponse.data;
25
+ if (priceFeedObject) {
26
+ const priceFeedPoolObject = priceFeedObject;
25
27
  if (
26
28
  priceFeedPoolObject.content &&
27
29
  'fields' in priceFeedPoolObject.content
@@ -54,3 +56,42 @@ export const getPythPrice = async (
54
56
 
55
57
  return 0;
56
58
  };
59
+
60
+ export const getPythPrices = async (
61
+ query: ScallopQuery,
62
+ assetCoinNames: SupportAssetCoins[]
63
+ ) => {
64
+ const seen: Record<string, boolean> = {};
65
+ const pythFeedObjectIds = assetCoinNames
66
+ .map((assetCoinName) => {
67
+ const pythFeedObjectId = query.address.get(
68
+ `core.coins.${assetCoinName}.oracle.pyth.feedObject`
69
+ );
70
+ if (seen[pythFeedObjectId]) return null;
71
+
72
+ seen[pythFeedObjectId] = true;
73
+ return pythFeedObjectId;
74
+ })
75
+ .filter((item) => !!item) as string[];
76
+ const priceFeedObjects = await query.cache.queryGetObjects(
77
+ pythFeedObjectIds,
78
+ {
79
+ showContent: true,
80
+ }
81
+ );
82
+
83
+ return (
84
+ await Promise.all(
85
+ priceFeedObjects.map(async (priceFeedObject, idx) => ({
86
+ coinName: assetCoinNames[idx],
87
+ price: await getPythPrice(query, assetCoinNames[idx], priceFeedObject),
88
+ }))
89
+ )
90
+ ).reduce(
91
+ (prev, curr) => {
92
+ prev[curr.coinName] = curr.price;
93
+ return prev;
94
+ },
95
+ {} as Record<SupportAssetCoins, number>
96
+ );
97
+ };
@@ -0,0 +1,27 @@
1
+ import { ScallopQuery } from 'src/models';
2
+
3
+ /**
4
+ * Query the veScaKeyId from the referral bindings table using the borrower address
5
+ * @param query
6
+ * @returns
7
+ */
8
+ export const queryVeScaKeyIdFromReferralBindings = async (
9
+ query: ScallopQuery,
10
+ refereeAddress: string
11
+ ): Promise<string | null> => {
12
+ const referralBindingTableId = query.address.get('referral.bindingTableId');
13
+
14
+ const referralBindResponse = await query.cache.queryGetDynamicFieldObject({
15
+ parentId: referralBindingTableId,
16
+ name: {
17
+ type: 'address',
18
+ value: refereeAddress,
19
+ },
20
+ });
21
+
22
+ if (referralBindResponse.data?.content?.dataType !== 'moveObject')
23
+ return null;
24
+
25
+ const fields = referralBindResponse.data.content.fields as any;
26
+ return fields.value;
27
+ };
@@ -133,25 +133,21 @@ export const getSpool = async (
133
133
  return spoolIndexer;
134
134
  }
135
135
 
136
- const spoolObjectResponse = await query.suiKit.client().multiGetObjects({
137
- ids: [poolId, rewardPoolId],
138
- options: {
136
+ const spoolObjectResponse = await query.cache.queryGetObjects(
137
+ [poolId, rewardPoolId],
138
+ {
139
139
  showContent: true,
140
- },
141
- });
140
+ }
141
+ );
142
142
 
143
- if (
144
- marketPool &&
145
- spoolObjectResponse[0].data &&
146
- spoolObjectResponse[1].data
147
- ) {
143
+ if (marketPool && spoolObjectResponse[0] && spoolObjectResponse[1]) {
148
144
  const rewardCoinName = query.utils.getSpoolRewardCoinName(marketCoinName);
149
145
  coinPrices =
150
146
  coinPrices ||
151
147
  (await query.utils.getCoinPrices([coinName, rewardCoinName]));
152
148
 
153
- const spoolObject = spoolObjectResponse[0].data;
154
- const rewardPoolObject = spoolObjectResponse[1].data;
149
+ const spoolObject = spoolObjectResponse[0];
150
+ const rewardPoolObject = spoolObjectResponse[1];
155
151
  if (spoolObject.content && 'fields' in spoolObject.content) {
156
152
  const spoolFields = spoolObject.content.fields as any;
157
153
  const parsedSpoolData = parseOriginSpoolData({
@@ -1,8 +1,14 @@
1
1
  import BigNumber from 'bignumber.js';
2
2
  import { Vesca } from '../types';
3
- import type { SuiObjectResponse, SuiObjectData } from '@mysten/sui.js/client';
3
+ import {
4
+ type SuiObjectResponse,
5
+ type SuiObjectData,
6
+ DevInspectResults,
7
+ } from '@mysten/sui.js/client';
4
8
  import type { ScallopQuery } from '../models';
5
- import { IS_VE_SCA_TEST, MAX_LOCK_DURATION } from 'src/constants';
9
+ import { MAX_LOCK_DURATION } from 'src/constants';
10
+ import { SUI_CLOCK_OBJECT_ID, SuiTxBlock } from '@scallop-io/sui-kit';
11
+ import { bcs } from '@mysten/sui.js/bcs';
6
12
  /**
7
13
  * Query all owned veSca key.
8
14
  *
@@ -15,10 +21,8 @@ export const getVescaKeys = async (
15
21
  ownerAddress?: string
16
22
  ) => {
17
23
  const owner = ownerAddress || query.suiKit.currentAddress();
18
- const veScaPkgId = IS_VE_SCA_TEST
19
- ? '0xb220d034bdf335d77ae5bfbf6daf059c2cc7a1f719b12bfed75d1736fac038c8'
20
- : query.address.get('vesca.id');
21
- const veScaKeyType = `${veScaPkgId}::ve_sca::VeScaKey`;
24
+ const veScaObjId = query.address.get('vesca.object');
25
+ const veScaKeyType = `${veScaObjId}::ve_sca::VeScaKey`;
22
26
  const keyObjectsResponse: SuiObjectResponse[] = [];
23
27
  let hasNextPage = false;
24
28
  let nextCursor: string | null | undefined = null;
@@ -61,13 +65,18 @@ export const getVeScas = async (query: ScallopQuery, ownerAddress?: string) => {
61
65
  const keyObjectDatas = await getVescaKeys(query, ownerAddress);
62
66
  const keyObjectId: string[] = keyObjectDatas.map((data) => data.objectId);
63
67
 
64
- const veScas: Vesca[] = [];
65
- for (const keyId of keyObjectId) {
68
+ const veScas: (Vesca | undefined)[] = Array(keyObjectId.length).fill(null);
69
+ const tasks = keyObjectId.map(async (keyId, idx) => {
66
70
  const veSca = await getVeSca(query, keyId);
67
- if (veSca) veScas.push(veSca);
68
- }
71
+ if (veSca) {
72
+ veScas[idx] = veSca;
73
+ }
74
+ });
75
+ await Promise.allSettled(tasks);
69
76
 
70
- return veScas;
77
+ return veScas
78
+ .filter(Boolean)
79
+ .sort((a, b) => a!.currentVeScaBalance - b!.currentVeScaBalance);
71
80
  };
72
81
 
73
82
  /**
@@ -83,9 +92,7 @@ export const getVeSca = async (
83
92
  veScaKeyId?: string,
84
93
  ownerAddress?: string
85
94
  ) => {
86
- const tableId = IS_VE_SCA_TEST
87
- ? '0xc607241e4a679fe376d1170b2fbe07b64917bfe69100d4825241cda20039d4bd'
88
- : query.address.get(`vesca.tableId`);
95
+ const tableId = query.address.get(`vesca.tableId`);
89
96
  veScaKeyId =
90
97
  veScaKeyId || (await getVescaKeys(query, ownerAddress))[0].objectId;
91
98
 
@@ -128,9 +135,81 @@ export const getVeSca = async (
128
135
  lockedScaAmount,
129
136
  lockedScaCoin,
130
137
  currentVeScaBalance,
131
- unlockAt: BigNumber(dynamicFields.unlock_at).toNumber(),
138
+ unlockAt: BigNumber(dynamicFields.unlock_at * 1000).toNumber(),
132
139
  } as Vesca;
133
140
  }
134
141
 
135
142
  return vesca;
136
143
  };
144
+
145
+ /**
146
+ * Get current total veSca treasury amount.
147
+ */
148
+ export const getTotalVeScaTreasuryAmount = async (
149
+ query: ScallopQuery
150
+ ): Promise<string> => {
151
+ const veScaPkgId = query.address.get('vesca.id');
152
+ const veScaConfig = query.address.get('vesca.config');
153
+ const veScaTreasury = query.address.get('vesca.treasury');
154
+
155
+ // refresh query
156
+ const refreshQueryTarget = `${veScaPkgId}::treasury::refresh`;
157
+ const refreshArgs = [veScaConfig, veScaTreasury, SUI_CLOCK_OBJECT_ID];
158
+
159
+ // query total veSca amount
160
+ const veScaAmountQueryTarget = `${veScaPkgId}::treasury::total_ve_sca_amount`;
161
+ const veScaAmountArgs = [veScaTreasury, SUI_CLOCK_OBJECT_ID];
162
+
163
+ // resolve each args
164
+ const resolvedRefreshArgs = await Promise.all(
165
+ refreshArgs.map(async (arg) => {
166
+ if (typeof arg === 'string') {
167
+ return (await query.cache.queryGetObject(arg, { showContent: true }))
168
+ .data;
169
+ }
170
+ return arg;
171
+ })
172
+ );
173
+
174
+ const resolvedVeScaAmountArgs = await Promise.all(
175
+ veScaAmountArgs.map(async (arg) => {
176
+ if (typeof arg === 'string') {
177
+ return (await query.cache.queryGetObject(arg, { showContent: true }))
178
+ .data;
179
+ }
180
+ return arg;
181
+ })
182
+ );
183
+
184
+ const txb = new SuiTxBlock();
185
+ // refresh first
186
+ txb.moveCall(refreshQueryTarget, resolvedRefreshArgs);
187
+ txb.moveCall(veScaAmountQueryTarget, resolvedVeScaAmountArgs);
188
+
189
+ const txBytes = await txb.txBlock.build({
190
+ client: query.suiKit.client(),
191
+ onlyTransactionKind: true,
192
+ protocolConfig: await query.cache.getProtocolConfig(),
193
+ });
194
+
195
+ // return result
196
+ const res = await query.cache.queryClient.fetchQuery<DevInspectResults>({
197
+ queryKey: [
198
+ 'getTotalVeScaTreasuryAmount',
199
+ JSON.stringify([...refreshArgs, ...veScaAmountArgs]),
200
+ ],
201
+ queryFn: async () => {
202
+ return await query.suiKit.inspectTxn(txBytes);
203
+ },
204
+ staleTime: 8000,
205
+ });
206
+
207
+ const results = res.results;
208
+ if (results && results[1].returnValues) {
209
+ const value = Uint8Array.from(results[1].returnValues[0][0]);
210
+ const type = results[1].returnValues[0][1];
211
+ return bcs.de(type, value);
212
+ }
213
+
214
+ return '0';
215
+ };
@@ -73,6 +73,7 @@ export interface AddressesInterface {
73
73
  id: string;
74
74
  adminCap: string;
75
75
  object: string;
76
+ config: string;
76
77
  pools: Partial<
77
78
  Record<
78
79
  SupportStakeMarketCoins,
@@ -94,12 +95,26 @@ export interface AddressesInterface {
94
95
  };
95
96
  vesca: {
96
97
  id: string;
98
+ object: string;
97
99
  adminCap: string;
98
100
  tableId: string;
99
101
  table: string;
100
102
  treasury: string;
101
103
  config: string;
102
104
  };
105
+ referral: {
106
+ id: string;
107
+ version: string;
108
+ object: string;
109
+ adminCap: string;
110
+ referralBindings: string;
111
+ bindingTableId: string;
112
+ referralRevenuePool: string;
113
+ revenueTableId: string;
114
+ referralTiers: string;
115
+ tiersTableId: string;
116
+ authorizedWitnessList: string;
117
+ };
103
118
  }
104
119
 
105
120
  type AddressPathsProps<T> = T extends string
@@ -57,6 +57,13 @@ export type CoreNormalMethods = {
57
57
  amount: SuiTxArg,
58
58
  poolCoinName: SupportPoolCoins
59
59
  ) => TransactionResult;
60
+ borrowWithReferral: (
61
+ obligation: SuiAddressArg,
62
+ obligationKey: SuiAddressArg,
63
+ borrowReferral: SuiObjectArg,
64
+ amount: SuiTxArg,
65
+ poolCoinName: SupportPoolCoins
66
+ ) => TransactionResult;
60
67
  borrowEntry: (
61
68
  obligation: SuiAddressArg,
62
69
  obligationKey: SuiAddressArg,
@@ -97,6 +104,13 @@ export type CoreQuickMethods = {
97
104
  obligationId?: SuiAddressArg,
98
105
  obligationKey?: SuiAddressArg
99
106
  ) => Promise<TransactionResult>;
107
+ borrowWithReferralQuick: (
108
+ amount: number,
109
+ poolCoinName: SupportPoolCoins,
110
+ borrowReferral: SuiObjectArg,
111
+ obligationId?: SuiAddressArg,
112
+ obligationKey?: SuiAddressArg
113
+ ) => Promise<TransactionResult>;
100
114
  depositQuick: (
101
115
  amount: number,
102
116
  poolCoinName: SupportPoolCoins
@@ -2,6 +2,7 @@ import type { CoreTxBlock } from './core';
2
2
  import type { SpoolTxBlock } from './spool';
3
3
  import type { BorrowIncentiveTxBlock } from './borrowIncentive';
4
4
  import type { VeScaTxBlock } from './vesca';
5
+ import type { ReferralTxBlock } from './referral';
5
6
 
6
7
  export type * from './core';
7
8
  export type * from './spool';
@@ -10,5 +11,6 @@ export type * from './vesca';
10
11
 
11
12
  export type ScallopTxBlock = CoreTxBlock &
12
13
  SpoolTxBlock &
14
+ ReferralTxBlock &
13
15
  BorrowIncentiveTxBlock &
14
16
  VeScaTxBlock;
@@ -0,0 +1,51 @@
1
+ import {
2
+ SuiObjectArg,
3
+ TransactionResult,
4
+ SuiTxBlock as SuiKitTxBlock,
5
+ } from '@scallop-io/sui-kit';
6
+ import { ScallopBuilder } from 'src/models';
7
+ import { SupportPoolCoins } from '../constant';
8
+
9
+ export type ReferralIds = {
10
+ referralPgkId: string;
11
+ referralBindings: string;
12
+ referralRevenuePool: string;
13
+ referralTiers: string;
14
+ authorizedWitnessList: string;
15
+ version: string;
16
+ };
17
+
18
+ export type ReferralNormalMethods = {
19
+ bindToReferral: (veScaKeyId: string) => void;
20
+ claimReferralTicket: (poolCoinName: SupportPoolCoins) => TransactionResult;
21
+ burnReferralTicket: (
22
+ ticket: SuiObjectArg,
23
+ poolCoinName: SupportPoolCoins
24
+ ) => void;
25
+ claimReferralRevenue: (
26
+ veScaKey: SuiObjectArg,
27
+ poolCoinName: SupportPoolCoins
28
+ ) => TransactionResult;
29
+ };
30
+
31
+ export type ReferralQuickMethods = {
32
+ claimReferralRevenueQuick: (
33
+ veScaKey: SuiObjectArg,
34
+ coinNames: SupportPoolCoins[]
35
+ ) => Promise<void>;
36
+ };
37
+
38
+ export type SuiTxBlockWithReferralNormalMethods = SuiKitTxBlock &
39
+ ReferralNormalMethods;
40
+ export type ReferralTxBlock = SuiTxBlockWithReferralNormalMethods &
41
+ ReferralQuickMethods;
42
+
43
+ export type GenerateReferralNormalMethod = (params: {
44
+ builder: ScallopBuilder;
45
+ txBlock: SuiKitTxBlock;
46
+ }) => ReferralNormalMethods;
47
+
48
+ export type GenerateReferralQuickMethod = (params: {
49
+ builder: ScallopBuilder;
50
+ txBlock: SuiTxBlockWithReferralNormalMethods;
51
+ }) => ReferralQuickMethods;