@ckb-ccc/core 1.5.3 → 1.7.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/CHANGELOG.md +61 -7
- package/dist/ckb/script.d.ts +2 -1
- package/dist/ckb/script.d.ts.map +1 -1
- package/dist/ckb/transaction.d.ts +125 -7
- package/dist/ckb/transaction.d.ts.map +1 -1
- package/dist/ckb/transaction.js +263 -73
- package/dist/client/cache/cache.d.ts +67 -11
- package/dist/client/cache/cache.d.ts.map +1 -1
- package/dist/client/cache/cache.js +94 -9
- package/dist/client/cache/memory.advanced.d.ts +2 -2
- package/dist/client/cache/memory.advanced.d.ts.map +1 -1
- package/dist/client/cache/memory.advanced.js +19 -7
- package/dist/client/cache/memory.d.ts +24 -7
- package/dist/client/cache/memory.d.ts.map +1 -1
- package/dist/client/cache/memory.js +76 -18
- package/dist/client/client.d.ts +30 -7
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +114 -22
- package/dist/client/clientPublicMainnet.advanced.d.ts +2 -1
- package/dist/client/clientPublicMainnet.advanced.d.ts.map +1 -1
- package/dist/client/clientPublicMainnet.advanced.js +1 -1
- package/dist/client/clientPublicMainnet.d.ts +2 -1
- package/dist/client/clientPublicMainnet.d.ts.map +1 -1
- package/dist/client/clientPublicMainnet.js +1 -6
- package/dist/client/clientPublicTestnet.advanced.d.ts +2 -1
- package/dist/client/clientPublicTestnet.advanced.d.ts.map +1 -1
- package/dist/client/clientPublicTestnet.advanced.js +1 -1
- package/dist/client/clientPublicTestnet.d.ts +2 -1
- package/dist/client/clientPublicTestnet.d.ts.map +1 -1
- package/dist/client/clientTypes.advanced.d.ts +3 -0
- package/dist/client/clientTypes.advanced.d.ts.map +1 -1
- package/dist/client/clientTypes.advanced.js +3 -0
- package/dist/client/clientTypes.d.ts +110 -38
- package/dist/client/clientTypes.d.ts.map +1 -1
- package/dist/client/clientTypes.js +118 -31
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/jsonRpc/client.d.ts +4 -4
- package/dist/client/jsonRpc/client.d.ts.map +1 -1
- package/dist/client/jsonRpc/client.js +4 -4
- package/dist/client/jsonRpc/transformers.js +3 -3
- package/dist/client/knownScript.d.ts +26 -0
- package/dist/client/knownScript.d.ts.map +1 -0
- package/dist/client/knownScript.js +27 -0
- package/dist/jsonRpc/transports/webSocket.d.ts.map +1 -1
- package/dist/jsonRpc/transports/webSocket.js +7 -3
- package/dist/molecule/predefined.d.ts +10 -10
- package/dist/molecule/predefined.d.ts.map +1 -1
- package/dist/num/index.d.ts.map +1 -1
- package/dist/num/index.js +17 -1
- package/dist/signer/ckb/signerCkbPublicKey.d.ts.map +1 -1
- package/dist/signer/ckb/signerCkbPublicKey.js +1 -5
- package/dist/signer/nostr/index.d.ts +1 -0
- package/dist/signer/nostr/index.d.ts.map +1 -1
- package/dist/signer/nostr/index.js +1 -0
- package/dist/signer/nostr/signerNostr.d.ts +1 -1
- package/dist/signer/nostr/signerNostr.d.ts.map +1 -1
- package/dist/signer/nostr/signerNostr.js +8 -0
- package/dist/signer/nostr/signerNostrPrivateKey.d.ts +5 -7
- package/dist/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
- package/dist/signer/nostr/signerNostrPrivateKey.js +6 -12
- package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts +11 -0
- package/dist/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -0
- package/dist/signer/nostr/signerNostrPublicKeyReadonly.js +22 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +13 -1
- package/dist.commonjs/advanced.js +17 -7
- package/dist.commonjs/ckb/script.d.ts +2 -1
- package/dist.commonjs/ckb/script.d.ts.map +1 -1
- package/dist.commonjs/ckb/transaction.d.ts +125 -7
- package/dist.commonjs/ckb/transaction.d.ts.map +1 -1
- package/dist.commonjs/ckb/transaction.js +352 -160
- package/dist.commonjs/client/cache/cache.d.ts +67 -11
- package/dist.commonjs/client/cache/cache.d.ts.map +1 -1
- package/dist.commonjs/client/cache/cache.js +94 -9
- package/dist.commonjs/client/cache/memory.advanced.d.ts +2 -2
- package/dist.commonjs/client/cache/memory.advanced.d.ts.map +1 -1
- package/dist.commonjs/client/cache/memory.advanced.js +19 -7
- package/dist.commonjs/client/cache/memory.d.ts +24 -7
- package/dist.commonjs/client/cache/memory.d.ts.map +1 -1
- package/dist.commonjs/client/cache/memory.js +75 -17
- package/dist.commonjs/client/client.d.ts +30 -7
- package/dist.commonjs/client/client.d.ts.map +1 -1
- package/dist.commonjs/client/client.js +112 -20
- package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts +2 -1
- package/dist.commonjs/client/clientPublicMainnet.advanced.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicMainnet.advanced.js +21 -21
- package/dist.commonjs/client/clientPublicMainnet.d.ts +2 -1
- package/dist.commonjs/client/clientPublicMainnet.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicMainnet.js +1 -6
- package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts +2 -1
- package/dist.commonjs/client/clientPublicTestnet.advanced.d.ts.map +1 -1
- package/dist.commonjs/client/clientPublicTestnet.advanced.js +21 -21
- package/dist.commonjs/client/clientPublicTestnet.d.ts +2 -1
- package/dist.commonjs/client/clientPublicTestnet.d.ts.map +1 -1
- package/dist.commonjs/client/clientTypes.advanced.d.ts +3 -0
- package/dist.commonjs/client/clientTypes.advanced.d.ts.map +1 -1
- package/dist.commonjs/client/clientTypes.advanced.js +4 -0
- package/dist.commonjs/client/clientTypes.d.ts +110 -38
- package/dist.commonjs/client/clientTypes.d.ts.map +1 -1
- package/dist.commonjs/client/clientTypes.js +123 -31
- package/dist.commonjs/client/index.d.ts +1 -0
- package/dist.commonjs/client/index.d.ts.map +1 -1
- package/dist.commonjs/client/index.js +1 -0
- package/dist.commonjs/client/jsonRpc/client.d.ts +4 -4
- package/dist.commonjs/client/jsonRpc/client.d.ts.map +1 -1
- package/dist.commonjs/client/jsonRpc/client.js +4 -4
- package/dist.commonjs/client/jsonRpc/transformers.js +2 -2
- package/dist.commonjs/client/knownScript.d.ts +26 -0
- package/dist.commonjs/client/knownScript.d.ts.map +1 -0
- package/dist.commonjs/client/knownScript.js +30 -0
- package/dist.commonjs/index.js +17 -7
- package/dist.commonjs/jsonRpc/transports/webSocket.d.ts.map +1 -1
- package/dist.commonjs/jsonRpc/transports/webSocket.js +7 -3
- package/dist.commonjs/molecule/index.js +17 -7
- package/dist.commonjs/num/index.d.ts.map +1 -1
- package/dist.commonjs/num/index.js +17 -1
- package/dist.commonjs/signer/ckb/signerCkbPublicKey.d.ts.map +1 -1
- package/dist.commonjs/signer/ckb/signerCkbPublicKey.js +1 -5
- package/dist.commonjs/signer/nostr/index.d.ts +1 -0
- package/dist.commonjs/signer/nostr/index.d.ts.map +1 -1
- package/dist.commonjs/signer/nostr/index.js +1 -0
- package/dist.commonjs/signer/nostr/signerNostr.d.ts +1 -1
- package/dist.commonjs/signer/nostr/signerNostr.d.ts.map +1 -1
- package/dist.commonjs/signer/nostr/signerNostr.js +8 -0
- package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts +5 -7
- package/dist.commonjs/signer/nostr/signerNostrPrivateKey.d.ts.map +1 -1
- package/dist.commonjs/signer/nostr/signerNostrPrivateKey.js +6 -12
- package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts +11 -0
- package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.d.ts.map +1 -0
- package/dist.commonjs/signer/nostr/signerNostrPublicKeyReadonly.js +26 -0
- package/dist.commonjs/utils/index.d.ts +4 -0
- package/dist.commonjs/utils/index.d.ts.map +1 -1
- package/dist.commonjs/utils/index.js +13 -0
- package/package.json +1 -1
- package/src/ckb/script.ts +2 -1
- package/src/ckb/transaction.ts +376 -97
- package/src/client/cache/cache.ts +126 -13
- package/src/client/cache/memory.advanced.ts +24 -7
- package/src/client/cache/memory.ts +130 -30
- package/src/client/client.ts +172 -28
- package/src/client/clientPublicMainnet.advanced.ts +2 -1
- package/src/client/clientPublicMainnet.ts +3 -7
- package/src/client/clientPublicTestnet.advanced.ts +2 -1
- package/src/client/clientPublicTestnet.ts +2 -1
- package/src/client/clientTypes.advanced.ts +4 -0
- package/src/client/clientTypes.ts +224 -61
- package/src/client/index.ts +1 -0
- package/src/client/jsonRpc/client.ts +11 -9
- package/src/client/jsonRpc/transformers.ts +2 -2
- package/src/client/knownScript.ts +27 -0
- package/src/jsonRpc/transports/webSocket.ts +17 -13
- package/src/num/index.ts +21 -1
- package/src/signer/ckb/signerCkbPublicKey.ts +3 -5
- package/src/signer/nostr/index.ts +1 -0
- package/src/signer/nostr/signerNostr.ts +3 -1
- package/src/signer/nostr/signerNostrPrivateKey.ts +7 -14
- package/src/signer/nostr/signerNostrPublicKeyReadonly.ts +29 -0
- package/src/utils/index.ts +14 -1
package/src/ckb/transaction.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Bytes, BytesLike, bytesFrom } from "../bytes/index.js";
|
|
2
2
|
import type { ClientCollectableSearchKeyFilterLike } from "../client/clientTypes.advanced.js";
|
|
3
|
-
import
|
|
3
|
+
import {
|
|
4
|
+
ClientBlockHeader,
|
|
5
|
+
type CellDepInfoLike,
|
|
6
|
+
type Client,
|
|
7
|
+
type ClientBlockHeaderLike,
|
|
8
|
+
} from "../client/index.js";
|
|
9
|
+
import { KnownScript } from "../client/knownScript.js";
|
|
4
10
|
import {
|
|
5
11
|
Zero,
|
|
6
12
|
fixedPointFrom,
|
|
@@ -229,8 +235,12 @@ export const CellOutputVec = mol.vector(CellOutput);
|
|
|
229
235
|
/**
|
|
230
236
|
* @public
|
|
231
237
|
*/
|
|
232
|
-
export type CellLike =
|
|
233
|
-
|
|
238
|
+
export type CellLike = (
|
|
239
|
+
| {
|
|
240
|
+
outPoint: OutPointLike;
|
|
241
|
+
}
|
|
242
|
+
| { previousOutput: OutPointLike }
|
|
243
|
+
) & {
|
|
234
244
|
cellOutput: CellOutputLike;
|
|
235
245
|
outputData: HexLike;
|
|
236
246
|
};
|
|
@@ -265,12 +275,133 @@ export class Cell {
|
|
|
265
275
|
}
|
|
266
276
|
|
|
267
277
|
return new Cell(
|
|
268
|
-
OutPoint.from(cell.outPoint),
|
|
278
|
+
OutPoint.from("outPoint" in cell ? cell.outPoint : cell.previousOutput),
|
|
269
279
|
CellOutput.from(cell.cellOutput),
|
|
270
280
|
hexFrom(cell.outputData),
|
|
271
281
|
);
|
|
272
282
|
}
|
|
273
283
|
|
|
284
|
+
get capacityFree() {
|
|
285
|
+
const occupiedSize = fixedPointFrom(
|
|
286
|
+
this.cellOutput.occupiedSize + bytesFrom(this.outputData).length,
|
|
287
|
+
);
|
|
288
|
+
return this.cellOutput.capacity - occupiedSize;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Occupied bytes of a cell on chain
|
|
293
|
+
* It's CellOutput.occupiedSize + bytesFrom(outputData).byteLength
|
|
294
|
+
*/
|
|
295
|
+
get occupiedSize() {
|
|
296
|
+
return this.cellOutput.occupiedSize + bytesFrom(this.outputData).byteLength;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Gets confirmed Nervos DAO profit of a Cell
|
|
301
|
+
* It returns non-zero value only when the cell is in withdrawal phase 2
|
|
302
|
+
* See https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md
|
|
303
|
+
*
|
|
304
|
+
* @param client - A client for searching DAO related headers
|
|
305
|
+
* @returns Profit
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const profit = await cell.getDaoProfit(client);
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
async getDaoProfit(client: Client): Promise<Num> {
|
|
313
|
+
if (!(await this.isNervosDao(client, "withdrew"))) {
|
|
314
|
+
return Zero;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const { depositHeader, withdrawHeader } =
|
|
318
|
+
await this.getNervosDaoInfo(client);
|
|
319
|
+
if (!withdrawHeader || !depositHeader) {
|
|
320
|
+
throw new Error(
|
|
321
|
+
`Unable to get headers of a Nervos DAO cell ${this.outPoint.txHash}:${this.outPoint.index.toString()}`,
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return calcDaoProfit(this.capacityFree, depositHeader, withdrawHeader);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async isNervosDao(
|
|
329
|
+
client: Client,
|
|
330
|
+
phase?: "deposited" | "withdrew",
|
|
331
|
+
): Promise<boolean> {
|
|
332
|
+
const { type } = this.cellOutput;
|
|
333
|
+
|
|
334
|
+
const daoType = await client.getKnownScript(KnownScript.NervosDao);
|
|
335
|
+
if (
|
|
336
|
+
!type ||
|
|
337
|
+
type.codeHash !== daoType.codeHash ||
|
|
338
|
+
type.hashType !== daoType.hashType
|
|
339
|
+
) {
|
|
340
|
+
// Non Nervos DAO cell
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const hasWithdrew = numFrom(this.outputData) !== Zero;
|
|
345
|
+
return (
|
|
346
|
+
!phase ||
|
|
347
|
+
(phase === "deposited" && !hasWithdrew) ||
|
|
348
|
+
(phase === "withdrew" && hasWithdrew)
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async getNervosDaoInfo(client: Client): Promise<
|
|
353
|
+
// Non Nervos DAO cell
|
|
354
|
+
| {
|
|
355
|
+
depositHeader?: undefined;
|
|
356
|
+
withdrawHeader?: undefined;
|
|
357
|
+
}
|
|
358
|
+
// Deposited Nervos DAO cell
|
|
359
|
+
| {
|
|
360
|
+
depositHeader: ClientBlockHeader;
|
|
361
|
+
withdrawHeader?: undefined;
|
|
362
|
+
}
|
|
363
|
+
// Withdrew Nervos DAO cell
|
|
364
|
+
| {
|
|
365
|
+
depositHeader: ClientBlockHeader;
|
|
366
|
+
withdrawHeader: ClientBlockHeader;
|
|
367
|
+
}
|
|
368
|
+
> {
|
|
369
|
+
if (!(await this.isNervosDao(client))) {
|
|
370
|
+
// Non Nervos DAO cell
|
|
371
|
+
return {};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (numFrom(this.outputData) === Zero) {
|
|
375
|
+
// Deposited Nervos DAO cell
|
|
376
|
+
const depositRes = await client.getCellWithHeader(this.outPoint);
|
|
377
|
+
if (!depositRes?.header) {
|
|
378
|
+
throw new Error(
|
|
379
|
+
`Unable to get header of a Nervos DAO deposited cell ${this.outPoint.txHash}:${this.outPoint.index.toString()}`,
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return {
|
|
384
|
+
depositHeader: depositRes.header,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Withdrew Nervos DAO cell
|
|
389
|
+
const [depositHeader, withdrawRes] = await Promise.all([
|
|
390
|
+
client.getHeaderByNumber(numFromBytes(this.outputData)),
|
|
391
|
+
client.getCellWithHeader(this.outPoint),
|
|
392
|
+
]);
|
|
393
|
+
if (!withdrawRes?.header || !depositHeader) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
`Unable to get headers of a Nervos DAO withdrew cell ${this.outPoint.txHash}:${this.outPoint.index.toString()}`,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
depositHeader,
|
|
401
|
+
withdrawHeader: withdrawRes.header,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
274
405
|
/**
|
|
275
406
|
* Clone a Cell
|
|
276
407
|
*
|
|
@@ -450,8 +581,12 @@ export class Since extends mol.Entity.Base<SinceLike, Since>() {
|
|
|
450
581
|
/**
|
|
451
582
|
* @public
|
|
452
583
|
*/
|
|
453
|
-
export type CellInputLike =
|
|
454
|
-
|
|
584
|
+
export type CellInputLike = (
|
|
585
|
+
| {
|
|
586
|
+
previousOutput: OutPointLike;
|
|
587
|
+
}
|
|
588
|
+
| { outPoint: OutPointLike }
|
|
589
|
+
) & {
|
|
455
590
|
since?: SinceLike | NumLike | null;
|
|
456
591
|
cellOutput?: CellOutputLike | null;
|
|
457
592
|
outputData?: HexLike | null;
|
|
@@ -465,10 +600,7 @@ export type CellInputLike = {
|
|
|
465
600
|
since: Since,
|
|
466
601
|
previousOutput: OutPoint,
|
|
467
602
|
})
|
|
468
|
-
.mapIn((encodable: CellInputLike) => (
|
|
469
|
-
...encodable,
|
|
470
|
-
since: encodable.since ?? 0,
|
|
471
|
-
})),
|
|
603
|
+
.mapIn((encodable: CellInputLike) => CellInput.from(encodable)),
|
|
472
604
|
)
|
|
473
605
|
export class CellInput extends mol.Entity.Base<CellInputLike, CellInput>() {
|
|
474
606
|
/**
|
|
@@ -509,21 +641,40 @@ export class CellInput extends mol.Entity.Base<CellInputLike, CellInput>() {
|
|
|
509
641
|
}
|
|
510
642
|
|
|
511
643
|
return new CellInput(
|
|
512
|
-
OutPoint.from(
|
|
644
|
+
OutPoint.from(
|
|
645
|
+
"previousOutput" in cellInput
|
|
646
|
+
? cellInput.previousOutput
|
|
647
|
+
: cellInput.outPoint,
|
|
648
|
+
),
|
|
513
649
|
Since.from(cellInput.since ?? 0).toNum(),
|
|
514
650
|
apply(CellOutput.from, cellInput.cellOutput),
|
|
515
651
|
apply(hexFrom, cellInput.outputData),
|
|
516
652
|
);
|
|
517
653
|
}
|
|
518
654
|
|
|
655
|
+
async getCell(client: Client): Promise<Cell> {
|
|
656
|
+
await this.completeExtraInfos(client);
|
|
657
|
+
if (!this.cellOutput || !this.outputData) {
|
|
658
|
+
throw new Error("Unable to complete input");
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return Cell.from({
|
|
662
|
+
outPoint: this.previousOutput,
|
|
663
|
+
cellOutput: this.cellOutput,
|
|
664
|
+
outputData: this.outputData,
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
519
668
|
/**
|
|
520
|
-
* Complete extra infos in the input.
|
|
669
|
+
* Complete extra infos in the input. Including
|
|
670
|
+
* - Previous cell output
|
|
671
|
+
* - Previous cell data
|
|
521
672
|
* The instance will be modified.
|
|
522
673
|
*
|
|
523
674
|
* @returns true if succeed.
|
|
524
675
|
* @example
|
|
525
676
|
* ```typescript
|
|
526
|
-
* await cellInput.completeExtraInfos();
|
|
677
|
+
* await cellInput.completeExtraInfos(client);
|
|
527
678
|
* ```
|
|
528
679
|
*/
|
|
529
680
|
async completeExtraInfos(client: Client): Promise<void> {
|
|
@@ -539,6 +690,23 @@ export class CellInput extends mol.Entity.Base<CellInputLike, CellInput>() {
|
|
|
539
690
|
this.cellOutput = cell.cellOutput;
|
|
540
691
|
this.outputData = cell.outputData;
|
|
541
692
|
}
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* The extra capacity created when consume this input.
|
|
696
|
+
* This is usually NervosDAO interest, see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md.
|
|
697
|
+
* And it can also be miners' income. (But this is not implemented yet)
|
|
698
|
+
*/
|
|
699
|
+
async getExtraCapacity(client: Client): Promise<Num> {
|
|
700
|
+
return (await this.getCell(client)).getDaoProfit(client);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
clone(): CellInput {
|
|
704
|
+
const cloned = super.clone();
|
|
705
|
+
cloned.cellOutput = this.cellOutput;
|
|
706
|
+
cloned.outputData = this.outputData;
|
|
707
|
+
|
|
708
|
+
return cloned;
|
|
709
|
+
}
|
|
542
710
|
}
|
|
543
711
|
export const CellInputVec = mol.vector(CellInput);
|
|
544
712
|
|
|
@@ -684,11 +852,13 @@ export class WitnessArgs extends mol.Entity.Base<
|
|
|
684
852
|
}
|
|
685
853
|
|
|
686
854
|
/**
|
|
855
|
+
* Convert a bytes to a num.
|
|
856
|
+
*
|
|
687
857
|
* @public
|
|
688
858
|
*/
|
|
689
859
|
export function udtBalanceFrom(dataLike: BytesLike): Num {
|
|
690
860
|
const data = bytesFrom(dataLike).slice(0, 16);
|
|
691
|
-
return numFromBytes(data);
|
|
861
|
+
return data.length === 0 ? Zero : numFromBytes(data);
|
|
692
862
|
}
|
|
693
863
|
|
|
694
864
|
export const RawTransaction = mol.table({
|
|
@@ -891,6 +1061,11 @@ export class Transaction extends mol.Entity.Base<
|
|
|
891
1061
|
});
|
|
892
1062
|
}
|
|
893
1063
|
|
|
1064
|
+
/**
|
|
1065
|
+
* @deprecated
|
|
1066
|
+
* Use ccc.stringify instead.
|
|
1067
|
+
* stringify the tx to JSON string.
|
|
1068
|
+
*/
|
|
894
1069
|
stringify(): string {
|
|
895
1070
|
return JSON.stringify(this, (_, value) => {
|
|
896
1071
|
if (typeof value === "bigint") {
|
|
@@ -991,13 +1166,9 @@ export class Transaction extends mol.Entity.Base<
|
|
|
991
1166
|
for (let i = 0; i < this.witnesses.length; i += 1) {
|
|
992
1167
|
const input = this.inputs[i];
|
|
993
1168
|
if (input) {
|
|
994
|
-
await input.
|
|
1169
|
+
const { cellOutput } = await input.getCell(client);
|
|
995
1170
|
|
|
996
|
-
if (!
|
|
997
|
-
throw new Error("Unable to complete input");
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
if (!script.eq(input.cellOutput.lock)) {
|
|
1171
|
+
if (!script.eq(cellOutput.lock)) {
|
|
1001
1172
|
continue;
|
|
1002
1173
|
}
|
|
1003
1174
|
|
|
@@ -1042,15 +1213,11 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1042
1213
|
const script = Script.from({ ...scriptIdLike, args: "0x" });
|
|
1043
1214
|
|
|
1044
1215
|
for (let i = 0; i < this.inputs.length; i += 1) {
|
|
1045
|
-
const
|
|
1046
|
-
await input.completeExtraInfos(client);
|
|
1047
|
-
if (!input.cellOutput) {
|
|
1048
|
-
throw new Error("Unable to complete input");
|
|
1049
|
-
}
|
|
1216
|
+
const { cellOutput } = await this.inputs[i].getCell(client);
|
|
1050
1217
|
|
|
1051
1218
|
if (
|
|
1052
|
-
script.codeHash ===
|
|
1053
|
-
script.hashType ===
|
|
1219
|
+
script.codeHash === cellOutput.lock.codeHash &&
|
|
1220
|
+
script.hashType === cellOutput.lock.hashType
|
|
1054
1221
|
) {
|
|
1055
1222
|
return i;
|
|
1056
1223
|
}
|
|
@@ -1076,13 +1243,9 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1076
1243
|
const script = Script.from(scriptLike);
|
|
1077
1244
|
|
|
1078
1245
|
for (let i = 0; i < this.inputs.length; i += 1) {
|
|
1079
|
-
const
|
|
1080
|
-
await input.completeExtraInfos(client);
|
|
1081
|
-
if (!input.cellOutput) {
|
|
1082
|
-
throw new Error("Unable to complete input");
|
|
1083
|
-
}
|
|
1246
|
+
const { cellOutput } = await this.inputs[i].getCell(client);
|
|
1084
1247
|
|
|
1085
|
-
if (script.eq(
|
|
1248
|
+
if (script.eq(cellOutput.lock)) {
|
|
1086
1249
|
return i;
|
|
1087
1250
|
}
|
|
1088
1251
|
}
|
|
@@ -1107,13 +1270,9 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1107
1270
|
const script = Script.from(scriptLike);
|
|
1108
1271
|
|
|
1109
1272
|
for (let i = this.inputs.length - 1; i >= 0; i -= 1) {
|
|
1110
|
-
const
|
|
1111
|
-
await input.completeExtraInfos(client);
|
|
1112
|
-
if (!input.cellOutput) {
|
|
1113
|
-
throw new Error("Unable to complete input");
|
|
1114
|
-
}
|
|
1273
|
+
const { cellOutput } = await this.inputs[i].getCell(client);
|
|
1115
1274
|
|
|
1116
|
-
if (script.eq(
|
|
1275
|
+
if (script.eq(cellOutput.lock)) {
|
|
1117
1276
|
return i;
|
|
1118
1277
|
}
|
|
1119
1278
|
}
|
|
@@ -1230,6 +1389,62 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1230
1389
|
this.outputsData[index] = hexFrom(witness);
|
|
1231
1390
|
}
|
|
1232
1391
|
|
|
1392
|
+
/**
|
|
1393
|
+
* get input
|
|
1394
|
+
*
|
|
1395
|
+
* @param index - The cell input index
|
|
1396
|
+
*
|
|
1397
|
+
* @example
|
|
1398
|
+
* ```typescript
|
|
1399
|
+
* await tx.getInput(0);
|
|
1400
|
+
* ```
|
|
1401
|
+
*/
|
|
1402
|
+
getInput(index: NumLike): CellInput | undefined {
|
|
1403
|
+
return this.inputs[Number(numFrom(index))];
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* add input
|
|
1407
|
+
*
|
|
1408
|
+
* @param inputLike - The cell input.
|
|
1409
|
+
*
|
|
1410
|
+
* @example
|
|
1411
|
+
* ```typescript
|
|
1412
|
+
* await tx.addInput({ });
|
|
1413
|
+
* ```
|
|
1414
|
+
*/
|
|
1415
|
+
addInput(inputLike: CellInputLike): number {
|
|
1416
|
+
if (this.witnesses.length > this.inputs.length) {
|
|
1417
|
+
this.witnesses.splice(this.inputs.length, 0, "0x");
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
return this.inputs.push(CellInput.from(inputLike));
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
/**
|
|
1424
|
+
* get output
|
|
1425
|
+
*
|
|
1426
|
+
* @param index - The cell output index
|
|
1427
|
+
*
|
|
1428
|
+
* @example
|
|
1429
|
+
* ```typescript
|
|
1430
|
+
* await tx.getOutput(0);
|
|
1431
|
+
* ```
|
|
1432
|
+
*/
|
|
1433
|
+
getOutput(index: NumLike):
|
|
1434
|
+
| {
|
|
1435
|
+
cellOutput: CellOutput;
|
|
1436
|
+
outputData: Hex;
|
|
1437
|
+
}
|
|
1438
|
+
| undefined {
|
|
1439
|
+
const i = Number(numFrom(index));
|
|
1440
|
+
if (i >= this.outputs.length) {
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
return {
|
|
1444
|
+
cellOutput: this.outputs[i],
|
|
1445
|
+
outputData: this.outputsData[i] ?? "0x",
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1233
1448
|
/**
|
|
1234
1449
|
* Add output
|
|
1235
1450
|
*
|
|
@@ -1245,7 +1460,7 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1245
1460
|
outputLike: Omit<CellOutputLike, "capacity"> &
|
|
1246
1461
|
Partial<Pick<CellOutputLike, "capacity">>,
|
|
1247
1462
|
outputData: HexLike = "0x",
|
|
1248
|
-
):
|
|
1463
|
+
): number {
|
|
1249
1464
|
const output = CellOutput.from({
|
|
1250
1465
|
...outputLike,
|
|
1251
1466
|
capacity: outputLike.capacity ?? 0,
|
|
@@ -1255,8 +1470,10 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1255
1470
|
output.occupiedSize + bytesFrom(outputData).length,
|
|
1256
1471
|
);
|
|
1257
1472
|
}
|
|
1258
|
-
const
|
|
1259
|
-
this.setOutputDataAt(
|
|
1473
|
+
const len = this.outputs.push(output);
|
|
1474
|
+
this.setOutputDataAt(len - 1, outputData);
|
|
1475
|
+
|
|
1476
|
+
return len;
|
|
1260
1477
|
}
|
|
1261
1478
|
|
|
1262
1479
|
/**
|
|
@@ -1289,6 +1506,21 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1289
1506
|
* ```
|
|
1290
1507
|
*/
|
|
1291
1508
|
setWitnessArgsAt(index: number, witness: WitnessArgs): void {
|
|
1509
|
+
this.setWitnessAt(index, witness.toBytes());
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* Set witness at index
|
|
1514
|
+
*
|
|
1515
|
+
* @param index - The index of the witness.
|
|
1516
|
+
* @param witness - The witness to set.
|
|
1517
|
+
*
|
|
1518
|
+
* @example
|
|
1519
|
+
* ```typescript
|
|
1520
|
+
* await tx.setWitnessAt(0, witness);
|
|
1521
|
+
* ```
|
|
1522
|
+
*/
|
|
1523
|
+
setWitnessAt(index: number, witness: HexLike): void {
|
|
1292
1524
|
if (this.witnesses.length < index) {
|
|
1293
1525
|
this.witnesses.push(
|
|
1294
1526
|
...Array.from(
|
|
@@ -1298,7 +1530,7 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1298
1530
|
);
|
|
1299
1531
|
}
|
|
1300
1532
|
|
|
1301
|
-
this.witnesses[index] = hexFrom(witness
|
|
1533
|
+
this.witnesses[index] = hexFrom(witness);
|
|
1302
1534
|
}
|
|
1303
1535
|
|
|
1304
1536
|
/**
|
|
@@ -1329,20 +1561,31 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1329
1561
|
this.setWitnessArgsAt(position, witness);
|
|
1330
1562
|
}
|
|
1331
1563
|
|
|
1332
|
-
async
|
|
1564
|
+
async getInputsCapacityExtra(client: Client): Promise<Num> {
|
|
1333
1565
|
return reduceAsync(
|
|
1334
1566
|
this.inputs,
|
|
1335
|
-
async (acc, input) =>
|
|
1336
|
-
await input.completeExtraInfos(client);
|
|
1337
|
-
if (!input.cellOutput) {
|
|
1338
|
-
throw new Error("Unable to complete input");
|
|
1339
|
-
}
|
|
1340
|
-
return acc + input.cellOutput.capacity;
|
|
1341
|
-
},
|
|
1567
|
+
async (acc, input) => acc + (await input.getExtraCapacity(client)),
|
|
1342
1568
|
numFrom(0),
|
|
1343
1569
|
);
|
|
1344
1570
|
}
|
|
1345
1571
|
|
|
1572
|
+
// This also includes extra amount
|
|
1573
|
+
async getInputsCapacity(client: Client): Promise<Num> {
|
|
1574
|
+
return (
|
|
1575
|
+
(await reduceAsync(
|
|
1576
|
+
this.inputs,
|
|
1577
|
+
async (acc, input) => {
|
|
1578
|
+
const {
|
|
1579
|
+
cellOutput: { capacity },
|
|
1580
|
+
} = await input.getCell(client);
|
|
1581
|
+
|
|
1582
|
+
return acc + capacity;
|
|
1583
|
+
},
|
|
1584
|
+
numFrom(0),
|
|
1585
|
+
)) + (await this.getInputsCapacityExtra(client))
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1346
1589
|
getOutputsCapacity(): Num {
|
|
1347
1590
|
return this.outputs.reduce(
|
|
1348
1591
|
(acc, { capacity }) => acc + capacity,
|
|
@@ -1354,15 +1597,12 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1354
1597
|
return reduceAsync(
|
|
1355
1598
|
this.inputs,
|
|
1356
1599
|
async (acc, input) => {
|
|
1357
|
-
await input.
|
|
1358
|
-
if (!
|
|
1359
|
-
throw new Error("Unable to complete input");
|
|
1360
|
-
}
|
|
1361
|
-
if (!input.cellOutput.type?.eq(type)) {
|
|
1600
|
+
const { cellOutput, outputData } = await input.getCell(client);
|
|
1601
|
+
if (!cellOutput.type?.eq(type)) {
|
|
1362
1602
|
return;
|
|
1363
1603
|
}
|
|
1364
1604
|
|
|
1365
|
-
return acc + udtBalanceFrom(
|
|
1605
|
+
return acc + udtBalanceFrom(outputData);
|
|
1366
1606
|
},
|
|
1367
1607
|
numFrom(0),
|
|
1368
1608
|
);
|
|
@@ -1415,15 +1655,7 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1415
1655
|
acc = next;
|
|
1416
1656
|
}
|
|
1417
1657
|
|
|
1418
|
-
this.
|
|
1419
|
-
...collectedCells.map(({ outPoint, outputData, cellOutput }) =>
|
|
1420
|
-
CellInput.from({
|
|
1421
|
-
previousOutput: outPoint,
|
|
1422
|
-
outputData,
|
|
1423
|
-
cellOutput,
|
|
1424
|
-
}),
|
|
1425
|
-
),
|
|
1426
|
-
);
|
|
1658
|
+
collectedCells.forEach((cell) => this.addInput(cell));
|
|
1427
1659
|
if (fulfilled) {
|
|
1428
1660
|
return {
|
|
1429
1661
|
addedCount: collectedCells.length,
|
|
@@ -1526,31 +1758,18 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1526
1758
|
from: Signer,
|
|
1527
1759
|
filter?: ClientCollectableSearchKeyFilterLike,
|
|
1528
1760
|
): Promise<number> {
|
|
1529
|
-
|
|
1761
|
+
const { addedCount, accumulated } = await this.completeInputs(
|
|
1762
|
+
from,
|
|
1530
1763
|
filter ?? {
|
|
1531
1764
|
scriptLenRange: [0, 1],
|
|
1532
1765
|
outputDataLenRange: [0, 1],
|
|
1533
1766
|
},
|
|
1767
|
+
() => undefined,
|
|
1534
1768
|
true,
|
|
1535
|
-
|
|
1536
|
-
1,
|
|
1537
|
-
)) {
|
|
1538
|
-
if (
|
|
1539
|
-
this.inputs.some(({ previousOutput }) =>
|
|
1540
|
-
previousOutput.eq(cell.outPoint),
|
|
1541
|
-
)
|
|
1542
|
-
) {
|
|
1543
|
-
continue;
|
|
1544
|
-
}
|
|
1769
|
+
);
|
|
1545
1770
|
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
previousOutput: cell.outPoint,
|
|
1549
|
-
outputData: cell.outputData,
|
|
1550
|
-
cellOutput: cell.cellOutput,
|
|
1551
|
-
}),
|
|
1552
|
-
);
|
|
1553
|
-
return 1;
|
|
1771
|
+
if (accumulated === undefined) {
|
|
1772
|
+
return addedCount;
|
|
1554
1773
|
}
|
|
1555
1774
|
|
|
1556
1775
|
throw new Error(`Insufficient CKB, need at least one new cell`);
|
|
@@ -1567,9 +1786,21 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1567
1786
|
return this.completeInputsAddOne(from, filter);
|
|
1568
1787
|
}
|
|
1569
1788
|
|
|
1789
|
+
async getFee(client: Client): Promise<Num> {
|
|
1790
|
+
return (await this.getInputsCapacity(client)) - this.getOutputsCapacity();
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
async getFeeRate(client: Client): Promise<Num> {
|
|
1794
|
+
return (
|
|
1795
|
+
((await this.getFee(client)) * numFrom(1000)) /
|
|
1796
|
+
numFrom(this.toBytes().length + 4)
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1570
1800
|
estimateFee(feeRate: NumLike): Num {
|
|
1571
1801
|
const txSize = this.toBytes().length + 4;
|
|
1572
|
-
|
|
1802
|
+
// + 999 then / 1000 to ceil the calculated fee
|
|
1803
|
+
return (numFrom(txSize) * numFrom(feeRate) + numFrom(999)) / numFrom(1000);
|
|
1573
1804
|
}
|
|
1574
1805
|
|
|
1575
1806
|
async completeFee(
|
|
@@ -1577,8 +1808,11 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1577
1808
|
change: (tx: Transaction, capacity: Num) => Promise<NumLike> | NumLike,
|
|
1578
1809
|
expectedFeeRate?: NumLike,
|
|
1579
1810
|
filter?: ClientCollectableSearchKeyFilterLike,
|
|
1811
|
+
options?: { feeRateBlockRange?: NumLike; maxFeeRate?: NumLike },
|
|
1580
1812
|
): Promise<[number, boolean]> {
|
|
1581
|
-
const feeRate =
|
|
1813
|
+
const feeRate =
|
|
1814
|
+
expectedFeeRate ??
|
|
1815
|
+
(await from.client.getFeeRate(options?.feeRateBlockRange, options));
|
|
1582
1816
|
|
|
1583
1817
|
// Complete all inputs extra infos for cache
|
|
1584
1818
|
await this.getInputsCapacity(from.client);
|
|
@@ -1609,27 +1843,21 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1609
1843
|
// The initial fee is calculated based on prepared transaction
|
|
1610
1844
|
leastFee = tx.estimateFee(feeRate);
|
|
1611
1845
|
}
|
|
1612
|
-
const
|
|
1613
|
-
(await tx.getInputsCapacity(from.client)) - tx.getOutputsCapacity();
|
|
1846
|
+
const fee = await tx.getFee(from.client);
|
|
1614
1847
|
// The extra capacity paid the fee without a change
|
|
1615
|
-
if (
|
|
1848
|
+
if (fee === leastFee) {
|
|
1616
1849
|
this.copy(tx);
|
|
1617
1850
|
return [collected, false];
|
|
1618
1851
|
}
|
|
1619
1852
|
|
|
1620
|
-
const needed = numFrom(
|
|
1621
|
-
await Promise.resolve(change(tx, extraCapacity - leastFee)),
|
|
1622
|
-
);
|
|
1853
|
+
const needed = numFrom(await Promise.resolve(change(tx, fee - leastFee)));
|
|
1623
1854
|
// No enough extra capacity to create new cells for change
|
|
1624
1855
|
if (needed > Zero) {
|
|
1625
1856
|
leastExtraCapacity = needed;
|
|
1626
1857
|
continue;
|
|
1627
1858
|
}
|
|
1628
1859
|
|
|
1629
|
-
if (
|
|
1630
|
-
(await tx.getInputsCapacity(from.client)) - tx.getOutputsCapacity() !==
|
|
1631
|
-
leastFee
|
|
1632
|
-
) {
|
|
1860
|
+
if ((await tx.getFee(from.client)) !== leastFee) {
|
|
1633
1861
|
throw new Error(
|
|
1634
1862
|
"The change function doesn't use all available capacity",
|
|
1635
1863
|
);
|
|
@@ -1708,3 +1936,54 @@ export class Transaction extends mol.Entity.Base<
|
|
|
1708
1936
|
);
|
|
1709
1937
|
}
|
|
1710
1938
|
}
|
|
1939
|
+
|
|
1940
|
+
/**
|
|
1941
|
+
* Calculate Nervos DAO profit between two blocks
|
|
1942
|
+
*/
|
|
1943
|
+
export function calcDaoProfit(
|
|
1944
|
+
profitableCapacity: NumLike,
|
|
1945
|
+
depositHeaderLike: ClientBlockHeaderLike,
|
|
1946
|
+
withdrawHeaderLike: ClientBlockHeaderLike,
|
|
1947
|
+
): Num {
|
|
1948
|
+
const depositHeader = ClientBlockHeader.from(depositHeaderLike);
|
|
1949
|
+
const withdrawHeader = ClientBlockHeader.from(withdrawHeaderLike);
|
|
1950
|
+
|
|
1951
|
+
const profitableSize = numFrom(profitableCapacity);
|
|
1952
|
+
|
|
1953
|
+
return (
|
|
1954
|
+
(profitableSize * withdrawHeader.dao.ar) / depositHeader.dao.ar -
|
|
1955
|
+
profitableSize
|
|
1956
|
+
);
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
/**
|
|
1960
|
+
* Calculate claimable epoch for Nervos DAO withdrawal
|
|
1961
|
+
* See https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md
|
|
1962
|
+
*/
|
|
1963
|
+
export function calcDaoClaimEpoch(
|
|
1964
|
+
depositHeader: ClientBlockHeaderLike,
|
|
1965
|
+
withdrawHeader: ClientBlockHeaderLike,
|
|
1966
|
+
): Epoch {
|
|
1967
|
+
const depositEpoch = ClientBlockHeader.from(depositHeader).epoch;
|
|
1968
|
+
const withdrawEpoch = ClientBlockHeader.from(withdrawHeader).epoch;
|
|
1969
|
+
const intDiff = withdrawEpoch[0] - depositEpoch[0];
|
|
1970
|
+
// deposit[1] withdraw[1]
|
|
1971
|
+
// ---------- <= -----------
|
|
1972
|
+
// deposit[2] withdraw[2]
|
|
1973
|
+
if (
|
|
1974
|
+
intDiff % numFrom(180) !== numFrom(0) ||
|
|
1975
|
+
depositEpoch[1] * withdrawEpoch[2] <= depositEpoch[2] * withdrawEpoch[1]
|
|
1976
|
+
) {
|
|
1977
|
+
return [
|
|
1978
|
+
depositEpoch[0] + (intDiff / numFrom(180) + numFrom(1)) * numFrom(180),
|
|
1979
|
+
depositEpoch[1],
|
|
1980
|
+
depositEpoch[2],
|
|
1981
|
+
];
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
return [
|
|
1985
|
+
depositEpoch[0] + (intDiff / numFrom(180)) * numFrom(180),
|
|
1986
|
+
depositEpoch[1],
|
|
1987
|
+
depositEpoch[2],
|
|
1988
|
+
];
|
|
1989
|
+
}
|