@ickb/sdk 1000.0.43 → 1000.0.52
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/cjs/index.d.ts +120 -9
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +140 -34
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.ts +120 -9
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +141 -35
- package/dist/esm/index.js.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +219 -53
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
asyncBinarySearch,
|
|
12
12
|
RestrictedTransaction,
|
|
13
13
|
type ExchangeRatio,
|
|
14
|
+
binarySearch,
|
|
14
15
|
} from "@ickb/utils";
|
|
15
16
|
import {
|
|
16
17
|
convert,
|
|
@@ -31,61 +32,94 @@ import {
|
|
|
31
32
|
type OrderGroup,
|
|
32
33
|
} from "@ickb/order";
|
|
33
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Controller for managing iCKB operations.
|
|
37
|
+
*/
|
|
34
38
|
export class IckbController {
|
|
39
|
+
/**
|
|
40
|
+
* Creates an instance of IckbController.
|
|
41
|
+
* @param ickbUdtManager - The manager for iCKB UDT operations.
|
|
42
|
+
* @param logicManager - The logic manager for handling business logic.
|
|
43
|
+
* @param ownedOwnerManager - The manager for owned owner operations.
|
|
44
|
+
* @param orderManager - The manager for order operations.
|
|
45
|
+
* @param daoManager - The manager for DAO operations.
|
|
46
|
+
*/
|
|
35
47
|
constructor(
|
|
36
48
|
public readonly ickbUdtManager: IckbUdtManager,
|
|
37
49
|
public readonly logicManager: LogicManager,
|
|
38
50
|
public readonly ownedOwnerManager: OwnedOwnerManager,
|
|
39
51
|
public readonly orderManager: OrderManager,
|
|
40
52
|
public readonly daoManager: DaoManager,
|
|
53
|
+
public readonly bots: ccc.Script[],
|
|
41
54
|
) {}
|
|
42
55
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Creates an instance of IckbController from script dependencies.
|
|
58
|
+
* @param deps - The script dependencies.
|
|
59
|
+
* @param deps.udt - The script dependencies for UDT.
|
|
60
|
+
* @param deps.dao - The script dependencies for DAO.
|
|
61
|
+
* @param deps.ickbLogic - The script dependencies for iCKB logic.
|
|
62
|
+
* @param deps.ownedOwner - The script dependencies for owned owner.
|
|
63
|
+
* @param deps.order - The script dependencies for order.
|
|
64
|
+
* @returns An instance of IckbController.
|
|
65
|
+
*/
|
|
66
|
+
static fromDeps(
|
|
67
|
+
deps: {
|
|
68
|
+
udt: ScriptDeps;
|
|
69
|
+
dao: ScriptDeps;
|
|
70
|
+
ickbLogic: ScriptDeps;
|
|
71
|
+
ownedOwner: ScriptDeps;
|
|
72
|
+
order: ScriptDeps;
|
|
73
|
+
},
|
|
74
|
+
bots: ccc.Script[],
|
|
75
|
+
): IckbController {
|
|
58
76
|
const {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
udt: {
|
|
78
|
+
script: { codeHash, hashType },
|
|
79
|
+
cellDeps,
|
|
80
|
+
},
|
|
81
|
+
ickbLogic: { script: ickbLogicScript },
|
|
82
|
+
} = deps;
|
|
83
|
+
|
|
84
|
+
const daoManager = DaoManager.fromDeps(deps);
|
|
85
|
+
const udt = {
|
|
63
86
|
script: new ccc.Script(
|
|
64
87
|
codeHash,
|
|
65
88
|
hashType,
|
|
66
|
-
[
|
|
89
|
+
[ickbLogicScript.hash(), "00000080"].join("") as ccc.Hex,
|
|
67
90
|
),
|
|
68
91
|
cellDeps,
|
|
69
92
|
};
|
|
70
|
-
const ickbUdtManager = IckbUdtManager.fromDeps(
|
|
93
|
+
const ickbUdtManager = IckbUdtManager.fromDeps({ udt }, daoManager);
|
|
71
94
|
|
|
72
95
|
return new IckbController(
|
|
73
96
|
ickbUdtManager,
|
|
74
|
-
LogicManager.fromDeps(
|
|
75
|
-
OwnedOwnerManager.fromDeps(
|
|
76
|
-
OrderManager.fromDeps(
|
|
97
|
+
LogicManager.fromDeps(deps, daoManager, ickbUdtManager),
|
|
98
|
+
OwnedOwnerManager.fromDeps(deps, daoManager, ickbUdtManager),
|
|
99
|
+
OrderManager.fromDeps(deps, ickbUdtManager),
|
|
77
100
|
daoManager,
|
|
101
|
+
bots,
|
|
78
102
|
);
|
|
79
103
|
}
|
|
80
104
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Previews the conversion between CKB and UDT.
|
|
107
|
+
* @param conversion - The conversion parameters.
|
|
108
|
+
* @param conversion.isCkb2Udt - Indicates if the conversion is from CKB to UDT.
|
|
109
|
+
* @param conversion.amount - The amount to convert.
|
|
110
|
+
* @param conversion.rate - The exchange rate for conversion.
|
|
111
|
+
* @param conversion.fee - The fee for the conversion.
|
|
112
|
+
* @returns The rate and converted amount.
|
|
113
|
+
*
|
|
114
|
+
* Fee meaning examples:
|
|
115
|
+
* - 100000n => 0.001%
|
|
116
|
+
* - 10000n => 0.01%
|
|
117
|
+
* - 1000n => 0.1%
|
|
118
|
+
* - 100n => 1%
|
|
119
|
+
* - 10n => 10%
|
|
120
|
+
* - 1n => 100%
|
|
121
|
+
* - less than 1n => 0%
|
|
122
|
+
*/
|
|
89
123
|
static previewConversion(conversion: {
|
|
90
124
|
isCkb2Udt: boolean;
|
|
91
125
|
amount: ccc.FixedPoint;
|
|
@@ -111,6 +145,23 @@ export class IckbController {
|
|
|
111
145
|
return { rate, convertedAmount };
|
|
112
146
|
}
|
|
113
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Converts between CKB and UDT based on the provided options.
|
|
150
|
+
* @param options - The conversion options.
|
|
151
|
+
* @param options.conversion - The conversion parameters.
|
|
152
|
+
* @param options.conversion.isCkb2Udt - Indicates if the conversion is from CKB to UDT.
|
|
153
|
+
* @param options.conversion.amount - The amount to convert.
|
|
154
|
+
* @param options.conversion.rate - The exchange rate for conversion.
|
|
155
|
+
* @param options.conversion.ckbMinMatchLog - Minimum CKB match log (optional).
|
|
156
|
+
* @param options.conversion.ckbMinFee - Minimum CKB fee (optional).
|
|
157
|
+
* @param options.signer - The signer for the transaction.
|
|
158
|
+
* @param options.userCells - The user's cells.
|
|
159
|
+
* @param options.system - The current system state.
|
|
160
|
+
* @param options.filters - The filters for the conversion.
|
|
161
|
+
* @param options.filters.isReadyOnly - Indicates if only ready conversions should be considered.
|
|
162
|
+
* @param options.filters.isFulfilledOnly - Indicates if only fulfilled conversions should be considered.
|
|
163
|
+
* @returns A promise that resolves to the conversion result or undefined.
|
|
164
|
+
*/
|
|
114
165
|
async convert(options: {
|
|
115
166
|
conversion: Parameters<typeof IckbController.previewConversion>[0] & {
|
|
116
167
|
ckbMinMatchLog?: number;
|
|
@@ -166,6 +217,19 @@ export class IckbController {
|
|
|
166
217
|
);
|
|
167
218
|
}
|
|
168
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Attempts to perform a conversion based on the provided parameters.
|
|
222
|
+
* @param n - The size of deposit to make or withdraw from.
|
|
223
|
+
* @param conversion - The conversion parameters.
|
|
224
|
+
* @param conversion.isCkb2Udt - Indicates if the conversion is from CKB to UDT.
|
|
225
|
+
* @param conversion.amount - The amount to convert.
|
|
226
|
+
* @param conversion.rate - The exchange rate for conversion.
|
|
227
|
+
* @param conversion.info - Additional information for the conversion.
|
|
228
|
+
* @param conversion.ckbMinFee - Minimum CKB fee.
|
|
229
|
+
* @param conversion.lock - The script lock for the transaction.
|
|
230
|
+
* @param options - Additional options for the conversion.
|
|
231
|
+
* @returns A promise that resolves to the conversion result or undefined.
|
|
232
|
+
*/
|
|
169
233
|
private async attempt(
|
|
170
234
|
n: number,
|
|
171
235
|
conversion: {
|
|
@@ -180,13 +244,14 @@ export class IckbController {
|
|
|
180
244
|
): ReturnType<IckbController["convert"]> {
|
|
181
245
|
try {
|
|
182
246
|
const { isCkb2Udt, rate, info, ckbMinFee, lock } = conversion;
|
|
183
|
-
const { signer, userCells,
|
|
184
|
-
const { feeRate,
|
|
247
|
+
const { signer, userCells, filters, system } = options;
|
|
248
|
+
const { feeRate, ckbDepositCap, exchangeRatio, depositPool } = system;
|
|
185
249
|
|
|
186
250
|
const tx = SmartTransaction.default();
|
|
187
|
-
const maturities: ccc.Epoch[] = [];
|
|
251
|
+
const maturities: ccc.Epoch[] = [[0n, 1n, 80n]]; // 3 minutes minimum
|
|
188
252
|
let ckbFee = ccc.Zero;
|
|
189
253
|
let amount = conversion.amount;
|
|
254
|
+
let udtWithdrawed = ccc.Zero;
|
|
190
255
|
|
|
191
256
|
// Core protocol
|
|
192
257
|
if (n > 0) {
|
|
@@ -200,7 +265,8 @@ export class IckbController {
|
|
|
200
265
|
} else {
|
|
201
266
|
const myDeposits = depositPool.slice(0, n);
|
|
202
267
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
203
|
-
|
|
268
|
+
udtWithdrawed = myDeposits.slice(-1)[0]!.udtCumulative;
|
|
269
|
+
amount -= udtWithdrawed;
|
|
204
270
|
if (amount < ccc.Zero) {
|
|
205
271
|
// Too many Withdrawal Requests respectfully to the amount
|
|
206
272
|
return undefined;
|
|
@@ -223,14 +289,13 @@ export class IckbController {
|
|
|
223
289
|
: convert(true, amount, exchangeRatio) - convertedAmount;
|
|
224
290
|
|
|
225
291
|
maturities.push(
|
|
226
|
-
|
|
227
|
-
orderMaturityEstimate(isCkb2Udt, amount, system.tip),
|
|
292
|
+
orderMaturityEstimate(isCkb2Udt, amount, udtWithdrawed, system),
|
|
228
293
|
);
|
|
229
|
-
}
|
|
230
294
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
295
|
+
// Check that order provides enough fee to the bot for being matched
|
|
296
|
+
if (ckbFee < ckbMinFee) {
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
234
299
|
}
|
|
235
300
|
|
|
236
301
|
const { receipts, withdrawalGroups, orders, udts, capacities } =
|
|
@@ -262,9 +327,19 @@ export class IckbController {
|
|
|
262
327
|
}
|
|
263
328
|
}
|
|
264
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Retrieves the L1 state based on the provided parameters.
|
|
332
|
+
* @param client - The client to interact with the blockchain.
|
|
333
|
+
* @param filter - The set of filters to apply.
|
|
334
|
+
* @param locks - The script locks to filter the user cells.
|
|
335
|
+
* @param options - Optional parameters for the state retrieval.
|
|
336
|
+
* @param options.minLockUp - The minimum lock-up period (optional).
|
|
337
|
+
* @param options.maxLockUp - The maximum lock-up period (optional).
|
|
338
|
+
* @returns A promise that resolves to an object containing the system state and user cells.
|
|
339
|
+
*/
|
|
265
340
|
async getL1State(
|
|
266
341
|
client: ccc.Client,
|
|
267
|
-
filter: Set<keyof UserCells | "depositPool">,
|
|
342
|
+
filter: Set<keyof UserCells | "depositPool" | "ckbBots">,
|
|
268
343
|
locks: ccc.Script[],
|
|
269
344
|
options?: {
|
|
270
345
|
minLockUp?: ccc.Epoch;
|
|
@@ -287,6 +362,7 @@ export class IckbController {
|
|
|
287
362
|
orders,
|
|
288
363
|
deposits,
|
|
289
364
|
withdrawalRequests,
|
|
365
|
+
botCapacities,
|
|
290
366
|
] = await Promise.all([
|
|
291
367
|
client.getFeeRate(),
|
|
292
368
|
filter.has("depositPool")
|
|
@@ -313,7 +389,9 @@ export class IckbController {
|
|
|
313
389
|
filter.has("withdrawalRequests")
|
|
314
390
|
? collect(this.daoManager.findWithdrawalRequests(client, locks, opts))
|
|
315
391
|
: [],
|
|
316
|
-
|
|
392
|
+
filter.has("ckbBots")
|
|
393
|
+
? collect(CapacityManager.findCapacities(client, locks, opts))
|
|
394
|
+
: [],
|
|
317
395
|
]);
|
|
318
396
|
|
|
319
397
|
// Sort depositPool by maturity
|
|
@@ -339,6 +417,12 @@ export class IckbController {
|
|
|
339
417
|
const exchangeRatio = ickbExchangeRatio(tip);
|
|
340
418
|
const ckbDepositCap = convert(false, ICKB_DEPOSIT_CAP, exchangeRatio);
|
|
341
419
|
|
|
420
|
+
// Calculate the ckb ready to match incoming transactions
|
|
421
|
+
let ckbBots = botCapacities.reduce((acc, c) => acc + c.ckbValue, ccc.Zero);
|
|
422
|
+
// Each bot keeps a reserve of CKB for operations
|
|
423
|
+
ckbBots -= ccc.numFrom(this.bots.length) * ccc.fixedPointFrom("2000");
|
|
424
|
+
ckbBots = ckbBots > ccc.Zero ? ckbBots : ccc.Zero;
|
|
425
|
+
|
|
342
426
|
return {
|
|
343
427
|
system: {
|
|
344
428
|
feeRate,
|
|
@@ -348,6 +432,7 @@ export class IckbController {
|
|
|
348
432
|
udtDepositCap: ICKB_DEPOSIT_CAP,
|
|
349
433
|
depositPool: cumulativeDepositPool,
|
|
350
434
|
orderPool: nonUserOrders,
|
|
435
|
+
ckbBots,
|
|
351
436
|
},
|
|
352
437
|
user: {
|
|
353
438
|
capacities,
|
|
@@ -362,46 +447,127 @@ export class IckbController {
|
|
|
362
447
|
}
|
|
363
448
|
}
|
|
364
449
|
|
|
450
|
+
/**
|
|
451
|
+
* Represents the state of the system.
|
|
452
|
+
*/
|
|
365
453
|
export interface SystemState {
|
|
454
|
+
/** The fee rate for transactions. */
|
|
366
455
|
feeRate: ccc.Num;
|
|
456
|
+
|
|
457
|
+
/** The tip for the current block header. */
|
|
367
458
|
tip: ccc.ClientBlockHeader;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
459
|
+
|
|
460
|
+
/** The exchange ratio between CKB and UDT. */
|
|
461
|
+
exchangeRatio: ExchangeRatio;
|
|
462
|
+
|
|
463
|
+
/** The deposit cap expressed in CKB. */
|
|
372
464
|
ckbDepositCap: ccc.FixedPoint;
|
|
465
|
+
|
|
466
|
+
/** The deposit cap expressed in iCKB. */
|
|
373
467
|
udtDepositCap: ccc.FixedPoint;
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* The deposit pool containing iCKB deposit cells with cumulative iCKB amounts.
|
|
471
|
+
*/
|
|
374
472
|
depositPool: (IckbDepositCell & { udtCumulative: bigint })[];
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* The order pool containing non-user order cells.
|
|
476
|
+
*/
|
|
375
477
|
orderPool: OrderCell[];
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* The ckb held by bots ready to match incoming iCKB to CKB conversions.
|
|
481
|
+
*/
|
|
482
|
+
ckbBots: ccc.FixedPoint;
|
|
376
483
|
}
|
|
377
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Represents the user cells in the system.
|
|
487
|
+
*/
|
|
378
488
|
export interface UserCells {
|
|
489
|
+
/** The capacities owned by the user. */
|
|
379
490
|
capacities: CapacityCell[];
|
|
491
|
+
|
|
492
|
+
/** The UDTs owned by the user. */
|
|
380
493
|
udts: UdtCell[];
|
|
494
|
+
|
|
495
|
+
/** The receipts associated with the user's transactions. */
|
|
381
496
|
receipts: ReceiptCell[];
|
|
497
|
+
|
|
498
|
+
/** The withdrawal groups for the user. */
|
|
382
499
|
withdrawalGroups: WithdrawalGroup[];
|
|
500
|
+
|
|
501
|
+
/** The orders placed by the user. */
|
|
383
502
|
orders: OrderGroup[];
|
|
503
|
+
|
|
504
|
+
/** The classical/non-iCKB deposits made by the user. */
|
|
384
505
|
deposits: DaoCell[];
|
|
506
|
+
|
|
507
|
+
/** The classical/non-iCKB withdrawal requests made by the user. */
|
|
385
508
|
withdrawalRequests: DaoCell[];
|
|
386
509
|
}
|
|
387
510
|
|
|
511
|
+
/**
|
|
512
|
+
* Represents a conversion transaction.
|
|
513
|
+
*/
|
|
388
514
|
export interface Conversion {
|
|
515
|
+
/** The smart transaction associated with the conversion. */
|
|
389
516
|
tx: SmartTransaction;
|
|
517
|
+
|
|
518
|
+
/** The fee in CKB for the order created by the conversion. */
|
|
390
519
|
ckbFee: ccc.FixedPoint;
|
|
520
|
+
|
|
521
|
+
/** The estimated maturity epoch for conversion. */
|
|
391
522
|
maturity: ccc.Epoch;
|
|
392
523
|
}
|
|
393
524
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
525
|
+
/**
|
|
526
|
+
* Estimates the maturity of an order based on the type of conversion and amount.
|
|
527
|
+
*
|
|
528
|
+
* @param isCkb2Udt - A boolean indicating if the order is from CKB to UDT.
|
|
529
|
+
* @param amount - The amount of CKB or UDT involved in the order.
|
|
530
|
+
* @param udtWithdrawed - The amount of UDT that has been withdrawn by the current conversion via core.
|
|
531
|
+
* @param system - The current system state, which includes the block header tip, order pool, deposit pool, CKB bots, and exchange ratio.
|
|
532
|
+
*
|
|
533
|
+
* @returns The estimated maturity epoch for the order.
|
|
534
|
+
*/
|
|
397
535
|
function orderMaturityEstimate(
|
|
398
536
|
isCkb2Udt: boolean,
|
|
399
537
|
amount: bigint,
|
|
400
|
-
|
|
538
|
+
udtWithdrawed: ccc.FixedPoint,
|
|
539
|
+
system: SystemState,
|
|
401
540
|
): ccc.Epoch {
|
|
402
|
-
|
|
541
|
+
const { tip, orderPool, depositPool, ckbBots, exchangeRatio } = system;
|
|
542
|
+
|
|
543
|
+
// Maturity estimate a priori, the estimation is based on:
|
|
544
|
+
// - CKB to iCKB orders at 100k CKB every minute
|
|
545
|
+
// - iCKB to CKB orders at 200 CKB every minute
|
|
546
|
+
let maturity = epochAdd(tip.epoch, [
|
|
403
547
|
0n,
|
|
404
548
|
1n + amount / ccc.fixedPointFrom(isCkb2Udt ? 100000 : 200),
|
|
405
549
|
4n * 60n,
|
|
406
550
|
]);
|
|
551
|
+
|
|
552
|
+
if (isCkb2Udt) {
|
|
553
|
+
return maturity;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (depositPool.length > 0) {
|
|
557
|
+
const udtWaiting = orderPool
|
|
558
|
+
.filter((o) => o.isUdt2CkbMatchable())
|
|
559
|
+
.reduce((acc, o) => acc + o.udtValue, ccc.Zero);
|
|
560
|
+
const udtAvailable = convert(isCkb2Udt, ckbBots, exchangeRatio);
|
|
561
|
+
|
|
562
|
+
const udtToConvert = amount + udtWithdrawed + udtWaiting - udtAvailable;
|
|
563
|
+
const i = binarySearch(
|
|
564
|
+
depositPool.length,
|
|
565
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
566
|
+
(n) => depositPool[n]!.udtCumulative >= udtToConvert,
|
|
567
|
+
);
|
|
568
|
+
|
|
569
|
+
maturity = depositPool[i]?.maturity ?? maturity;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return maturity;
|
|
407
573
|
}
|