88// ! * Caching spent UTXOs so that they are not reused in future transactions.
99// ! * Option to set the fee.
1010
11- import Debug "mo:base/Debug" ;
12- import Array "mo:base/Array" ;
13- import Nat8 "mo:base/Nat8" ;
14- import Nat32 "mo:base/Nat32" ;
15- import Nat64 "mo:base/Nat64" ;
16- import Iter "mo:base/Iter" ;
17- import Blob "mo:base/Blob" ;
18- import Nat "mo:base/Nat" ;
11+ import Debug "mo:core/Debug" ;
12+ import Runtime "mo:core/Runtime" ;
13+ import Array "mo:core/Array" ;
14+ import Nat8 "mo:core/Nat8" ;
15+ import Nat32 "mo:core/Nat32" ;
16+ import Nat64 "mo:core/Nat64" ;
17+ import Blob "mo:core/Blob" ;
1918
2019import EcdsaTypes "mo:bitcoin/ecdsa/Types" ;
2120import P2pkh "mo:bitcoin/bitcoin/P2pkh" ;
@@ -50,10 +49,10 @@ module {
5049 // / Returns the P2PKH address of this canister at the given derivation path.
5150 public func get_address(ecdsa_canister_actor : EcdsaCanisterActor , network : Network , key_name : Text , derivation_path : [[Nat8 ]]) : async BitcoinAddress {
5251 // Fetch the public key of the given derivation path.
53- let public_key = await EcdsaApi . ecdsa_public_key(ecdsa_canister_actor, key_name, Array . map(derivation_path, Blob . fromArray));
52+ let public_key = await EcdsaApi . ecdsa_public_key(ecdsa_canister_actor, key_name, derivation_path . map(Blob . fromArray));
5453
5554 // Compute the address.
56- public_key_to_p2pkh_address(network, Blob . toArray(public_key ));
55+ public_key_to_p2pkh_address(network, public_key . toArray());
5756 };
5857
5958 // / Sends a transaction to the network that transfers the given amount to the
@@ -74,7 +73,7 @@ module {
7473 };
7574
7675 // Fetch our public key, P2PKH address, and UTXOs.
77- let own_public_key = Blob . toArray (await EcdsaApi . ecdsa_public_key(ecdsa_canister_actor, key_name, Array . map(derivation_path, Blob . fromArray)));
76+ let own_public_key = (await EcdsaApi . ecdsa_public_key(ecdsa_canister_actor, key_name, derivation_path . map(Blob . fromArray))) . toArray( );
7877 let own_address = public_key_to_p2pkh_address(network, own_public_key);
7978
8079 // Note that pagination may have to be used to get all UTXOs for the given address.
@@ -84,11 +83,11 @@ module {
8483
8584 // Build the transaction that sends `amount` to the destination address.
8685 let tx_bytes = await build_transaction(ecdsa_canister_actor, own_public_key, own_address, own_utxos, dst_address, amount, fee_per_vbyte);
87- let transaction = Utils . get_ok(Transaction . fromBytes(Iter . fromArray(tx_bytes )));
86+ let transaction = Utils . get_ok(Transaction . fromBytes(tx_bytes . vals( )));
8887
8988 // Sign the transaction.
90- let signed_transaction_bytes = await sign_transaction(ecdsa_canister_actor, own_public_key, own_address, transaction, key_name, Array . map(derivation_path, Blob . fromArray), EcdsaApi . sign_with_ecdsa);
91- let signed_transaction = Utils . get_ok(Transaction . fromBytes(Iter . fromArray(signed_transaction_bytes )));
89+ let signed_transaction_bytes = await sign_transaction(ecdsa_canister_actor, own_public_key, own_address, transaction, key_name, derivation_path . map(Blob . fromArray), EcdsaApi . sign_with_ecdsa);
90+ let signed_transaction = Utils . get_ok(Transaction . fromBytes(signed_transaction_bytes . vals( )));
9291
9392 Debug . print("Sending transaction" );
9493 await BitcoinApi . send_transaction(network, signed_transaction_bytes);
@@ -117,7 +116,7 @@ module {
117116 // We solve this problem iteratively. We start with a fee of zero, build
118117 // and sign a transaction, see what its size is, and then update the fee,
119118 // rebuild the transaction, until the fee is set to the correct amount.
120- let fee_per_vbyte_nat = Nat64 . toNat(fee_per_vbyte );
119+ let fee_per_vbyte_nat = fee_per_vbyte . toNat();
121120 Debug . print("Building transaction..." );
122121 var total_fee : Nat = 0 ;
123122 loop {
@@ -166,27 +165,27 @@ module {
166165 // scriptPubKey of the Tx output being spent.
167166 switch (Address . scriptPubKey(#p2pkh own_address)) {
168167 case (#ok scriptPubKey) {
169- let scriptSigs = Array . init < Script > ( transaction. txInputs. size(), [] );
168+ let scriptSigs = Array . repeat([] : Script , transaction. txInputs. size()) . toVarArray < Script > ( );
170169
171170 // Obtain scriptSigs for each Tx input.
172- for (i in Iter . range( 0 , transaction. txInputs. size() - 1 )) {
171+ for (i in transaction. txInputs. keys( )) {
173172 let sighash = transaction. createP2pkhSignatureHash(
174173 scriptPubKey,
175174 Nat32 . fromIntWrap(i),
176175 SIGHASH_ALL ,
177176 );
178177
179178 let signature_sec = await signer(ecdsa_canister_actor, key_name, derivation_path, Blob . fromArray(sighash));
180- let signature_der = Blob . toArray( Der . encodeSignature(signature_sec));
179+ let signature_der = Der . encodeSignature(signature_sec). toArray( );
181180
182181 // Append the sighash type.
183- let encodedSignatureWithSighashType = Array . tabulate< Nat8 > (
182+ let encodedSignatureWithSighashType = Array . tabulate(
184183 signature_der. size() + 1 ,
185- func (n) {
184+ func (n : Nat ) : Nat8 {
186185 if (n < signature_der. size()) {
187186 signature_der[n];
188187 } else {
189- Nat8 . fromNat(Nat32 . toNat(SIGHASH_ALL ));
188+ Nat8 . fromNat(SIGHASH_ALL . toNat());
190189 };
191190 },
192191 );
@@ -200,12 +199,12 @@ module {
200199 scriptSigs[i] := script;
201200 };
202201 // Assign ScriptSigs to their associated TxInputs.
203- for (i in Iter . range( 0 , scriptSigs. size() - 1 )) {
202+ for (i in scriptSigs. keys( )) {
204203 transaction. txInputs[i]. script := scriptSigs[i];
205204 };
206205 };
207206 // Verify that our own address is P2PKH.
208- case (#err msg) Debug . trap("This example supports signing p2pkh addresses only: " # msg);
207+ case (#err msg) Runtime . trap("This example supports signing p2pkh addresses only: " # msg);
209208 };
210209
211210 transaction. toBytes();
0 commit comments