1
1
import { Bytes , BytesLike , bytesFrom } from "../bytes/index.js" ;
2
2
import type { ClientCollectableSearchKeyFilterLike } from "../client/clientTypes.advanced.js" ;
3
- import type { CellDepInfoLike , Client , KnownScript } from "../client/index.js" ;
3
+ import type { CellDepInfoLike , Client } from "../client/index.js" ;
4
+ import { KnownScript } from "../client/knownScript.js" ;
4
5
import {
5
6
Zero ,
6
7
fixedPointFrom ,
@@ -526,13 +527,15 @@ export class CellInput extends mol.Entity.Base<CellInputLike, CellInput>() {
526
527
}
527
528
528
529
/**
529
- * Complete extra infos in the input. Like the output of the out point.
530
+ * Complete extra infos in the input. Including
531
+ * - Previous cell output
532
+ * - Previous cell data
530
533
* The instance will be modified.
531
534
*
532
535
* @returns true if succeed.
533
536
* @example
534
537
* ```typescript
535
- * await cellInput.completeExtraInfos();
538
+ * await cellInput.completeExtraInfos(client );
536
539
* ```
537
540
*/
538
541
async completeExtraInfos ( client : Client ) : Promise < void > {
@@ -549,6 +552,69 @@ export class CellInput extends mol.Entity.Base<CellInputLike, CellInput>() {
549
552
this . outputData = cell . outputData ;
550
553
}
551
554
555
+ /**
556
+ * The extra capacity created when consume this input.
557
+ * This is usually NervosDAO interest, see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md.
558
+ * And it can also be miners' income. (But this is not implemented yet)
559
+ */
560
+ async getExtraCapacity ( client : Client ) : Promise < Num > {
561
+ return this . getDaoProfit ( client ) ;
562
+ }
563
+
564
+ /**
565
+ * Gets confirmed Nervos DAO profit of a CellInput
566
+ * It returns non-zero value only when the cell is in withdrawal phase 2
567
+ * See https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0023-dao-deposit-withdraw/0023-dao-deposit-withdraw.md
568
+ *
569
+ * @param client - A client for searching DAO related headers
570
+ * @returns Profit
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * const profit = await input.getDaoProfit(client);
575
+ * ```
576
+ */
577
+ async getDaoProfit ( client : Client ) : Promise < Num > {
578
+ await this . completeExtraInfos ( client ) ;
579
+ if ( ! this . cellOutput || ! this . outputData ) {
580
+ throw new Error ( "Unable to complete input" ) ;
581
+ }
582
+
583
+ const daoType = await client . getKnownScript ( KnownScript . NervosDao ) ;
584
+ const type = this . cellOutput . type ;
585
+ if (
586
+ ! type ||
587
+ type . codeHash !== daoType . codeHash ||
588
+ type . hashType !== daoType . hashType ||
589
+ ! this . outputData ||
590
+ numFrom ( this . outputData ) === Zero
591
+ ) {
592
+ // Not a withdrawal phase 2 cell
593
+ return Zero ;
594
+ }
595
+
596
+ const [ depositHeader , withdrawRes ] = await Promise . all ( [
597
+ client . getHeaderByNumber ( numFromBytes ( this . outputData ) ) ,
598
+ client . getCellWithHeader ( this . previousOutput ) ,
599
+ ] ) ;
600
+ if ( ! withdrawRes ?. header || ! depositHeader ) {
601
+ throw new Error (
602
+ `Unable to get headers of a Nervos DAO input ${ this . previousOutput . txHash } :${ this . previousOutput . index . toString ( ) } ` ,
603
+ ) ;
604
+ }
605
+ const withdrawHeader = withdrawRes . header ;
606
+
607
+ const occupiedSize = fixedPointFrom (
608
+ this . cellOutput . occupiedSize + bytesFrom ( this . outputData ) . length ,
609
+ ) ;
610
+ const profitableSize = this . cellOutput . capacity - occupiedSize ;
611
+
612
+ return (
613
+ ( profitableSize * withdrawHeader . dao . ar ) / depositHeader . dao . ar -
614
+ profitableSize
615
+ ) ;
616
+ }
617
+
552
618
clone ( ) : CellInput {
553
619
const cloned = super . clone ( ) ;
554
620
cloned . cellOutput = this . cellOutput ;
@@ -1426,15 +1492,33 @@ export class Transaction extends mol.Entity.Base<
1426
1492
this . setWitnessArgsAt ( position , witness ) ;
1427
1493
}
1428
1494
1495
+ async getInputsCapacityExtra ( client : Client ) : Promise < Num > {
1496
+ return reduceAsync (
1497
+ this . inputs ,
1498
+ async ( acc , input ) => {
1499
+ const extraCapacity = await input . getExtraCapacity ( client ) ;
1500
+ if ( extraCapacity === undefined ) {
1501
+ throw new Error ( "Unable to complete input" ) ;
1502
+ }
1503
+
1504
+ return acc + extraCapacity ;
1505
+ } ,
1506
+ numFrom ( 0 ) ,
1507
+ ) ;
1508
+ }
1509
+
1510
+ // This also includes extra amount
1429
1511
async getInputsCapacity ( client : Client ) : Promise < Num > {
1430
1512
return reduceAsync (
1431
1513
this . inputs ,
1432
1514
async ( acc , input ) => {
1515
+ const extraCapacity = await input . getExtraCapacity ( client ) ;
1433
1516
await input . completeExtraInfos ( client ) ;
1434
1517
if ( ! input . cellOutput ) {
1435
1518
throw new Error ( "Unable to complete input" ) ;
1436
1519
}
1437
- return acc + input . cellOutput . capacity ;
1520
+
1521
+ return acc + input . cellOutput . capacity + extraCapacity ;
1438
1522
} ,
1439
1523
numFrom ( 0 ) ,
1440
1524
) ;
0 commit comments