1- import { Indexer , helpers , Address , Script , RPC , hd , config , commons , BI , Transaction } from "@ckb-lumos/lumos" ;
1+ import { Indexer , helpers , Address , Script , RPC , hd , config , commons , BI } from "@ckb-lumos/lumos" ;
22import { BIish } from "@ckb-lumos/bi" ;
33import { payFeeByFeeRate } from "@ckb-lumos/common-scripts/lib/common" ;
44
@@ -15,6 +15,50 @@ export type Account = {
1515 pubKey : string ;
1616} ;
1717
18+ /**
19+ * send a transaction to CKB testnet
20+ * @returns Promise with transaction hash
21+ */
22+ export async function transfer ( options : TransactionIO , privateKey : string ) : Promise < { txHash : string ; fee : BI } > {
23+ // step 1, create an raw transaction
24+ // an raw transaction have it's inputs and outputs, but no signature
25+ let txSkeleton = helpers . TransactionSkeleton ( { cellProvider : indexer } ) ;
26+ for ( const target of options . targets ) {
27+ // add each outputs to the transaction skeleton
28+ txSkeleton = await commons . common . transfer (
29+ txSkeleton ,
30+ [ options . address ] ,
31+ target . address ,
32+ target . capacity ,
33+ options . address ,
34+ undefined ,
35+ { config : AGGRON4 }
36+ ) ;
37+ }
38+
39+ // these methods add transaction fee to transaction.
40+ // see the calculate algorithm in https://docs.nervos.org/docs/essays/faq/#how-do-you-calculate-transaction-fee
41+ txSkeleton = await payFeeByFeeRate ( txSkeleton , [ options . address ] , 1000 , undefined , { config : AGGRON4 } ) ;
42+
43+ // step2: sign an transaction
44+
45+ txSkeleton = commons . common . prepareSigningEntries ( txSkeleton ) ;
46+
47+ // message is the hash of raw transaction
48+ const message = txSkeleton . get ( "signingEntries" ) . get ( 0 ) ?. message ;
49+ const signature = hd . key . signRecoverable ( message ! , privateKey ) ;
50+ const tx = helpers . sealTransaction ( txSkeleton , [ signature ] ) ;
51+
52+ // step3: send the transaction to block chain
53+ const txHash = await rpc . sendTransaction ( tx , "passthrough" ) ;
54+
55+ // how about transaction fee? it's just sum(transaction.inputs) - sum(transaction.outputs).
56+ // the transaction fee will be sent to miner.
57+
58+ const transactionFee = getPaidTransactionFee ( txSkeleton ) ;
59+ return { txHash, fee : transactionFee } ;
60+ }
61+
1862export const generateAccountFromPrivateKey = ( privKey : string ) : Account => {
1963 const pubKey = hd . key . privateToPublic ( privKey ) ;
2064 const args = hd . key . publicKeyToBlake160 ( pubKey ) ;
@@ -42,6 +86,7 @@ export function getPaidTransactionFee(skeleton: helpers.TransactionSkeletonType)
4286 const outputs = skeleton . outputs . reduce ( ( acc , cur ) => acc . add ( cur . cellOutput . capacity ) , BI . from ( 0 ) ) ;
4387 return inputs . sub ( outputs ) ;
4488}
89+
4590/**
4691 * fetch all cells and calculate the sum of their capacities
4792 */
@@ -55,54 +100,13 @@ export async function fetchAddressBalance(address: string): Promise<BI> {
55100 return balance ;
56101}
57102
58- interface Options {
103+ /**
104+ * Transaction input and output
105+ */
106+ interface TransactionIO {
59107 targets : {
60108 address : string ;
61109 capacity : BIish ;
62110 } [ ] ;
63111 address : string ;
64112}
65-
66- /**
67- * create an unsigned transaction skeleton which includes several inputs and outputs(for multiple transaction receivers)
68- */
69- export async function createUnsignedTxSkeleton ( options : Options ) {
70- let txSkeleton = helpers . TransactionSkeleton ( { cellProvider : indexer } ) ;
71- for ( const target of options . targets ) {
72- txSkeleton = await commons . common . transfer (
73- txSkeleton ,
74- [ options . address ] ,
75- target . address ,
76- target . capacity ,
77- options . address ,
78- undefined ,
79- { config : AGGRON4 }
80- ) ;
81- }
82-
83- txSkeleton = await payFeeByFeeRate ( txSkeleton , [ options . address ] , 1000 , undefined , { config : AGGRON4 } ) ;
84- return txSkeleton ;
85- }
86-
87- /**
88- * sign a transaction skeleton
89- * @param txSkeleton unsigned transaction skeleton
90- * @param privateKey the private key which can unlock input cells
91- * @returns
92- */
93- export function signTransaction ( txSkeleton : helpers . TransactionSkeletonType , privateKey : string ) {
94- txSkeleton = commons . common . prepareSigningEntries ( txSkeleton ) ;
95- const message = txSkeleton . get ( "signingEntries" ) . get ( 0 ) ?. message ;
96- const signature = hd . key . signRecoverable ( message ! , privateKey ) ;
97- const tx = helpers . sealTransaction ( txSkeleton , [ signature ] ) ;
98- return tx ;
99- }
100-
101- /**
102- * send a transaction to CKB testnet
103- * @returns Promise with transaction hash
104- */
105- export async function transfer ( tx : Transaction ) : Promise < string > {
106- const hash = await rpc . sendTransaction ( tx , "passthrough" ) ;
107- return hash ;
108- }
0 commit comments