@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.
- package/dist/builders/borrowIncentiveBuilder.d.ts +1 -1
- package/dist/builders/referralBuilder.d.ts +12 -0
- package/dist/constants/common.d.ts +1 -1
- package/dist/index.js +533 -279
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +587 -329
- package/dist/index.mjs.map +1 -1
- package/dist/models/scallopCache.d.ts +6 -2
- package/dist/models/scallopQuery.d.ts +26 -28
- package/dist/queries/coreQuery.d.ts +3 -29
- package/dist/queries/index.d.ts +1 -0
- package/dist/queries/priceQuery.d.ts +3 -1
- package/dist/queries/referralQuery.d.ts +7 -0
- package/dist/queries/vescaQuery.d.ts +6 -2
- package/dist/types/address.d.ts +15 -0
- package/dist/types/builder/core.d.ts +2 -0
- package/dist/types/builder/index.d.ts +2 -1
- package/dist/types/builder/referral.d.ts +30 -0
- package/dist/types/builder/vesca.d.ts +1 -0
- package/package.json +7 -6
- package/src/builders/borrowIncentiveBuilder.ts +10 -19
- package/src/builders/coreBuilder.ts +54 -0
- package/src/builders/index.ts +5 -2
- package/src/builders/referralBuilder.ts +178 -0
- package/src/builders/vescaBuilder.ts +8 -6
- package/src/constants/common.ts +9 -2
- package/src/constants/vesca.ts +1 -3
- package/src/models/scallopAddress.ts +63 -19
- package/src/models/scallopCache.ts +42 -2
- package/src/models/scallopQuery.ts +40 -0
- package/src/models/scallopUtils.ts +35 -35
- package/src/queries/borrowIncentiveQuery.ts +2 -5
- package/src/queries/coreQuery.ts +33 -197
- package/src/queries/index.ts +1 -0
- package/src/queries/priceQuery.ts +48 -7
- package/src/queries/referralQuery.ts +27 -0
- package/src/queries/spoolQuery.ts +8 -12
- package/src/queries/vescaQuery.ts +94 -15
- package/src/types/address.ts +15 -0
- package/src/types/builder/core.ts +14 -0
- package/src/types/builder/index.ts +2 -0
- package/src/types/builder/referral.ts +51 -0
- package/src/types/builder/vesca.ts +1 -0
package/src/queries/coreQuery.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
786
|
+
await Promise.allSettled(
|
|
787
|
+
assetCoinNames.map(async (assetCoinName) => {
|
|
788
|
+
const marketCoin = await getCoinAmount(query, assetCoinName, owner);
|
|
789
|
+
assetCoins[assetCoinName] = marketCoin;
|
|
822
790
|
})
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
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
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
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
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
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
|
-
|
|
959
|
-
|
|
960
|
-
|
|
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
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
};
|
package/src/queries/index.ts
CHANGED
|
@@ -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
|
-
|
|
19
|
-
|
|
20
|
-
{ showContent: true }
|
|
21
|
-
|
|
20
|
+
priceFeedObject =
|
|
21
|
+
priceFeedObject ||
|
|
22
|
+
(await query.cache.queryGetObject(pythFeedObjectId, { showContent: true }))
|
|
23
|
+
.data;
|
|
22
24
|
|
|
23
|
-
if (
|
|
24
|
-
const priceFeedPoolObject =
|
|
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.
|
|
137
|
-
|
|
138
|
-
|
|
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]
|
|
154
|
-
const rewardPoolObject = spoolObjectResponse[1]
|
|
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
|
|
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 {
|
|
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
|
|
19
|
-
|
|
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
|
-
|
|
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)
|
|
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 =
|
|
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
|
+
};
|
package/src/types/address.ts
CHANGED
|
@@ -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;
|