zo-sdk 0.1.2 → 0.1.3
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/abstract/BaseAPI.cjs +3 -4
- package/dist/abstract/BaseAPI.cjs.map +1 -1
- package/dist/abstract/BaseAPI.d.cts +13 -13
- package/dist/abstract/BaseAPI.d.cts.map +1 -1
- package/dist/abstract/BaseAPI.d.mts +13 -13
- package/dist/abstract/BaseAPI.d.mts.map +1 -1
- package/dist/abstract/BaseAPI.mjs +3 -4
- package/dist/abstract/BaseAPI.mjs.map +1 -1
- package/dist/abstract/BaseDataAPI.cjs +2 -2
- package/dist/abstract/BaseDataAPI.cjs.map +1 -1
- package/dist/abstract/BaseDataAPI.d.cts +2 -2
- package/dist/abstract/BaseDataAPI.d.cts.map +1 -1
- package/dist/abstract/BaseDataAPI.d.mts +2 -2
- package/dist/abstract/BaseDataAPI.d.mts.map +1 -1
- package/dist/abstract/BaseDataAPI.mjs +2 -2
- package/dist/abstract/BaseDataAPI.mjs.map +1 -1
- package/dist/abstract/index.cjs +3 -3
- package/dist/abstract/index.cjs.map +1 -1
- package/dist/abstract/index.d.cts +1 -1
- package/dist/abstract/index.d.cts.map +1 -1
- package/dist/abstract/index.d.mts +1 -1
- package/dist/abstract/index.d.mts.map +1 -1
- package/dist/abstract/index.mjs +1 -1
- package/dist/abstract/index.mjs.map +1 -1
- package/dist/api.cjs +2 -1
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts.map +1 -1
- package/dist/api.d.mts.map +1 -1
- package/dist/api.mjs +2 -1
- package/dist/api.mjs.map +1 -1
- package/dist/bcs.cjs.map +1 -1
- package/dist/bcs.d.cts.map +1 -1
- package/dist/bcs.d.mts.map +1 -1
- package/dist/bcs.mjs.map +1 -1
- package/dist/consts/deployments-slp-mainnet.json +0 -70
- package/dist/consts/deployments-usdz-mainnet.json +1 -133
- package/dist/consts/index.cjs +21 -14
- package/dist/consts/index.cjs.map +1 -1
- package/dist/consts/index.d.cts.map +1 -1
- package/dist/consts/index.d.mts.map +1 -1
- package/dist/consts/index.mjs +21 -14
- package/dist/consts/index.mjs.map +1 -1
- package/dist/factory/SDKFactory.cjs +21 -14
- package/dist/factory/SDKFactory.cjs.map +1 -1
- package/dist/factory/SDKFactory.d.cts +4 -4
- package/dist/factory/SDKFactory.d.cts.map +1 -1
- package/dist/factory/SDKFactory.d.mts +4 -4
- package/dist/factory/SDKFactory.d.mts.map +1 -1
- package/dist/factory/SDKFactory.mjs +22 -15
- package/dist/factory/SDKFactory.mjs.map +1 -1
- package/dist/implementations/SLPAPI.cjs +143 -110
- package/dist/implementations/SLPAPI.cjs.map +1 -1
- package/dist/implementations/SLPAPI.d.cts +49 -47
- package/dist/implementations/SLPAPI.d.cts.map +1 -1
- package/dist/implementations/SLPAPI.d.mts +49 -47
- package/dist/implementations/SLPAPI.d.mts.map +1 -1
- package/dist/implementations/SLPAPI.mjs +143 -110
- package/dist/implementations/SLPAPI.mjs.map +1 -1
- package/dist/implementations/SLPDataAPI.cjs +98 -89
- package/dist/implementations/SLPDataAPI.cjs.map +1 -1
- package/dist/implementations/SLPDataAPI.d.cts +21 -21
- package/dist/implementations/SLPDataAPI.d.cts.map +1 -1
- package/dist/implementations/SLPDataAPI.d.mts +21 -21
- package/dist/implementations/SLPDataAPI.d.mts.map +1 -1
- package/dist/implementations/SLPDataAPI.mjs +98 -89
- package/dist/implementations/SLPDataAPI.mjs.map +1 -1
- package/dist/implementations/USDZAPI.cjs +128 -84
- package/dist/implementations/USDZAPI.cjs.map +1 -1
- package/dist/implementations/USDZAPI.d.cts +46 -45
- package/dist/implementations/USDZAPI.d.cts.map +1 -1
- package/dist/implementations/USDZAPI.d.mts +46 -45
- package/dist/implementations/USDZAPI.d.mts.map +1 -1
- package/dist/implementations/USDZAPI.mjs +128 -84
- package/dist/implementations/USDZAPI.mjs.map +1 -1
- package/dist/implementations/USDZDataAPI.cjs +48 -47
- package/dist/implementations/USDZDataAPI.cjs.map +1 -1
- package/dist/implementations/USDZDataAPI.d.cts +19 -19
- package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
- package/dist/implementations/USDZDataAPI.d.mts +19 -19
- package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
- package/dist/implementations/USDZDataAPI.mjs +49 -48
- package/dist/implementations/USDZDataAPI.mjs.map +1 -1
- package/dist/implementations/ZLPAPI.cjs +137 -89
- package/dist/implementations/ZLPAPI.cjs.map +1 -1
- package/dist/implementations/ZLPAPI.d.cts +50 -48
- package/dist/implementations/ZLPAPI.d.cts.map +1 -1
- package/dist/implementations/ZLPAPI.d.mts +50 -48
- package/dist/implementations/ZLPAPI.d.mts.map +1 -1
- package/dist/implementations/ZLPAPI.mjs +137 -89
- package/dist/implementations/ZLPAPI.mjs.map +1 -1
- package/dist/implementations/ZLPDataAPI.cjs +62 -63
- package/dist/implementations/ZLPDataAPI.cjs.map +1 -1
- package/dist/implementations/ZLPDataAPI.d.cts +19 -19
- package/dist/implementations/ZLPDataAPI.d.cts.map +1 -1
- package/dist/implementations/ZLPDataAPI.d.mts +19 -19
- package/dist/implementations/ZLPDataAPI.d.mts.map +1 -1
- package/dist/implementations/ZLPDataAPI.mjs +63 -64
- package/dist/implementations/ZLPDataAPI.mjs.map +1 -1
- package/dist/implementations/index.cjs +5 -5
- package/dist/implementations/index.cjs.map +1 -1
- package/dist/implementations/index.d.cts +2 -2
- package/dist/implementations/index.d.cts.map +1 -1
- package/dist/implementations/index.d.mts +2 -2
- package/dist/implementations/index.d.mts.map +1 -1
- package/dist/implementations/index.mjs +2 -2
- package/dist/implementations/index.mjs.map +1 -1
- package/dist/index.cjs +9 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +6 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/dist/interfaces/base.cjs +0 -1
- package/dist/interfaces/base.cjs.map +1 -1
- package/dist/interfaces/base.d.cts +57 -57
- package/dist/interfaces/base.d.cts.map +1 -1
- package/dist/interfaces/base.d.mts +57 -57
- package/dist/interfaces/base.d.mts.map +1 -1
- package/dist/interfaces/base.mjs +1 -1
- package/dist/interfaces/base.mjs.map +1 -1
- package/dist/interfaces/index.d.cts +4 -4
- package/dist/interfaces/index.d.cts.map +1 -1
- package/dist/interfaces/index.d.mts +4 -4
- package/dist/interfaces/index.d.mts.map +1 -1
- package/dist/interfaces/slp.cjs +0 -2
- package/dist/interfaces/slp.cjs.map +1 -1
- package/dist/interfaces/slp.d.cts +5 -5
- package/dist/interfaces/slp.d.cts.map +1 -1
- package/dist/interfaces/slp.d.mts +5 -5
- package/dist/interfaces/slp.d.mts.map +1 -1
- package/dist/interfaces/slp.mjs +1 -2
- package/dist/interfaces/slp.mjs.map +1 -1
- package/dist/interfaces/usdz.d.cts +1 -1
- package/dist/interfaces/usdz.d.cts.map +1 -1
- package/dist/interfaces/usdz.d.mts +1 -1
- package/dist/interfaces/usdz.d.mts.map +1 -1
- package/dist/interfaces/zlp.d.cts +5 -5
- package/dist/interfaces/zlp.d.cts.map +1 -1
- package/dist/interfaces/zlp.d.mts +5 -5
- package/dist/interfaces/zlp.d.mts.map +1 -1
- package/dist/oracle.cjs +12 -2
- package/dist/oracle.cjs.map +1 -1
- package/dist/oracle.d.cts +4 -3
- package/dist/oracle.d.cts.map +1 -1
- package/dist/oracle.d.mts +4 -3
- package/dist/oracle.d.mts.map +1 -1
- package/dist/oracle.mjs +13 -3
- package/dist/oracle.mjs.map +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +1 -1
- package/dist/utils.mjs.map +1 -1
- package/eslint.config.mjs +18 -0
- package/package.json +16 -15
- package/src/abstract/BaseAPI.ts +55 -49
- package/src/abstract/BaseDataAPI.ts +19 -17
- package/src/abstract/index.ts +1 -1
- package/src/api.ts +3 -1
- package/src/bcs.ts +9 -9
- package/src/consts/deployments-slp-mainnet.json +0 -70
- package/src/consts/deployments-usdz-mainnet.json +1 -133
- package/src/consts/index.ts +22 -15
- package/src/factory/SDKFactory.ts +49 -41
- package/src/implementations/SLPAPI.ts +299 -210
- package/src/implementations/SLPDataAPI.ts +163 -146
- package/src/implementations/USDZAPI.ts +238 -133
- package/src/implementations/USDZDataAPI.ts +79 -74
- package/src/implementations/ZLPAPI.ts +296 -174
- package/src/implementations/ZLPDataAPI.ts +93 -88
- package/src/implementations/index.ts +3 -3
- package/src/index.ts +17 -17
- package/src/interfaces/base.ts +123 -116
- package/src/interfaces/index.ts +14 -17
- package/src/interfaces/slp.ts +20 -19
- package/src/interfaces/usdz.ts +13 -13
- package/src/interfaces/zlp.ts +22 -21
- package/src/oracle.ts +25 -5
- package/src/utils.ts +9 -9
- package/tsconfig.json +1 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
/* eslint-disable @stylistic/indent-binary-ops */
|
|
3
|
+
/* eslint-disable @stylistic/indent */
|
|
1
4
|
/**
|
|
2
5
|
* SLP DataAPI implementation
|
|
3
6
|
* Implements SLP-specific data access methods for Sudo SDK
|
|
4
7
|
*/
|
|
5
8
|
import { Transaction } from "@mysten/sui/transactions";
|
|
6
9
|
import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils";
|
|
7
|
-
import { LPToken, SLP_TOKEN_DECIMALS } from "../consts/index.mjs";
|
|
8
10
|
import { BaseDataAPI } from "../abstract/index.mjs";
|
|
9
|
-
import { decimalToObject, joinSymbol, parseSymbolKey, parseValue, suiSymbolToSymbol } from "../utils.mjs";
|
|
10
11
|
import { Rate, SRate, SymbolsValuation, VaultsValuation } from "../bcs.mjs";
|
|
12
|
+
import { LPToken, SLP_TOKEN_DECIMALS } from "../consts/index.mjs";
|
|
13
|
+
import { decimalToObject, joinSymbol, parseSymbolKey, parseValue, suiSymbolToSymbol } from "../utils.mjs";
|
|
11
14
|
let aprResponse = {};
|
|
12
15
|
const SECONDS_PER_EIGHT_HOUR = 8 * 60 * 60; // 28800 seconds
|
|
13
16
|
export class SLPDataAPI extends BaseDataAPI {
|
|
@@ -25,7 +28,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
25
28
|
showContent: true,
|
|
26
29
|
},
|
|
27
30
|
});
|
|
28
|
-
return
|
|
31
|
+
return SLPDataAPI.parseRebaseFeeModel(rawData);
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
31
34
|
* Creates vaults valuation for SLP using Sudo SDK approach
|
|
@@ -133,9 +136,9 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
133
136
|
const vaultsValuation = VaultsValuation.parse(new Uint8Array(res.results[(res.results?.length || 0) - symbolsValuationOffset - 1].mutableReferenceOutputs[1][1]));
|
|
134
137
|
const symbolsValuation = SymbolsValuation.parse(new Uint8Array(res.results[(res.results?.length || 0) - 1]
|
|
135
138
|
.mutableReferenceOutputs[1][1]));
|
|
136
|
-
const result = Number(BigInt(vaultsValuation.value)
|
|
137
|
-
BigInt(symbolsValuation.value.value)
|
|
138
|
-
BigInt(symbolsValuation.value.is_positive ? 1 : -1)) / 1e18;
|
|
139
|
+
const result = Number(BigInt(vaultsValuation.value)
|
|
140
|
+
+ BigInt(symbolsValuation.value.value)
|
|
141
|
+
* BigInt(symbolsValuation.value.is_positive ? 1 : -1)) / 1e18;
|
|
139
142
|
return result;
|
|
140
143
|
}
|
|
141
144
|
/**
|
|
@@ -161,8 +164,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
161
164
|
throw new Error('Sudo Core configuration not found');
|
|
162
165
|
}
|
|
163
166
|
const marketInfo = await this.getMarketInfo();
|
|
164
|
-
|
|
165
|
-
|
|
167
|
+
const value = await this.simValuateVaults(this.consts.sudoCore.adminCap);
|
|
168
|
+
const slpPrice = value / marketInfo.lpSupplyWithDecimals;
|
|
166
169
|
return {
|
|
167
170
|
marketCap: value,
|
|
168
171
|
price: slpPrice,
|
|
@@ -186,7 +189,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
186
189
|
});
|
|
187
190
|
const apr = await this.getCumulativeApr();
|
|
188
191
|
return {
|
|
189
|
-
...
|
|
192
|
+
...SLPDataAPI.parseMarketInfo(rawData),
|
|
190
193
|
apr,
|
|
191
194
|
};
|
|
192
195
|
}
|
|
@@ -280,7 +283,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
280
283
|
async getStaked(owner) {
|
|
281
284
|
let rawCredentialsData = [];
|
|
282
285
|
let queryNextPage = true;
|
|
283
|
-
let queryCursor
|
|
286
|
+
let queryCursor;
|
|
284
287
|
const limit = 50;
|
|
285
288
|
while (queryNextPage) {
|
|
286
289
|
const { data, hasNextPage, nextCursor } = await this.provider.getOwnedObjects({
|
|
@@ -305,7 +308,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
305
308
|
rawCredentialsData = [...rawCredentialsData, ...data];
|
|
306
309
|
}
|
|
307
310
|
const pool = await this.getStakePool();
|
|
308
|
-
const credentials = rawCredentialsData.map((item) =>
|
|
311
|
+
const credentials = rawCredentialsData.map((item) => SLPDataAPI.parseCredential(item, pool));
|
|
309
312
|
return {
|
|
310
313
|
credentials,
|
|
311
314
|
amount: credentials.reduce((acc, cur) => acc + cur.amount, BigInt(0)),
|
|
@@ -319,12 +322,15 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
319
322
|
showContent: true,
|
|
320
323
|
},
|
|
321
324
|
});
|
|
322
|
-
return
|
|
325
|
+
return SLPDataAPI.parseStakePool(raw);
|
|
323
326
|
}
|
|
324
327
|
async fundingFeeRate(indexToken, long, sender) {
|
|
328
|
+
if (!sender) {
|
|
329
|
+
throw new Error('Sender address is required for fundingFeeRate calculation');
|
|
330
|
+
}
|
|
325
331
|
const tx = await this.initOracleTxb([indexToken]);
|
|
326
332
|
const symbol_ = joinSymbol(long ? 'long' : 'short', indexToken);
|
|
327
|
-
const currentTimestamp = parseInt((
|
|
333
|
+
const currentTimestamp = Number.parseInt((Date.now() / 1000).toFixed(0), 10);
|
|
328
334
|
const symbol = tx.moveCall({
|
|
329
335
|
target: `${this.consts.sudoCore.package}::market::symbol`,
|
|
330
336
|
typeArguments: [
|
|
@@ -375,10 +381,13 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
375
381
|
transactionBlock: tx,
|
|
376
382
|
sender,
|
|
377
383
|
});
|
|
378
|
-
const de = SRate.parse(new Uint8Array(res.results
|
|
384
|
+
const de = SRate.parse(new Uint8Array(res.results.at(-1).returnValues[0][0]));
|
|
379
385
|
return (Number(BigInt(de.value)) / 1e18) * (de.is_positive ? 1 : -1);
|
|
380
386
|
}
|
|
381
387
|
async rebaseFeeRate(collateralToken, increase, amount, sender) {
|
|
388
|
+
if (!sender) {
|
|
389
|
+
throw new Error('Sender address is required for rebaseFeeRate calculation');
|
|
390
|
+
}
|
|
382
391
|
const tx1 = await this.initOracleTxb(Object.keys(this.consts.pythFeeder.feeder));
|
|
383
392
|
this.valuateVaults(tx1);
|
|
384
393
|
const res1 = await this.provider.devInspectTransactionBlock({
|
|
@@ -388,7 +397,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
388
397
|
const vaultsValuation = VaultsValuation.parse(new Uint8Array(res1.results[(res1.results?.length || 0) - 1]
|
|
389
398
|
.mutableReferenceOutputs[1][1]));
|
|
390
399
|
const singleVaultValue = BigInt(
|
|
391
|
-
// @ts-
|
|
400
|
+
// @ts-expect-error: vaultsValuation.handled type is not properly defined in BCS schema
|
|
392
401
|
vaultsValuation.handled.find((item) => (item.key || '').includes(this.consts.coins[collateralToken].module.slice(2)) || false)?.value.value) + BigInt(Math.floor(amount));
|
|
393
402
|
const allVaultValue = BigInt(vaultsValuation.value) + BigInt(Math.floor(amount));
|
|
394
403
|
const singleVaultWeight = BigInt(this.consts.sudoCore.vaults[collateralToken].weight);
|
|
@@ -409,17 +418,20 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
409
418
|
transactionBlock: tx2,
|
|
410
419
|
sender,
|
|
411
420
|
});
|
|
412
|
-
const de = Rate.parse(new Uint8Array(res2.results
|
|
421
|
+
const de = Rate.parse(new Uint8Array(res2.results.at(-1).returnValues[0][0]));
|
|
413
422
|
return Number(BigInt(de)) / 1e18;
|
|
414
423
|
}
|
|
415
424
|
async reservingFeeRate(collateralToken, amount, sender) {
|
|
425
|
+
if (!sender) {
|
|
426
|
+
throw new Error('Sender address is required for reservingFeeRate calculation');
|
|
427
|
+
}
|
|
416
428
|
const vaultInfo = await this.getVaultInfo(collateralToken);
|
|
417
|
-
const vaultSupply = vaultInfo.liquidity
|
|
418
|
-
vaultInfo.reservedAmount
|
|
419
|
-
vaultInfo.unrealisedReservingFeeAmount
|
|
420
|
-
amount;
|
|
429
|
+
const vaultSupply = vaultInfo.liquidity
|
|
430
|
+
+ vaultInfo.reservedAmount
|
|
431
|
+
+ vaultInfo.unrealisedReservingFeeAmount
|
|
432
|
+
+ amount;
|
|
421
433
|
const utilization = vaultSupply
|
|
422
|
-
? parseInt((((vaultInfo.reservedAmount + amount) / vaultSupply) * 1e18).toFixed(0))
|
|
434
|
+
? Number.parseInt((((vaultInfo.reservedAmount + amount) / vaultSupply) * 1e18).toFixed(0), 10)
|
|
423
435
|
: 0;
|
|
424
436
|
const tx = new Transaction();
|
|
425
437
|
tx.moveCall({
|
|
@@ -434,7 +446,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
434
446
|
transactionBlock: tx,
|
|
435
447
|
sender,
|
|
436
448
|
});
|
|
437
|
-
const de = Rate.parse(new Uint8Array(res.results
|
|
449
|
+
const de = Rate.parse(new Uint8Array(res.results.at(-1).returnValues[0][0]));
|
|
438
450
|
return Number(BigInt(de)) / 1e18;
|
|
439
451
|
}
|
|
440
452
|
async getPositionConfig(indexToken, long) {
|
|
@@ -449,12 +461,12 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
449
461
|
showContent: true,
|
|
450
462
|
},
|
|
451
463
|
});
|
|
452
|
-
return
|
|
464
|
+
return SLPDataAPI.parsePositionConfig(rawData);
|
|
453
465
|
}
|
|
454
466
|
async getOpenPositions(batchSize = 50, symbol = 'sui') {
|
|
455
467
|
let positionDynamicFields = [];
|
|
456
468
|
let _continue = true;
|
|
457
|
-
let cursor
|
|
469
|
+
let cursor;
|
|
458
470
|
while (_continue) {
|
|
459
471
|
// data here will be a list of dynamic fields containing name and value
|
|
460
472
|
const { data, nextCursor, hasNextPage } = await this.provider.getDynamicFields({
|
|
@@ -466,23 +478,21 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
466
478
|
cursor = nextCursor;
|
|
467
479
|
}
|
|
468
480
|
// Filter by symbol if provided
|
|
469
|
-
if (symbol && this.consts.coins[symbol]) {
|
|
470
|
-
const coinModule = symbol === 'sui' ? '0x2::sui::SUI' : this.consts.coins[symbol].module;
|
|
471
|
-
positionDynamicFields = positionDynamicFields.filter(field => {
|
|
472
|
-
// Extract the second coin module from PositionName<coin1, coin2, direction>
|
|
473
|
-
const typeStr = field.name?.type;
|
|
474
|
-
if (!typeStr)
|
|
475
|
-
return false;
|
|
476
|
-
const match = typeStr.match(/PositionName<([^,]+),\s*([^,]+),\s*([^>]+)>/);
|
|
477
|
-
if (!match)
|
|
478
|
-
return false;
|
|
479
|
-
const secondCoin = match[2].trim();
|
|
480
|
-
return secondCoin === coinModule;
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
481
|
+
if (!(symbol && this.consts.coins[symbol])) {
|
|
484
482
|
return [];
|
|
485
483
|
}
|
|
484
|
+
const coinModule = symbol === 'sui' ? '0x2::sui::SUI' : this.consts.coins[symbol].module;
|
|
485
|
+
positionDynamicFields = positionDynamicFields.filter((field) => {
|
|
486
|
+
// Extract the second coin module from PositionName<coin1, coin2, direction>
|
|
487
|
+
const typeStr = field.name?.type;
|
|
488
|
+
if (!typeStr)
|
|
489
|
+
return false;
|
|
490
|
+
const match = typeStr.match(/PositionName<([^,]+),([^,]+),([^>]+)>/);
|
|
491
|
+
if (!match)
|
|
492
|
+
return false;
|
|
493
|
+
const secondCoin = match[2].trim();
|
|
494
|
+
return secondCoin === coinModule;
|
|
495
|
+
});
|
|
486
496
|
// then we query by dynamic field names and order by time
|
|
487
497
|
const positionInfoList = [];
|
|
488
498
|
for (let i = 0; i < positionDynamicFields.length; i += batchSize) {
|
|
@@ -493,7 +503,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
493
503
|
name: positionDynamicField.name,
|
|
494
504
|
});
|
|
495
505
|
if (positionRaw?.data?.content) {
|
|
496
|
-
// @ts-
|
|
506
|
+
// @ts-expect-error: content fields type is not properly defined
|
|
497
507
|
if (positionRaw?.data?.content?.fields?.value?.fields?.closed) {
|
|
498
508
|
// skip closed positions
|
|
499
509
|
return;
|
|
@@ -510,7 +520,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
510
520
|
.sort((a, b) => (a.openTimestamp > b.openTimestamp ? 1 : -1));
|
|
511
521
|
}
|
|
512
522
|
async getPositionCapInfoList(owner) {
|
|
513
|
-
let cursor
|
|
523
|
+
let cursor;
|
|
514
524
|
let hasNextPage = true;
|
|
515
525
|
const positionCapInfoList = [];
|
|
516
526
|
while (hasNextPage) {
|
|
@@ -544,7 +554,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
544
554
|
return positionCapInfoList;
|
|
545
555
|
}
|
|
546
556
|
async getOrderCapInfoList(owner) {
|
|
547
|
-
let cursor
|
|
557
|
+
let cursor;
|
|
548
558
|
let hasNextPage = true;
|
|
549
559
|
const orderCapInfoList = [];
|
|
550
560
|
while (hasNextPage) {
|
|
@@ -602,7 +612,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
602
612
|
const orderRaw = await this.provider.getDynamicFieldObject({
|
|
603
613
|
parentId: this.consts.sudoCore.ordersParent,
|
|
604
614
|
name: {
|
|
605
|
-
type: `${this.consts.sudoCore.package}::market::OrderName<${orderCapInfo.symbol0}, ${orderCapInfo.symbol1}, ${this.consts.sudoCore.package}::market::${orderCapInfo.long ? 'LONG' : 'SHORT'}, ${this.consts.coins
|
|
615
|
+
type: `${this.consts.sudoCore.package}::market::OrderName<${orderCapInfo.symbol0}, ${orderCapInfo.symbol1}, ${this.consts.sudoCore.package}::market::${orderCapInfo.long ? 'LONG' : 'SHORT'}, ${this.consts.coins.sui.module}>`,
|
|
606
616
|
value: {
|
|
607
617
|
owner,
|
|
608
618
|
id: orderCapInfo.orderCapId,
|
|
@@ -619,9 +629,9 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
619
629
|
async getCumulativeApr() {
|
|
620
630
|
const refetchDate = new Date(Date.now() - 3600000);
|
|
621
631
|
// fetch new every hour
|
|
622
|
-
if (!aprResponse?.generatedAt
|
|
623
|
-
(aprResponse?.generatedAt
|
|
624
|
-
refetchDate > new Date(aprResponse?.generatedAt))) {
|
|
632
|
+
if (!aprResponse?.generatedAt
|
|
633
|
+
|| (aprResponse?.generatedAt
|
|
634
|
+
&& refetchDate > new Date(aprResponse?.generatedAt))) {
|
|
625
635
|
try {
|
|
626
636
|
const url = `${this.apiEndpoint}/cumulativeApr`;
|
|
627
637
|
const res = await fetch(url, {
|
|
@@ -631,64 +641,63 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
631
641
|
},
|
|
632
642
|
});
|
|
633
643
|
const data = await res.json();
|
|
644
|
+
// eslint-disable-next-line require-atomic-updates
|
|
634
645
|
aprResponse = { ...data };
|
|
635
646
|
return data.cumulativeApr;
|
|
636
647
|
}
|
|
637
|
-
catch
|
|
648
|
+
catch {
|
|
638
649
|
console.error('Failed to get cumulative APR');
|
|
639
650
|
}
|
|
640
651
|
return 0;
|
|
641
652
|
}
|
|
642
|
-
|
|
643
|
-
return aprResponse.apr;
|
|
644
|
-
}
|
|
653
|
+
return aprResponse.apr;
|
|
645
654
|
}
|
|
646
655
|
// Private helper methods
|
|
647
|
-
calculatePositionFundingFee(position, symbol, model, price, lpSupplyAmount, timestamp) {
|
|
656
|
+
static calculatePositionFundingFee(position, symbol, model, price, lpSupplyAmount, timestamp) {
|
|
648
657
|
const accFundingRate = this.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, position.long);
|
|
649
658
|
return position.fundingFeeValue + (accFundingRate - position.lastFundingRate) * position.positionSize;
|
|
650
659
|
}
|
|
651
|
-
calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, isLong) {
|
|
660
|
+
static calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, isLong) {
|
|
652
661
|
if (symbol.lastUpdate > 0) {
|
|
653
662
|
const elapsed = timestamp - symbol.lastUpdate;
|
|
654
663
|
if (elapsed > 0) {
|
|
655
664
|
const deltaSize = this.calcDeltaSize(symbol, price, isLong);
|
|
656
665
|
const pnlPerLp = (symbol.realisedPnl + symbol.unrealisedFundingFeeValue + deltaSize) / lpSupplyAmount;
|
|
657
|
-
return symbol.accFundingRate +
|
|
666
|
+
return symbol.accFundingRate + SLPDataAPI.calcFundingFeeRate(model, pnlPerLp, elapsed);
|
|
658
667
|
}
|
|
659
668
|
}
|
|
660
669
|
return symbol.accFundingRate;
|
|
661
670
|
}
|
|
662
|
-
calcDeltaSize(symbol, price, isLong) {
|
|
671
|
+
static calcDeltaSize(symbol, price, isLong) {
|
|
663
672
|
const latestSize = symbol.openingAmount * price;
|
|
664
673
|
return isLong ? symbol.openingSize - latestSize : latestSize - symbol.openingSize;
|
|
665
674
|
}
|
|
666
|
-
calcFundingFeeRate(model, pnlPerRate, elapsed) {
|
|
675
|
+
static calcFundingFeeRate(model, pnlPerRate, elapsed) {
|
|
667
676
|
const dailyRate = Math.min(model.multiplier * Math.abs(pnlPerRate), model.max);
|
|
668
677
|
const secondsRate = dailyRate * elapsed / SECONDS_PER_EIGHT_HOUR;
|
|
669
678
|
return pnlPerRate >= 0 ? -secondsRate : secondsRate;
|
|
670
679
|
}
|
|
671
|
-
calculatePositionReserveFee(position, vault, model, timestamp) {
|
|
672
|
-
const accReservingRate =
|
|
680
|
+
static calculatePositionReserveFee(position, vault, model, timestamp) {
|
|
681
|
+
const accReservingRate = SLPDataAPI.calcAccReservingFeeRate(vault, model, timestamp);
|
|
673
682
|
return position.reservingFeeAmount + (accReservingRate - position.lastReservingRate) * position.collateralAmount;
|
|
674
683
|
}
|
|
675
|
-
calcAccReservingFeeRate(vault, model, timestamp) {
|
|
684
|
+
static calcAccReservingFeeRate(vault, model, timestamp) {
|
|
676
685
|
if (vault.lastUpdate > 0) {
|
|
677
686
|
const elapsed = timestamp - vault.lastUpdate;
|
|
678
687
|
if (elapsed > 0) {
|
|
679
|
-
const utilization =
|
|
680
|
-
return vault.accReservingRate +
|
|
688
|
+
const utilization = SLPDataAPI.vaultUtilization(vault);
|
|
689
|
+
return vault.accReservingRate + SLPDataAPI.calcReservingFeeRate(model, utilization, elapsed);
|
|
681
690
|
}
|
|
682
691
|
}
|
|
683
692
|
return vault.accReservingRate;
|
|
684
693
|
}
|
|
685
|
-
vaultUtilization(vault) {
|
|
694
|
+
static vaultUtilization(vault) {
|
|
686
695
|
return vault.liquidity > 0 ? vault.reservedAmount / vault.liquidity : 0;
|
|
687
696
|
}
|
|
688
|
-
calcReservingFeeRate(model, utilization, elapsed) {
|
|
697
|
+
static calcReservingFeeRate(model, utilization, elapsed) {
|
|
689
698
|
return model.multiplier * utilization * elapsed / SECONDS_PER_EIGHT_HOUR;
|
|
690
699
|
}
|
|
691
|
-
parsePositionConfig(raw) {
|
|
700
|
+
static parsePositionConfig(raw) {
|
|
692
701
|
const positionConfigFields = raw.data.content.fields.inner.fields;
|
|
693
702
|
return {
|
|
694
703
|
decreaseFeeBps: parseValue(positionConfigFields.decrease_fee_bps),
|
|
@@ -701,21 +710,21 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
701
710
|
minCollateralValue: parseValue(positionConfigFields.min_collateral_value),
|
|
702
711
|
};
|
|
703
712
|
}
|
|
704
|
-
parseRebaseFeeModel(raw) {
|
|
713
|
+
static parseRebaseFeeModel(raw) {
|
|
705
714
|
const { fields } = raw.data.content;
|
|
706
715
|
return {
|
|
707
716
|
base: parseValue(fields.base),
|
|
708
717
|
multiplier: parseValue(fields.multiplier),
|
|
709
718
|
};
|
|
710
719
|
}
|
|
711
|
-
parseFundingFeeModel(raw) {
|
|
720
|
+
static parseFundingFeeModel(raw) {
|
|
712
721
|
const { fields } = raw.data.content;
|
|
713
722
|
return {
|
|
714
723
|
multiplier: parseValue(fields.multiplier),
|
|
715
724
|
max: parseValue(fields.max),
|
|
716
725
|
};
|
|
717
726
|
}
|
|
718
|
-
parseMarketInfo(raw) {
|
|
727
|
+
static parseMarketInfo(raw) {
|
|
719
728
|
const content = raw.data.content.fields;
|
|
720
729
|
return {
|
|
721
730
|
lpSupply: content.lp_supply.fields.value,
|
|
@@ -734,7 +743,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
734
743
|
showContent: true,
|
|
735
744
|
},
|
|
736
745
|
});
|
|
737
|
-
const reservingFeeModel =
|
|
746
|
+
const reservingFeeModel = SLPDataAPI.parseReservingFeeModel(reservingFeeModelRaw);
|
|
738
747
|
return {
|
|
739
748
|
liquidity: parseValue(vaultFields.liquidity),
|
|
740
749
|
reservedAmount: parseValue(vaultFields.reserved_amount),
|
|
@@ -752,14 +761,14 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
752
761
|
},
|
|
753
762
|
};
|
|
754
763
|
}
|
|
755
|
-
parseReservingFeeModel(raw) {
|
|
764
|
+
static parseReservingFeeModel(raw) {
|
|
756
765
|
const content = raw.data.content.fields;
|
|
757
766
|
return {
|
|
758
767
|
multiplier: parseValue(content.multiplier),
|
|
759
768
|
};
|
|
760
769
|
}
|
|
761
770
|
async parseSymbolInfo(raw, long) {
|
|
762
|
-
const fields = raw.data.content.fields.value
|
|
771
|
+
const { fields } = raw.data.content.fields.value;
|
|
763
772
|
const fundingFeeModelAddr = fields.funding_fee_model;
|
|
764
773
|
const fundingFeeModelRaw = await this.provider.getObject({
|
|
765
774
|
id: fundingFeeModelAddr,
|
|
@@ -767,7 +776,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
767
776
|
showContent: true,
|
|
768
777
|
},
|
|
769
778
|
});
|
|
770
|
-
const fundingFeeModel =
|
|
779
|
+
const fundingFeeModel = SLPDataAPI.parseFundingFeeModel(fundingFeeModelRaw);
|
|
771
780
|
return {
|
|
772
781
|
openingSize: parseValue(fields.opening_size),
|
|
773
782
|
openingAmount: parseValue(fields.opening_amount),
|
|
@@ -789,15 +798,15 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
789
798
|
};
|
|
790
799
|
}
|
|
791
800
|
async parsePositionInfo(raw, id_) {
|
|
792
|
-
const content = raw.data
|
|
793
|
-
const fields = content
|
|
801
|
+
const { content } = raw.data;
|
|
802
|
+
const { fields } = content;
|
|
794
803
|
const positionFields = fields.value.fields;
|
|
795
804
|
const dataType = fields.name.type;
|
|
796
805
|
const positionInfo = {
|
|
797
806
|
id: id_,
|
|
798
807
|
long: dataType.includes('::market::LONG'),
|
|
799
808
|
owner: fields.name.fields.owner,
|
|
800
|
-
version: parseInt(raw.data.version, 10),
|
|
809
|
+
version: Number.parseInt(raw.data.version, 10),
|
|
801
810
|
collateralToken: suiSymbolToSymbol(dataType.split('<')[1].split(',')[0].trim(), this.consts),
|
|
802
811
|
indexToken: suiSymbolToSymbol(dataType.split(',')[1].trim(), this.consts),
|
|
803
812
|
collateralAmount: parseValue(positionFields.collateral),
|
|
@@ -814,8 +823,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
814
823
|
};
|
|
815
824
|
if (!positionFields.closed) {
|
|
816
825
|
try {
|
|
817
|
-
positionInfo.reservingFeeAmount =
|
|
818
|
-
positionInfo.fundingFeeValue =
|
|
826
|
+
positionInfo.reservingFeeAmount = SLPDataAPI.calculatePositionReserveFee(positionInfo, await this.getVaultInfo(positionInfo.collateralToken), (await this.getVaultInfo(positionInfo.collateralToken)).reservingFeeModel, Date.now() / 1000);
|
|
827
|
+
positionInfo.fundingFeeValue = SLPDataAPI.calculatePositionFundingFee(positionInfo, await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long), (await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long)).fundingFeeModel, (await this.getOraclePrice(positionInfo.indexToken)).getPriceUnchecked().getPriceAsNumberUnchecked(), (await this.getMarketInfo()).lpSupplyWithDecimals, Date.now() / 1000);
|
|
819
828
|
}
|
|
820
829
|
catch (e) {
|
|
821
830
|
console.error(e);
|
|
@@ -826,14 +835,14 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
826
835
|
return positionInfo;
|
|
827
836
|
}
|
|
828
837
|
parseOrderInfo(raw, capId) {
|
|
829
|
-
|
|
830
|
-
|
|
838
|
+
const { content } = raw.data;
|
|
839
|
+
const { fields } = content.fields.value;
|
|
831
840
|
// Extract tokens from dataType
|
|
832
|
-
|
|
841
|
+
const dataType = content.type;
|
|
833
842
|
const orderType = content.fields.value.type.includes('OpenPositionOrder')
|
|
834
843
|
? 'OPEN_POSITION'
|
|
835
844
|
: 'DECREASE_POSITION';
|
|
836
|
-
|
|
845
|
+
const ret = {
|
|
837
846
|
id: content.fields.id.id,
|
|
838
847
|
capId,
|
|
839
848
|
executed: fields.executed,
|
|
@@ -863,7 +872,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
863
872
|
}
|
|
864
873
|
return ret;
|
|
865
874
|
}
|
|
866
|
-
parseCredential(raw, pool) {
|
|
875
|
+
static parseCredential(raw, pool) {
|
|
867
876
|
const stakedAmount = BigInt(raw.data.content.fields.stake);
|
|
868
877
|
const accRewardPerShare = BigInt(raw.data.content.fields.acc_reward_per_share);
|
|
869
878
|
return {
|
|
@@ -871,11 +880,11 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
871
880
|
lockUntil: parseValue(raw.data.content.fields.lock_until),
|
|
872
881
|
amount: stakedAmount,
|
|
873
882
|
accRewardPerShare,
|
|
874
|
-
claimable: ((pool.accRewardPerShare - accRewardPerShare) * stakedAmount)
|
|
875
|
-
BigInt(1e18),
|
|
883
|
+
claimable: ((pool.accRewardPerShare - accRewardPerShare) * stakedAmount)
|
|
884
|
+
/ BigInt(1e18),
|
|
876
885
|
};
|
|
877
886
|
}
|
|
878
|
-
parseStakePool(raw) {
|
|
887
|
+
static parseStakePool(raw) {
|
|
879
888
|
const content = raw.data.content.fields;
|
|
880
889
|
const pool = {
|
|
881
890
|
id: content.id.id,
|
|
@@ -888,22 +897,22 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
888
897
|
accRewardPerShare: BigInt(content.acc_reward_per_share),
|
|
889
898
|
lockDuration: parseValue(content.lock_duration),
|
|
890
899
|
};
|
|
891
|
-
|
|
900
|
+
SLPDataAPI.refreshPool(pool, Math.floor(Date.now() / 1000));
|
|
892
901
|
return pool;
|
|
893
902
|
}
|
|
894
|
-
refreshPool(pool, timestamp) {
|
|
903
|
+
static refreshPool(pool, timestamp) {
|
|
895
904
|
if (timestamp === pool.lastUpdatedTime || timestamp < pool.startTime) {
|
|
896
905
|
return;
|
|
897
906
|
}
|
|
898
|
-
if (pool.lastUpdatedTime === pool.endTime
|
|
899
|
-
pool.stakedAmount === BigInt(0)) {
|
|
907
|
+
if (pool.lastUpdatedTime === pool.endTime
|
|
908
|
+
|| pool.stakedAmount === BigInt(0)) {
|
|
900
909
|
return;
|
|
901
910
|
}
|
|
902
911
|
if (timestamp > pool.endTime) {
|
|
903
912
|
timestamp = pool.endTime;
|
|
904
913
|
}
|
|
905
|
-
const rewardAmount = (pool.reward * BigInt(timestamp - pool.lastUpdatedTime))
|
|
906
|
-
BigInt(pool.endTime - pool.lastUpdatedTime);
|
|
914
|
+
const rewardAmount = (pool.reward * BigInt(timestamp - pool.lastUpdatedTime))
|
|
915
|
+
/ BigInt(pool.endTime - pool.lastUpdatedTime);
|
|
907
916
|
pool.lastUpdatedTime = timestamp;
|
|
908
917
|
const rewardPerShare = (rewardAmount * BigInt(1e18)) / pool.stakedAmount;
|
|
909
918
|
pool.accRewardPerShare += rewardPerShare;
|