@scallop-io/sui-scallop-sdk 2.0.4 → 2.0.6
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/index.d.mts +12 -5
- package/dist/index.d.ts +12 -5
- package/dist/index.js +11 -11
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
- package/src/builders/coreBuilder.ts +16 -39
- package/src/builders/sCoinBuilder.ts +2 -2
- package/src/models/scallopBuilder.ts +77 -1
- package/src/models/scallopCache.ts +1 -1
- package/src/models/scallopConstants.ts +1 -1
- package/src/queries/portfolioQuery.ts +11 -8
package/package.json
CHANGED
|
@@ -359,51 +359,28 @@ const generateCoreQuickMethod: GenerateCoreQuickMethod = ({
|
|
|
359
359
|
},
|
|
360
360
|
withdrawQuick: async (amount, poolCoinName) => {
|
|
361
361
|
const sender = requireSender(txBlock);
|
|
362
|
-
const marketCoinName = builder.utils.parseMarketCoinName(poolCoinName);
|
|
363
|
-
|
|
364
362
|
const sCoinName = builder.utils.parseSCoinName(poolCoinName);
|
|
365
363
|
if (!sCoinName) throw new Error(`No sCoin for ${poolCoinName}`);
|
|
366
364
|
|
|
367
|
-
//
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
const { leftCoin, takeCoin: walletMarketCoins } =
|
|
375
|
-
await builder.selectMarketCoin(
|
|
376
|
-
txBlock,
|
|
377
|
-
marketCoinName,
|
|
378
|
-
amount,
|
|
379
|
-
sender
|
|
380
|
-
);
|
|
381
|
-
txBlock.transferObjects([leftCoin], sender);
|
|
382
|
-
return txBlock.withdraw(walletMarketCoins, poolCoinName);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
txBlock.transferObjects([leftCoin], sender);
|
|
386
|
-
const marketCoins = txBlock.burnSCoin(sCoinName, sCoins);
|
|
365
|
+
// eslint-disable-next-line prefer-const
|
|
366
|
+
let { sCoin, marketCoin } = await builder.selectSCoinOrMarketCoin(
|
|
367
|
+
txBlock,
|
|
368
|
+
sCoinName,
|
|
369
|
+
amount,
|
|
370
|
+
sender
|
|
371
|
+
);
|
|
387
372
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
await builder.selectMarketCoin(
|
|
395
|
-
txBlock,
|
|
396
|
-
marketCoinName,
|
|
397
|
-
amount,
|
|
398
|
-
sender
|
|
399
|
-
);
|
|
400
|
-
txBlock.transferObjects([leftCoin], sender);
|
|
401
|
-
txBlock.mergeCoins(marketCoins, [walletMarketCoins]);
|
|
373
|
+
if (sCoin) {
|
|
374
|
+
const newMarketCoin = txBlock.burnSCoin(sCoinName, sCoin);
|
|
375
|
+
if (marketCoin) {
|
|
376
|
+
txBlock.mergeCoins(marketCoin, newMarketCoin);
|
|
377
|
+
} else {
|
|
378
|
+
marketCoin = newMarketCoin;
|
|
402
379
|
}
|
|
403
|
-
} catch (_e) {
|
|
404
|
-
// ignore
|
|
405
380
|
}
|
|
406
|
-
|
|
381
|
+
|
|
382
|
+
if (!marketCoin) throw new Error(`No market coin for ${poolCoinName}`);
|
|
383
|
+
return txBlock.withdraw(marketCoin, poolCoinName);
|
|
407
384
|
},
|
|
408
385
|
borrowQuick: async (amount, poolCoinName, obligationId, obligationKey) => {
|
|
409
386
|
const obligationInfo = await requireObligationInfo(
|
|
@@ -61,7 +61,7 @@ const generateSCoinQuickMethod: GenerateSCoinQuickMethod = ({
|
|
|
61
61
|
);
|
|
62
62
|
|
|
63
63
|
txBlock.transferObjects([leftCoin], sender);
|
|
64
|
-
return
|
|
64
|
+
return txBlock.mintSCoin(marketCoinName, takeCoin);
|
|
65
65
|
},
|
|
66
66
|
burnSCoinQuick: async (sCoinName, amount) => {
|
|
67
67
|
const sender = requireSender(txBlock);
|
|
@@ -73,7 +73,7 @@ const generateSCoinQuickMethod: GenerateSCoinQuickMethod = ({
|
|
|
73
73
|
);
|
|
74
74
|
|
|
75
75
|
txBlock.transferObjects([leftCoin], sender);
|
|
76
|
-
return
|
|
76
|
+
return txBlock.burnSCoin(sCoinName, takeCoin);
|
|
77
77
|
},
|
|
78
78
|
};
|
|
79
79
|
};
|
|
@@ -5,7 +5,10 @@ import { ScallopAddress } from './scallopAddress';
|
|
|
5
5
|
import { ScallopQuery } from './scallopQuery';
|
|
6
6
|
import { ScallopUtils } from './scallopUtils';
|
|
7
7
|
import type { SuiTransactionBlockResponse } from '@mysten/sui/client';
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
Transaction,
|
|
10
|
+
TransactionObjectArgument,
|
|
11
|
+
} from '@mysten/sui/transactions';
|
|
9
12
|
import type {
|
|
10
13
|
SuiAmountsArg,
|
|
11
14
|
SuiTxBlock as SuiKitTxBlock,
|
|
@@ -201,6 +204,79 @@ export class ScallopBuilder {
|
|
|
201
204
|
};
|
|
202
205
|
}
|
|
203
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Select sCoin or market coin automatically. Prioritize sCoin first
|
|
209
|
+
*/
|
|
210
|
+
public async selectSCoinOrMarketCoin(
|
|
211
|
+
txBlock: ScallopTxBlock | SuiKitTxBlock,
|
|
212
|
+
sCoinName: string,
|
|
213
|
+
amount: number,
|
|
214
|
+
sender: string = this.walletAddress
|
|
215
|
+
) {
|
|
216
|
+
let totalAmount = amount;
|
|
217
|
+
const result = {
|
|
218
|
+
sCoins: [] as TransactionObjectArgument[],
|
|
219
|
+
marketCoins: [] as TransactionObjectArgument[],
|
|
220
|
+
leftCoins: [] as TransactionObjectArgument[],
|
|
221
|
+
};
|
|
222
|
+
try {
|
|
223
|
+
// try sCoin first
|
|
224
|
+
const {
|
|
225
|
+
leftCoin,
|
|
226
|
+
takeCoin,
|
|
227
|
+
totalAmount: sCoinAmount,
|
|
228
|
+
} = await this.selectSCoin(txBlock, sCoinName, totalAmount, sender);
|
|
229
|
+
result.leftCoins.push(leftCoin);
|
|
230
|
+
result.sCoins.push(takeCoin);
|
|
231
|
+
totalAmount -= sCoinAmount;
|
|
232
|
+
|
|
233
|
+
if (totalAmount > 0) {
|
|
234
|
+
// sCoin is not enough, try market coin
|
|
235
|
+
const { leftCoin, takeCoin: marketCoin } = await this.selectMarketCoin(
|
|
236
|
+
txBlock,
|
|
237
|
+
sCoinName,
|
|
238
|
+
amount,
|
|
239
|
+
sender
|
|
240
|
+
);
|
|
241
|
+
txBlock.transferObjects([leftCoin], sender);
|
|
242
|
+
result.marketCoins.push(marketCoin);
|
|
243
|
+
}
|
|
244
|
+
} catch (_e) {
|
|
245
|
+
// no sCoin, try market coin
|
|
246
|
+
const { takeCoin: marketCoin, leftCoin } = await this.selectMarketCoin(
|
|
247
|
+
txBlock,
|
|
248
|
+
sCoinName,
|
|
249
|
+
amount,
|
|
250
|
+
sender
|
|
251
|
+
);
|
|
252
|
+
result.leftCoins.push(leftCoin);
|
|
253
|
+
result.marketCoins.push(marketCoin);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
txBlock.transferObjects(result.leftCoins, sender);
|
|
257
|
+
|
|
258
|
+
// merge sCoins and marketCoins
|
|
259
|
+
const mergedMarketCoins =
|
|
260
|
+
result.marketCoins.length > 0
|
|
261
|
+
? result.marketCoins.length > 1
|
|
262
|
+
? txBlock.mergeCoins(
|
|
263
|
+
result.marketCoins[0],
|
|
264
|
+
result.marketCoins.slice(1)
|
|
265
|
+
)
|
|
266
|
+
: result.marketCoins[0]
|
|
267
|
+
: undefined;
|
|
268
|
+
const mergedSCoins =
|
|
269
|
+
result.sCoins.length > 0
|
|
270
|
+
? result.sCoins.length > 1
|
|
271
|
+
? txBlock.mergeCoins(result.sCoins[0], result.sCoins.slice(1))
|
|
272
|
+
: result.sCoins[0]
|
|
273
|
+
: undefined;
|
|
274
|
+
return {
|
|
275
|
+
sCoin: mergedSCoins,
|
|
276
|
+
marketCoin: mergedMarketCoins,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
204
280
|
/**
|
|
205
281
|
* Execute Scallop txBlock using the `signAndSendTxn` methods in suikit.
|
|
206
282
|
*
|
|
@@ -210,7 +210,7 @@ export class ScallopConstants {
|
|
|
210
210
|
if (this.isEmptyObject(this._coinNameToOldMarketCoinTypeMap))
|
|
211
211
|
this._coinNameToOldMarketCoinTypeMap = Object.fromEntries(
|
|
212
212
|
Object.entries(this.poolAddresses)
|
|
213
|
-
.filter(([_, value]) => !!value
|
|
213
|
+
.filter(([_, value]) => !!value)
|
|
214
214
|
.map(([_, value]) => [
|
|
215
215
|
value!.coinName,
|
|
216
216
|
this.parseToOldMarketCoin(value!.coinType),
|
|
@@ -852,7 +852,7 @@ export const getUserPortfolio = async (
|
|
|
852
852
|
walletAddress: string,
|
|
853
853
|
indexer: boolean = false
|
|
854
854
|
) => {
|
|
855
|
-
const coinPrices = await query.
|
|
855
|
+
const coinPrices = await query.getAllCoinPrices({ indexer });
|
|
856
856
|
const market = await query.getMarketPools(undefined, { indexer, coinPrices });
|
|
857
857
|
|
|
858
858
|
const [lendings, obligationAccounts, borrowIncentivePools, veScas] =
|
|
@@ -953,19 +953,22 @@ export const getUserPortfolio = async (
|
|
|
953
953
|
};
|
|
954
954
|
});
|
|
955
955
|
|
|
956
|
+
const LENDING_SPOOL_REWARD_COIN_NAME = 'sui' as const;
|
|
957
|
+
const LENDING_SPOOL_REWARD_COIN_SYMBOL = 'SUI' as const;
|
|
956
958
|
const pendingLendingRewards = Object.values(lendings).reduce(
|
|
957
959
|
(acc, reward) => {
|
|
958
960
|
if (reward) {
|
|
959
961
|
if (reward.availableClaimCoin === 0) return acc;
|
|
960
|
-
if (!acc[
|
|
961
|
-
acc[
|
|
962
|
-
symbol:
|
|
962
|
+
if (!acc[LENDING_SPOOL_REWARD_COIN_NAME]) {
|
|
963
|
+
acc[LENDING_SPOOL_REWARD_COIN_NAME] = {
|
|
964
|
+
symbol: LENDING_SPOOL_REWARD_COIN_SYMBOL,
|
|
963
965
|
coinType: normalizeStructTag(SUI_TYPE_ARG), // @TODO: for now lending reward is all in SUI
|
|
964
|
-
coinPrice:
|
|
966
|
+
coinPrice: coinPrices[LENDING_SPOOL_REWARD_COIN_NAME] ?? 0,
|
|
965
967
|
pendingRewardInCoin: reward.availableClaimCoin,
|
|
966
968
|
};
|
|
967
969
|
} else {
|
|
968
|
-
acc[
|
|
970
|
+
acc[LENDING_SPOOL_REWARD_COIN_NAME].pendingRewardInCoin +=
|
|
971
|
+
reward.availableClaimCoin;
|
|
969
972
|
}
|
|
970
973
|
}
|
|
971
974
|
return acc;
|
|
@@ -1054,10 +1057,10 @@ export const getUserPortfolio = async (
|
|
|
1054
1057
|
borrowings: parsedObligationAccounts,
|
|
1055
1058
|
pendingRewards: {
|
|
1056
1059
|
lendings: Object.entries(pendingLendingRewards).reduce(
|
|
1057
|
-
(acc, [
|
|
1060
|
+
(acc, [_, value]) => {
|
|
1058
1061
|
acc.push({
|
|
1059
1062
|
...value,
|
|
1060
|
-
coinName:
|
|
1063
|
+
coinName: 'sui',
|
|
1061
1064
|
pendingRewardInUsd: value.coinPrice * value.pendingRewardInCoin,
|
|
1062
1065
|
});
|
|
1063
1066
|
return acc;
|