@ickb/sdk 1000.0.82 → 9001.0.0
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/README.md +84 -32
- package/dist/constants.d.ts +9 -22
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +62 -76
- package/dist/constants.js.map +1 -1
- package/dist/conversion/estimate.d.ts +33 -0
- package/dist/conversion/estimate.d.ts.map +1 -0
- package/dist/conversion/estimate.js +117 -0
- package/dist/conversion/estimate.js.map +1 -0
- package/dist/conversion/maturity.d.ts +15 -0
- package/dist/conversion/maturity.d.ts.map +1 -0
- package/dist/conversion/maturity.js +113 -0
- package/dist/conversion/maturity.js.map +1 -0
- package/dist/conversion/plans.d.ts +20 -0
- package/dist/conversion/plans.d.ts.map +1 -0
- package/dist/conversion/plans.js +106 -0
- package/dist/conversion/plans.js.map +1 -0
- package/dist/conversion/projection.d.ts +21 -0
- package/dist/conversion/projection.d.ts.map +1 -0
- package/dist/conversion/projection.js +94 -0
- package/dist/conversion/projection.js.map +1 -0
- package/dist/conversion/types.d.ts +264 -0
- package/dist/conversion/types.d.ts.map +1 -0
- package/dist/conversion/types.js +2 -0
- package/dist/conversion/types.js.map +1 -0
- package/dist/conversion/withdrawal_ring.d.ts +34 -0
- package/dist/conversion/withdrawal_ring.d.ts.map +1 -0
- package/dist/conversion/withdrawal_ring.js +87 -0
- package/dist/conversion/withdrawal_ring.js.map +1 -0
- package/dist/dao.d.ts +100 -0
- package/dist/dao.d.ts.map +1 -0
- package/dist/dao.js +125 -0
- package/dist/dao.js.map +1 -0
- package/dist/index.d.ts +49 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -3
- package/dist/index.js.map +1 -1
- package/dist/logic.d.ts +81 -0
- package/dist/logic.d.ts.map +1 -0
- package/dist/logic.js +173 -0
- package/dist/logic.js.map +1 -0
- package/dist/order/cells.d.ts +168 -0
- package/dist/order/cells.d.ts.map +1 -0
- package/dist/order/cells.js +309 -0
- package/dist/order/cells.js.map +1 -0
- package/dist/order/conversion.d.ts +37 -0
- package/dist/order/conversion.d.ts.map +1 -0
- package/dist/order/conversion.js +120 -0
- package/dist/order/conversion.js.map +1 -0
- package/dist/order/fee.d.ts +9 -0
- package/dist/order/fee.d.ts.map +1 -0
- package/dist/order/fee.js +24 -0
- package/dist/order/fee.js.map +1 -0
- package/dist/order/fill.d.ts +36 -0
- package/dist/order/fill.d.ts.map +1 -0
- package/dist/order/fill.js +53 -0
- package/dist/order/fill.js.map +1 -0
- package/dist/order/info.d.ts +62 -0
- package/dist/order/info.d.ts.map +1 -0
- package/dist/order/info.js +102 -0
- package/dist/order/info.js.map +1 -0
- package/dist/order/master.d.ts +49 -0
- package/dist/order/master.d.ts.map +1 -0
- package/dist/order/master.js +27 -0
- package/dist/order/master.js.map +1 -0
- package/dist/order/matcher.d.ts +43 -0
- package/dist/order/matcher.d.ts.map +1 -0
- package/dist/order/matcher.js +124 -0
- package/dist/order/matcher.js.map +1 -0
- package/dist/order/order.d.ts +63 -0
- package/dist/order/order.d.ts.map +1 -0
- package/dist/order/order.js +234 -0
- package/dist/order/order.js.map +1 -0
- package/dist/order/order_data.d.ts +51 -0
- package/dist/order/order_data.d.ts.map +1 -0
- package/dist/order/order_data.js +67 -0
- package/dist/order/order_data.js.map +1 -0
- package/dist/order/ratio.d.ts +40 -0
- package/dist/order/ratio.d.ts.map +1 -0
- package/dist/order/ratio.js +74 -0
- package/dist/order/ratio.js.map +1 -0
- package/dist/order/relative.d.ts +43 -0
- package/dist/order/relative.d.ts.map +1 -0
- package/dist/order/relative.js +57 -0
- package/dist/order/relative.js.map +1 -0
- package/dist/owned_owner.d.ts +108 -0
- package/dist/owned_owner.d.ts.map +1 -0
- package/dist/owned_owner.js +260 -0
- package/dist/owned_owner.js.map +1 -0
- package/dist/sdk.d.ts +113 -41
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +410 -209
- package/dist/sdk.js.map +1 -1
- package/dist/send/sign_and_send_transaction.d.ts +61 -0
- package/dist/send/sign_and_send_transaction.d.ts.map +1 -0
- package/dist/send/sign_and_send_transaction.js +201 -0
- package/dist/send/sign_and_send_transaction.js.map +1 -0
- package/dist/send/wait_transaction.d.ts +42 -0
- package/dist/send/wait_transaction.d.ts.map +1 -0
- package/dist/send/wait_transaction.js +172 -0
- package/dist/send/wait_transaction.js.map +1 -0
- package/dist/udt.d.ts +108 -0
- package/dist/udt.d.ts.map +1 -0
- package/dist/udt.js +180 -0
- package/dist/udt.js.map +1 -0
- package/dist/utils/chain.d.ts +3 -0
- package/dist/utils/chain.d.ts.map +1 -0
- package/dist/utils/chain.js +2 -0
- package/dist/utils/chain.js.map +1 -0
- package/dist/utils/codec.d.ts +19 -0
- package/dist/utils/codec.d.ts.map +1 -0
- package/dist/utils/codec.js +69 -0
- package/dist/utils/codec.js.map +1 -0
- package/dist/utils/utils.d.ts +99 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +130 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/utils/verified_client.d.ts +19 -0
- package/dist/utils/verified_client.d.ts.map +1 -0
- package/dist/utils/verified_client.js +92 -0
- package/dist/utils/verified_client.js.map +1 -0
- package/package.json +19 -26
- package/src/constants.ts +65 -181
- package/src/conversion/estimate.ts +155 -0
- package/src/conversion/maturity.ts +158 -0
- package/src/conversion/plans.ts +144 -0
- package/src/conversion/projection.ts +136 -0
- package/src/conversion/types.ts +302 -0
- package/src/conversion/withdrawal_ring.ts +122 -0
- package/src/dao.ts +196 -0
- package/src/index.ts +89 -3
- package/src/logic.ts +283 -0
- package/src/order/cells.ts +383 -0
- package/src/order/conversion.ts +162 -0
- package/src/order/fee.ts +30 -0
- package/src/order/fill.ts +83 -0
- package/src/order/info.ts +181 -0
- package/src/order/master.ts +42 -0
- package/src/order/matcher.ts +191 -0
- package/src/order/order.ts +288 -0
- package/src/order/order_data.ts +131 -0
- package/src/order/ratio.ts +127 -0
- package/src/order/relative.ts +109 -0
- package/src/owned_owner.ts +364 -0
- package/src/sdk.ts +542 -440
- package/src/send/sign_and_send_transaction.ts +256 -0
- package/src/send/wait_transaction.ts +227 -0
- package/src/udt.ts +249 -0
- package/src/utils/chain.ts +2 -0
- package/src/utils/codec.ts +78 -0
- package/src/utils/utils.ts +208 -0
- package/src/utils/verified_client.ts +136 -0
- package/dist/codec.d.ts +0 -3
- package/dist/codec.d.ts.map +0 -1
- package/dist/codec.js +0 -58
- package/dist/codec.js.map +0 -1
- package/src/codec.ts +0 -138
package/src/index.ts
CHANGED
|
@@ -1,3 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Public SDK for one iCKB conversion workflow: read the sampled state, quote, build and
|
|
3
|
+
* complete a conversion, sign, send, and wait.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ccc } from "@ckb-ccc/core";
|
|
9
|
+
import type {
|
|
10
|
+
AccountState,
|
|
11
|
+
ConversionTransactionOptions,
|
|
12
|
+
ConversionTransactionResult,
|
|
13
|
+
SystemState,
|
|
14
|
+
} from "./conversion/types.ts";
|
|
15
|
+
import type { LockUpPolicy } from "./dao.ts";
|
|
16
|
+
import type { OrderGroup } from "./order/cells.ts";
|
|
17
|
+
import { IckbSdk as IckbSdkClass } from "./sdk.ts";
|
|
18
|
+
import type { SupportedChain } from "./utils/chain.ts";
|
|
19
|
+
|
|
20
|
+
/** The SDK an integrator drives: the state read and the conversion builder. */
|
|
21
|
+
export interface IckbSdk {
|
|
22
|
+
/** Builds and completes a conversion, or returns a typed planning failure. */
|
|
23
|
+
buildConversionTransaction: (
|
|
24
|
+
options: ConversionTransactionOptions,
|
|
25
|
+
) => Promise<ConversionTransactionResult>;
|
|
26
|
+
/** Reads system, user-order, and account state at the sampled tip's parent, under one timing policy. */
|
|
27
|
+
getL1AccountState: (
|
|
28
|
+
client: ccc.Client,
|
|
29
|
+
locks: ccc.Script[],
|
|
30
|
+
lockUp: LockUpPolicy,
|
|
31
|
+
maxFeeRate?: ccc.NumLike,
|
|
32
|
+
) => Promise<{
|
|
33
|
+
system: SystemState;
|
|
34
|
+
userOrders: OrderGroup[];
|
|
35
|
+
account: AccountState;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Creates the SDK for one chain's deployment. */
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-redeclare -- The public type and the constructor namespace intentionally share a name.
|
|
41
|
+
export const IckbSdk: { fromChain: (chain: SupportedChain) => IckbSdk } = IckbSdkClass;
|
|
42
|
+
|
|
43
|
+
export { DEFAULT_ORDER_FEE, DEFAULT_ORDER_FEE_BASE } from "./conversion/estimate.ts";
|
|
44
|
+
export { projectConversionTransactionContext } from "./conversion/projection.ts";
|
|
45
|
+
export type {
|
|
46
|
+
AccountAvailabilityProjection,
|
|
47
|
+
AccountState,
|
|
48
|
+
ConversionDirection,
|
|
49
|
+
ConversionKind,
|
|
50
|
+
ConversionNotice,
|
|
51
|
+
ConversionTransactionContext,
|
|
52
|
+
ConversionTransactionContextProjection,
|
|
53
|
+
ConversionTransactionFailureReason,
|
|
54
|
+
ConversionTransactionOptions,
|
|
55
|
+
ConversionTransactionResult,
|
|
56
|
+
SystemState,
|
|
57
|
+
} from "./conversion/types.ts";
|
|
58
|
+
export { WALLET_LOCK_UP } from "./dao.ts";
|
|
59
|
+
export type { BroadcastDeadline, LockUpPolicy } from "./dao.ts";
|
|
60
|
+
export type { IckbDepositCell, ReceiptCell } from "./logic.ts";
|
|
61
|
+
export type { MasterCell, OrderCell, OrderGroup } from "./order/cells.ts";
|
|
62
|
+
export {
|
|
63
|
+
OrderConversionRepresentabilityError,
|
|
64
|
+
quoteConversion,
|
|
65
|
+
} from "./order/conversion.ts";
|
|
66
|
+
export type { Info, InfoLike } from "./order/info.ts";
|
|
67
|
+
export type { Master, MasterLike } from "./order/master.ts";
|
|
68
|
+
export type { OrderData, OrderDataLike } from "./order/order_data.ts";
|
|
69
|
+
export { Ratio } from "./order/ratio.ts";
|
|
70
|
+
export type { Relative, RelativeLike } from "./order/relative.ts";
|
|
71
|
+
export type {
|
|
72
|
+
DaoWithdrawalRequestCell,
|
|
73
|
+
OwnerCell,
|
|
74
|
+
WithdrawalGroup,
|
|
75
|
+
} from "./owned_owner.ts";
|
|
76
|
+
export { IckbError } from "./sdk.ts";
|
|
77
|
+
export type { IckbErrorCode } from "./sdk.ts";
|
|
78
|
+
export {
|
|
79
|
+
signAndSendTransaction,
|
|
80
|
+
signerAccountLocks,
|
|
81
|
+
TransactionBroadcastError,
|
|
82
|
+
TransactionExpiredError,
|
|
83
|
+
} from "./send/sign_and_send_transaction.ts";
|
|
84
|
+
export { TransactionWaitError, waitTransaction } from "./send/wait_transaction.ts";
|
|
85
|
+
export type { WaitTransactionOptions } from "./send/wait_transaction.ts";
|
|
86
|
+
export { ickbExchangeRatio } from "./udt.ts";
|
|
87
|
+
export type { SupportedChain } from "./utils/chain.ts";
|
|
88
|
+
export { clientCache } from "./utils/utils.ts";
|
|
89
|
+
export type { ExchangeRatio, ValueComponents } from "./utils/utils.ts";
|
package/src/logic.ts
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { ccc } from "@ckb-ccc/core";
|
|
2
|
+
import {
|
|
3
|
+
assertDaoOutputLimit,
|
|
4
|
+
DAO_DEPOSIT_DATA,
|
|
5
|
+
DaoOutputLimitError,
|
|
6
|
+
depositMaturity,
|
|
7
|
+
isDaoDeposit,
|
|
8
|
+
pushHeaderDep,
|
|
9
|
+
type LockUpPolicy,
|
|
10
|
+
} from "./dao.ts";
|
|
11
|
+
import {
|
|
12
|
+
decodeReceiptData,
|
|
13
|
+
encodeReceiptData,
|
|
14
|
+
IckbUdt,
|
|
15
|
+
ickbValue,
|
|
16
|
+
receiptDataBytes,
|
|
17
|
+
type ReceiptData,
|
|
18
|
+
} from "./udt.ts";
|
|
19
|
+
import {
|
|
20
|
+
findCells,
|
|
21
|
+
headersByNumber,
|
|
22
|
+
type ScannedCell,
|
|
23
|
+
type ScriptDeps,
|
|
24
|
+
type ValueComponents,
|
|
25
|
+
} from "./utils/utils.ts";
|
|
26
|
+
|
|
27
|
+
const maxDepositQuantity = 63;
|
|
28
|
+
// Receipts must carry enough capacity for phase 2 when the wallet has no other
|
|
29
|
+
// CKB: one iCKB xUDT cell, one plain capacity cell, and the fee reserve.
|
|
30
|
+
const phase2TxFeeReserve = ccc.One;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A live iCKB deposit: a DAO deposit cell locked by the iCKB Logic script, valued at its
|
|
34
|
+
* deposit header.
|
|
35
|
+
*/
|
|
36
|
+
export interface IckbDepositCell extends ValueComponents {
|
|
37
|
+
/** The DAO deposit cell. */
|
|
38
|
+
cell: ccc.Cell;
|
|
39
|
+
/** The header of the block that committed the deposit, which values it. */
|
|
40
|
+
header: ccc.ClientBlockHeader;
|
|
41
|
+
/**
|
|
42
|
+
* The DAO claim epoch as sampled at the tip, not rolled: each reader judges it against
|
|
43
|
+
* its own {@link LockUpPolicy} with `depositMaturity`.
|
|
44
|
+
*/
|
|
45
|
+
claimEpoch: ccc.Epoch;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Represents a receipt cell containing the receipt for iCKB Deposits.
|
|
50
|
+
*/
|
|
51
|
+
export interface ReceiptCell extends ValueComponents {
|
|
52
|
+
/** The cell associated with the receipt. */
|
|
53
|
+
cell: ccc.Cell;
|
|
54
|
+
/** The header of the block that committed the deposits, which values them. */
|
|
55
|
+
header: ccc.ClientBlockHeader;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Manages logic related to deposits and receipts in the blockchain.
|
|
60
|
+
*/
|
|
61
|
+
export class LogicManager implements ScriptDeps {
|
|
62
|
+
/** The iCKB Logic script used as receipt type and DAO deposit lock. */
|
|
63
|
+
public readonly script: ccc.Script;
|
|
64
|
+
|
|
65
|
+
/** Cell dependencies required to execute the iCKB Logic script. */
|
|
66
|
+
public readonly cellDeps: ccc.CellDep[];
|
|
67
|
+
|
|
68
|
+
/** The Nervos DAO script the deposits carry, with its cell deps. */
|
|
69
|
+
public readonly dao: ScriptDeps;
|
|
70
|
+
|
|
71
|
+
/** Creates the manager for one iCKB Logic deployment over one DAO deployment. */
|
|
72
|
+
constructor(script: ccc.Script, cellDeps: ccc.CellDep[], dao: ScriptDeps) {
|
|
73
|
+
this.script = script;
|
|
74
|
+
this.cellDeps = cellDeps;
|
|
75
|
+
this.dao = dao;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Whether the cell is an iCKB receipt: typed by the logic script with a decodable prefix. */
|
|
79
|
+
public isReceipt(cell: ccc.Cell): boolean {
|
|
80
|
+
return (
|
|
81
|
+
cell.cellOutput.type?.eq(this.script) === true &&
|
|
82
|
+
ccc.bytesFrom(cell.outputData).length >= receiptDataBytes
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Whether the cell is a DAO deposit locked by the logic script. */
|
|
87
|
+
public isDeposit(cell: ccc.Cell): boolean {
|
|
88
|
+
return isDaoDeposit(cell, this.dao.script) && cell.cellOutput.lock.eq(this.script);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Adds `depositQuantity` DAO deposits of `depositCapacity` locked by the logic script,
|
|
93
|
+
* then the receipt that mints their iCKB in phase 2, locked by `lock`.
|
|
94
|
+
*
|
|
95
|
+
* @remarks Completion (`IckbSdk.completeTransaction`) adds the dep group that also
|
|
96
|
+
* resolves the xUDT script.
|
|
97
|
+
*/
|
|
98
|
+
public deposit(
|
|
99
|
+
txLike: ccc.TransactionLike,
|
|
100
|
+
depositQuantity: number,
|
|
101
|
+
depositCapacity: ccc.FixedPoint,
|
|
102
|
+
lock: ccc.Script,
|
|
103
|
+
): ccc.Transaction {
|
|
104
|
+
// A zero quantity would mint a receipt for no deposits, which iCKB Logic refuses on chain.
|
|
105
|
+
if (!Number.isSafeInteger(depositQuantity) || depositQuantity <= 0) {
|
|
106
|
+
throw new TypeError("iCKB deposit quantity must be a positive safe integer");
|
|
107
|
+
}
|
|
108
|
+
const tx = ccc.Transaction.from(txLike);
|
|
109
|
+
if (depositQuantity > maxDepositQuantity) {
|
|
110
|
+
// The completion walk steps a plan down on this error.
|
|
111
|
+
throw new DaoOutputLimitError(tx.outputs.length + depositQuantity + 1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const depositCell = ccc.Cell.from({
|
|
115
|
+
previousOutput: { txHash: `0x${"00".repeat(32)}`, index: 0 },
|
|
116
|
+
cellOutput: { capacity: depositCapacity, lock: this.script, type: this.dao.script },
|
|
117
|
+
outputData: DAO_DEPOSIT_DATA,
|
|
118
|
+
});
|
|
119
|
+
const depositAmount = depositCell.capacityFree;
|
|
120
|
+
if (depositAmount < ccc.fixedPointFrom(1000)) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
"iCKB deposit minimum is 1000 CKB free capacity (1082 CKB total capacity)",
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
if (depositAmount > ccc.fixedPointFrom(1000000)) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
"iCKB deposit maximum is 1000000 CKB free capacity (1000082 CKB total capacity)",
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
tx.addCellDeps(this.cellDeps);
|
|
132
|
+
tx.addCellDeps(this.dao.cellDeps);
|
|
133
|
+
for (let i = 0; i < depositQuantity; i += 1) {
|
|
134
|
+
tx.addOutput(depositCell.cellOutput, depositCell.outputData);
|
|
135
|
+
}
|
|
136
|
+
// Receipts track the deposit's free capacity, not the full DAO cell capacity.
|
|
137
|
+
tx.addOutput(
|
|
138
|
+
{ capacity: receiptPhase2Capacity(lock), lock, type: this.script },
|
|
139
|
+
encodeReceiptData({ depositQuantity: BigInt(depositQuantity), depositAmount }),
|
|
140
|
+
);
|
|
141
|
+
assertDaoOutputLimit(tx, this.dao.script);
|
|
142
|
+
return tx;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Adds receipt inputs and their deposit header deps for iCKB deposit completion.
|
|
147
|
+
*
|
|
148
|
+
* @remarks This prepares the phase-2 inputs; the iCKB they mint is completed by
|
|
149
|
+
* `IckbSdk.completeTransaction`.
|
|
150
|
+
*/
|
|
151
|
+
public completeDeposit(
|
|
152
|
+
txLike: ccc.TransactionLike,
|
|
153
|
+
receipts: ReceiptCell[],
|
|
154
|
+
): ccc.Transaction {
|
|
155
|
+
const tx = ccc.Transaction.from(txLike);
|
|
156
|
+
if (receipts.length === 0) {
|
|
157
|
+
return tx;
|
|
158
|
+
}
|
|
159
|
+
for (const receipt of receipts) {
|
|
160
|
+
const outPoint = receipt.cell.outPoint.toHex();
|
|
161
|
+
if (!this.isReceipt(receipt.cell)) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`Receipt ${outPoint} is not an iCKB receipt for this logic script`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
tx.addCellDeps(this.cellDeps);
|
|
168
|
+
for (const receipt of receipts) {
|
|
169
|
+
pushHeaderDep(tx, receipt.header.hash);
|
|
170
|
+
tx.addInput(receipt.cell);
|
|
171
|
+
}
|
|
172
|
+
return tx;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The receipts among `cells`, valued at their deposit headers, each header read once.
|
|
177
|
+
*/
|
|
178
|
+
public async receiptsFrom(
|
|
179
|
+
client: ccc.Client,
|
|
180
|
+
cells: readonly ScannedCell[],
|
|
181
|
+
): Promise<ReceiptCell[]> {
|
|
182
|
+
const receipts = cells.filter(({ cell }) => this.isReceipt(cell));
|
|
183
|
+
const headers = await headersByNumber(
|
|
184
|
+
client,
|
|
185
|
+
receipts.map(({ blockNumber }) => blockNumber),
|
|
186
|
+
);
|
|
187
|
+
return receipts.map(({ cell, blockNumber }) =>
|
|
188
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- every receipt's block was read above.
|
|
189
|
+
receiptCell(cell, headers.get(blockNumber)!),
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Every live iCKB deposit, valued at its deposit header, with its claim epoch at the tip;
|
|
195
|
+
* each deposit block's header is read once.
|
|
196
|
+
*/
|
|
197
|
+
public async findDeposits(
|
|
198
|
+
client: ccc.Client,
|
|
199
|
+
tip: ccc.ClientBlockHeader,
|
|
200
|
+
): Promise<IckbDepositCell[]> {
|
|
201
|
+
const cells = (
|
|
202
|
+
await findCells(client, {
|
|
203
|
+
script: this.script,
|
|
204
|
+
scriptType: "lock",
|
|
205
|
+
filter: {
|
|
206
|
+
script: this.dao.script,
|
|
207
|
+
outputData: DAO_DEPOSIT_DATA,
|
|
208
|
+
outputDataSearchMode: "exact",
|
|
209
|
+
},
|
|
210
|
+
scriptSearchMode: "exact",
|
|
211
|
+
withData: true,
|
|
212
|
+
})
|
|
213
|
+
).filter(({ cell }) => this.isDeposit(cell));
|
|
214
|
+
const headers = await headersByNumber(
|
|
215
|
+
client,
|
|
216
|
+
cells.map(({ blockNumber }) => blockNumber),
|
|
217
|
+
);
|
|
218
|
+
return cells.map(({ cell, blockNumber }) =>
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- every deposit's block was read above.
|
|
220
|
+
ickbDepositCell(cell, headers.get(blockNumber)!, tip),
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Values a DAO deposit cell at its deposit header and samples its claim epoch at the tip. */
|
|
226
|
+
function ickbDepositCell(
|
|
227
|
+
cell: ccc.Cell,
|
|
228
|
+
header: ccc.ClientBlockHeader,
|
|
229
|
+
tip: ccc.ClientBlockHeader,
|
|
230
|
+
): IckbDepositCell {
|
|
231
|
+
const interests = ccc.calcDaoProfit(cell.capacityFree, header, tip);
|
|
232
|
+
return {
|
|
233
|
+
cell,
|
|
234
|
+
header,
|
|
235
|
+
claimEpoch: ccc.calcDaoClaimEpoch(header, tip),
|
|
236
|
+
ckbValue: cell.cellOutput.capacity + interests,
|
|
237
|
+
udtValue: ickbValue(cell.capacityFree, header),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** The deposits a withdrawal request made now may claim at their sampled dates under the policy. */
|
|
242
|
+
export function readyDeposits(
|
|
243
|
+
deposits: readonly IckbDepositCell[],
|
|
244
|
+
tip: ccc.ClientBlockHeader,
|
|
245
|
+
policy: LockUpPolicy,
|
|
246
|
+
): IckbDepositCell[] {
|
|
247
|
+
return deposits.filter(
|
|
248
|
+
(deposit) => depositMaturity(deposit.claimEpoch, tip, policy).isReady,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Decodes a receipt cell and values it at its deposit header. */
|
|
253
|
+
export function receiptCell(cell: ccc.Cell, header: ccc.ClientBlockHeader): ReceiptCell {
|
|
254
|
+
let receipt: ReceiptData;
|
|
255
|
+
try {
|
|
256
|
+
receipt = decodeReceiptData(cell.outputData);
|
|
257
|
+
} catch (error) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`Invalid iCKB receipt payload at ${cell.outPoint.toHex()}: ${cell.outputData}`,
|
|
260
|
+
{ cause: error },
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
cell,
|
|
265
|
+
header,
|
|
266
|
+
ckbValue: cell.cellOutput.capacity,
|
|
267
|
+
udtValue: ickbValue(receipt.depositAmount, header) * receipt.depositQuantity,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Returns the CKB needed for the two phase-2 outputs created by one receipt.
|
|
273
|
+
*
|
|
274
|
+
* @remarks The value is sized with the actual user lock because lock args affect
|
|
275
|
+
* occupied capacity. It includes one plain output, one xUDT output, and the
|
|
276
|
+
* phase-2 fee reserve.
|
|
277
|
+
*/
|
|
278
|
+
export function receiptPhase2Capacity(lock: ccc.Script): ccc.FixedPoint {
|
|
279
|
+
// Capacity is measured with the actual user lock. Lock args are wallet-specific
|
|
280
|
+
// and can make both phase-2 outputs larger than protocol-only examples.
|
|
281
|
+
const plainCellCapacity = BigInt(8 + lock.occupiedSize) * ccc.One;
|
|
282
|
+
return plainCellCapacity + IckbUdt.minimumXudtCellCapacity(lock) + phase2TxFeeReserve;
|
|
283
|
+
}
|