mainnet-js 0.4.31 → 0.4.35

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.
Files changed (52) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/main/transaction/Wif.d.ts +6 -4
  3. package/dist/main/transaction/Wif.js +14 -7
  4. package/dist/main/transaction/Wif.js.map +1 -1
  5. package/dist/main/transaction/allocateFee.d.ts +7 -0
  6. package/dist/main/transaction/allocateFee.js +118 -0
  7. package/dist/main/transaction/allocateFee.js.map +1 -0
  8. package/dist/main/util/index.d.ts +1 -0
  9. package/dist/main/util/index.js +4 -1
  10. package/dist/main/util/index.js.map +1 -1
  11. package/dist/main/wallet/Slp.js +4 -1
  12. package/dist/main/wallet/Slp.js.map +1 -1
  13. package/dist/main/wallet/Wif.d.ts +27 -10
  14. package/dist/main/wallet/Wif.js +117 -74
  15. package/dist/main/wallet/Wif.js.map +1 -1
  16. package/dist/main/wallet/enum.d.ts +9 -0
  17. package/dist/main/wallet/enum.js +11 -1
  18. package/dist/main/wallet/enum.js.map +1 -1
  19. package/dist/main/wallet/interface.d.ts +2 -1
  20. package/dist/mainnet-0.4.35.js +2 -0
  21. package/dist/{mainnet-0.4.31.js.LICENSE.txt → mainnet-0.4.35.js.LICENSE.txt} +0 -0
  22. package/dist/module/transaction/Wif.d.ts +6 -4
  23. package/dist/module/transaction/Wif.js +14 -7
  24. package/dist/module/transaction/Wif.js.map +1 -1
  25. package/dist/module/transaction/allocateFee.d.ts +7 -0
  26. package/dist/module/transaction/allocateFee.js +110 -0
  27. package/dist/module/transaction/allocateFee.js.map +1 -0
  28. package/dist/module/util/index.d.ts +1 -0
  29. package/dist/module/util/index.js +1 -0
  30. package/dist/module/util/index.js.map +1 -1
  31. package/dist/module/wallet/Slp.js +4 -1
  32. package/dist/module/wallet/Slp.js.map +1 -1
  33. package/dist/module/wallet/Wif.d.ts +27 -10
  34. package/dist/module/wallet/Wif.js +118 -75
  35. package/dist/module/wallet/Wif.js.map +1 -1
  36. package/dist/module/wallet/enum.d.ts +9 -0
  37. package/dist/module/wallet/enum.js +10 -0
  38. package/dist/module/wallet/enum.js.map +1 -1
  39. package/dist/module/wallet/interface.d.ts +2 -1
  40. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +1 -1
  43. package/src/transaction/Wif.ts +24 -7
  44. package/src/transaction/allocateFee.test.ts +309 -0
  45. package/src/transaction/allocateFee.ts +132 -0
  46. package/src/util/index.ts +1 -0
  47. package/src/wallet/Slp.ts +5 -1
  48. package/src/wallet/Wif.test.ts +38 -0
  49. package/src/wallet/Wif.ts +192 -118
  50. package/src/wallet/enum.ts +10 -0
  51. package/src/wallet/interface.ts +2 -1
  52. package/dist/mainnet-0.4.31.js +0 -2
package/src/wallet/Wif.ts CHANGED
@@ -31,7 +31,7 @@ import { networkPrefixMap } from "../enum";
31
31
  import { PrivateKeyI, UtxoI } from "../interface";
32
32
 
33
33
  import { BaseWallet } from "./Base";
34
- import { WalletTypeEnum } from "./enum";
34
+ import { FeePaidByEnum, WalletTypeEnum } from "./enum";
35
35
  import {
36
36
  CancelWatchFn,
37
37
  SendRequestOptionsI,
@@ -764,6 +764,13 @@ export class Wallet extends BaseWallet {
764
764
  this._slpSemiAware = true;
765
765
  }
766
766
 
767
+ let feePaidBy;
768
+ if (params.options && params.options.feePaidBy) {
769
+ feePaidBy = params.options.feePaidBy;
770
+ } else {
771
+ feePaidBy = FeePaidByEnum.change;
772
+ }
773
+
767
774
  // get inputs
768
775
  let utxos: UtxoI[];
769
776
  if (params.options && params.options.utxoIds) {
@@ -787,7 +794,12 @@ export class Wallet extends BaseWallet {
787
794
  .fill(0)
788
795
  .map(() => sendRequest);
789
796
 
790
- const fundingUtxos = await getSuitableUtxos(utxos, undefined, bestHeight);
797
+ const fundingUtxos = await getSuitableUtxos(
798
+ utxos,
799
+ undefined,
800
+ bestHeight,
801
+ feePaidBy
802
+ );
791
803
  const relayFeePerByteInSatoshi = await getRelayFeeCache(this.provider!);
792
804
  const fee = await getFeeAmount({
793
805
  utxos: fundingUtxos,
@@ -795,6 +807,7 @@ export class Wallet extends BaseWallet {
795
807
  privateKey: this.privateKey,
796
808
  relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
797
809
  slpOutputs: [],
810
+ feePaidBy: feePaidBy,
798
811
  });
799
812
  const spendableAmount = await sumUtxoValue(fundingUtxos);
800
813
 
@@ -808,6 +821,8 @@ export class Wallet extends BaseWallet {
808
821
 
809
822
  /**
810
823
  * send Send some amount to an address
824
+ * this function processes the send requests, encodes the transaction, sends it to the network
825
+ * @returns (depending on the options parameter) the transaction id, new address balance and a link to the transaction on the blockchain explorer
811
826
  *
812
827
  * This is a first class function with REST analog, maintainers should strive to keep backward-compatibility
813
828
  *
@@ -820,14 +835,24 @@ export class Wallet extends BaseWallet {
820
835
  | SendRequestArray[],
821
836
  options?: SendRequestOptionsI
822
837
  ): Promise<SendResponse> {
823
- let sendRequests = asSendRequestObject(requests);
824
- let result = await this._processSendRequests(
825
- sendRequests,
838
+ let encodedTransaction = await this.encodeTransaction(
839
+ requests,
826
840
  undefined,
827
841
  options
828
842
  );
843
+
844
+ const awaitTransactionPropagation =
845
+ !options ||
846
+ options.awaitTransactionPropagation === undefined ||
847
+ options.awaitTransactionPropagation;
848
+
849
+ const txId = await this.submitTransaction(
850
+ encodedTransaction,
851
+ awaitTransactionPropagation
852
+ );
853
+
829
854
  let resp = new SendResponse({});
830
- resp.txId = result;
855
+ resp.txId = txId;
831
856
  const queryBalance =
832
857
  !options || options.queryBalance === undefined || options.queryBalance;
833
858
  if (queryBalance) {
@@ -837,6 +862,14 @@ export class Wallet extends BaseWallet {
837
862
  return resp;
838
863
  }
839
864
 
865
+ /**
866
+ * sendMax Send all available funds to a destination cash address
867
+ *
868
+ * @param {string} cashaddr destination cash address
869
+ * @param {SendRequestOptionsI} options Options of the send requests
870
+ *
871
+ * @returns (depending on the options parameter) the transaction id, new address balance and a link to the transaction on the blockchain explorer
872
+ */
840
873
  public async sendMax(
841
874
  cashaddr: string,
842
875
  options?: SendRequestOptionsI
@@ -853,7 +886,18 @@ export class Wallet extends BaseWallet {
853
886
  };
854
887
  }
855
888
 
856
- private async sendMaxRaw(cashaddr: string, options?: SendRequestOptionsI) {
889
+ /**
890
+ * sendMaxRaw (internal) Send all available funds to a destination cash address
891
+ *
892
+ * @param {string} cashaddr destination cash address
893
+ * @param {SendRequestOptionsI} options Options of the send requests
894
+ *
895
+ * @returns the transaction id sent to the network
896
+ */
897
+ private async sendMaxRaw(
898
+ cashaddr: string,
899
+ options?: SendRequestOptionsI
900
+ ): Promise<string> {
857
901
  let maxSpendableAmount = await this.getMaxAmountToSend({
858
902
  outputCount: 1,
859
903
  options: options,
@@ -866,7 +910,141 @@ export class Wallet extends BaseWallet {
866
910
  value: maxSpendableAmount.sat,
867
911
  unit: "sat",
868
912
  });
869
- return await this._processSendRequests([sendRequest], true, options);
913
+
914
+ const encodedTransaction = await this.encodeTransaction(
915
+ [sendRequest],
916
+ true,
917
+ options
918
+ );
919
+ const awaitTransactionPropagation =
920
+ !options ||
921
+ options.awaitTransactionPropagation === undefined ||
922
+ options.awaitTransactionPropagation;
923
+
924
+ const txId = await this.submitTransaction(
925
+ encodedTransaction,
926
+ awaitTransactionPropagation
927
+ );
928
+
929
+ return txId;
930
+ }
931
+
932
+ /**
933
+ * encodeTransaction Encode and sign a transaction given a list of sendRequests, options and estimate fees.
934
+ * @param {SendRequest[]} sendRequests SendRequests
935
+ * @param {boolean} discardChange=false
936
+ * @param {SendRequestOptionsI} options Options of the send requests
937
+ */
938
+ public async encodeTransaction(
939
+ requests:
940
+ | SendRequest
941
+ | OpReturnData
942
+ | Array<SendRequest | OpReturnData>
943
+ | SendRequestArray[],
944
+ discardChange: boolean = false,
945
+ options?: SendRequestOptionsI
946
+ ) {
947
+ let sendRequests = asSendRequestObject(requests);
948
+
949
+ if (!this.privateKey) {
950
+ throw new Error(
951
+ `Wallet ${this.name} is missing either a network or private key`
952
+ );
953
+ }
954
+ if (!this.cashaddr) {
955
+ throw Error("attempted to send without a cashaddr");
956
+ }
957
+
958
+ if (options && options.slpAware) {
959
+ this._slpAware = true;
960
+ }
961
+
962
+ if (options && options.slpSemiAware) {
963
+ this._slpSemiAware = true;
964
+ }
965
+
966
+ let feePaidBy;
967
+ if (options && options.feePaidBy) {
968
+ feePaidBy = options.feePaidBy;
969
+ } else {
970
+ feePaidBy = FeePaidByEnum.change;
971
+ }
972
+
973
+ // get inputs from options or query all inputs
974
+ let utxos: UtxoI[];
975
+ if (options && options.utxoIds) {
976
+ utxos = options.utxoIds.map((utxoId) =>
977
+ UtxoItem.fromId(utxoId).asElectrum()
978
+ );
979
+ } else {
980
+ utxos = await this.getAddressUtxos(this.cashaddr);
981
+ }
982
+
983
+ const bestHeight = await this.provider!.getBlockHeight()!;
984
+ const spendAmount = await sumSendRequestAmounts(sendRequests);
985
+
986
+ if (utxos.length === 0) {
987
+ throw Error("There were no Unspent Outputs");
988
+ }
989
+ if (typeof spendAmount !== "bigint") {
990
+ throw Error("Couldn't get spend amount when building transaction");
991
+ }
992
+
993
+ const relayFeePerByteInSatoshi = await getRelayFeeCache(this.provider!);
994
+ const feeEstimate = await getFeeAmount({
995
+ utxos: utxos,
996
+ sendRequests: sendRequests,
997
+ privateKey: this.privateKey,
998
+ relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
999
+ slpOutputs: [],
1000
+ feePaidBy: feePaidBy,
1001
+ });
1002
+
1003
+ const fundingUtxos = await getSuitableUtxos(
1004
+ utxos,
1005
+ BigInt(spendAmount) + BigInt(feeEstimate),
1006
+ bestHeight,
1007
+ feePaidBy
1008
+ );
1009
+ if (fundingUtxos.length === 0) {
1010
+ throw Error(
1011
+ "The available inputs couldn't satisfy the request with fees"
1012
+ );
1013
+ }
1014
+ const fee = await getFeeAmount({
1015
+ utxos: fundingUtxos,
1016
+ sendRequests: sendRequests,
1017
+ privateKey: this.privateKey,
1018
+ relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
1019
+ slpOutputs: [],
1020
+ feePaidBy: feePaidBy,
1021
+ });
1022
+ const encodedTransaction = await buildEncodedTransaction(
1023
+ fundingUtxos,
1024
+ sendRequests,
1025
+ this.privateKey,
1026
+ fee,
1027
+ discardChange,
1028
+ [],
1029
+ feePaidBy
1030
+ );
1031
+
1032
+ return encodedTransaction;
1033
+ }
1034
+
1035
+ // Submit a raw transaction
1036
+ public async submitTransaction(
1037
+ transaction: Uint8Array,
1038
+ awaitPropagation: boolean = true
1039
+ ): Promise<string> {
1040
+ if (!this.provider) {
1041
+ throw Error("Wallet network provider was not initialized");
1042
+ }
1043
+ let rawTransaction = binToHex(transaction);
1044
+ return await this.provider.sendRawTransaction(
1045
+ rawTransaction,
1046
+ awaitPropagation
1047
+ );
870
1048
  }
871
1049
 
872
1050
  // gets transaction history of this wallet
@@ -877,11 +1055,16 @@ export class Wallet extends BaseWallet {
877
1055
  // gets last transaction of this wallet
878
1056
  public async getLastTransaction(
879
1057
  confirmedOnly: boolean = false
880
- ): Promise<ElectrumRawTransaction> {
1058
+ ): Promise<ElectrumRawTransaction | null> {
881
1059
  let history: TxI[] = await this.getHistory();
882
1060
  if (confirmedOnly) {
883
1061
  history = history.filter((val) => val.height > 0);
884
1062
  }
1063
+
1064
+ if (!history.length) {
1065
+ return null;
1066
+ }
1067
+
885
1068
  const [lastTx] = history.slice(-1);
886
1069
  return this.provider!.getRawTransactionObject(lastTx.tx_hash);
887
1070
  }
@@ -1002,115 +1185,6 @@ export class Wallet extends BaseWallet {
1002
1185
  this.publicKeyHash = derivePublicKeyHash(this.cashaddr!);
1003
1186
  return this;
1004
1187
  }
1005
-
1006
- /**
1007
- * _processSendRequests given a list of sendRequests, estimate fees, build the transaction and submit it.
1008
- * This function is an internal wrapper and may change.
1009
- * @param {SendRequest[]} sendRequests SendRequests
1010
- * @param {} discardChange=false
1011
- * @param {SendRequestOptionsI} options Options of the send requests
1012
- */
1013
- private async _processSendRequests(
1014
- sendRequests: Array<SendRequest | OpReturnData>,
1015
- discardChange = false,
1016
- options?: SendRequestOptionsI
1017
- ) {
1018
- if (!this.privateKey) {
1019
- throw new Error(
1020
- `Wallet ${this.name} is missing either a network or private key`
1021
- );
1022
- }
1023
- if (!this.cashaddr) {
1024
- throw Error("attempted to send without a cashaddr");
1025
- }
1026
-
1027
- if (options && options.slpAware) {
1028
- this._slpAware = true;
1029
- }
1030
-
1031
- if (options && options.slpSemiAware) {
1032
- this._slpSemiAware = true;
1033
- }
1034
-
1035
- // get inputs from options or query all inputs
1036
- let utxos: UtxoI[];
1037
- if (options && options.utxoIds) {
1038
- utxos = options.utxoIds.map((utxoId) =>
1039
- UtxoItem.fromId(utxoId).asElectrum()
1040
- );
1041
- } else {
1042
- utxos = await this.getAddressUtxos(this.cashaddr);
1043
- }
1044
-
1045
- const bestHeight = await this.provider!.getBlockHeight()!;
1046
- const spendAmount = await sumSendRequestAmounts(sendRequests);
1047
-
1048
- if (utxos.length === 0) {
1049
- throw Error("There were no Unspent Outputs");
1050
- }
1051
- if (typeof spendAmount !== "bigint") {
1052
- throw Error("Couldn't get spend amount when building transaction");
1053
- }
1054
-
1055
- const relayFeePerByteInSatoshi = await getRelayFeeCache(this.provider!);
1056
- const feeEstimate = await getFeeAmount({
1057
- utxos: utxos,
1058
- sendRequests: sendRequests,
1059
- privateKey: this.privateKey,
1060
- relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
1061
- slpOutputs: [],
1062
- });
1063
-
1064
- const fundingUtxos = await getSuitableUtxos(
1065
- utxos,
1066
- BigInt(spendAmount) + BigInt(feeEstimate),
1067
- bestHeight
1068
- );
1069
- if (fundingUtxos.length === 0) {
1070
- throw Error(
1071
- "The available inputs couldn't satisfy the request with fees"
1072
- );
1073
- }
1074
- const fee = await getFeeAmount({
1075
- utxos: fundingUtxos,
1076
- sendRequests: sendRequests,
1077
- privateKey: this.privateKey,
1078
- relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
1079
- slpOutputs: [],
1080
- });
1081
- const encodedTransaction = await buildEncodedTransaction(
1082
- fundingUtxos,
1083
- sendRequests,
1084
- this.privateKey,
1085
- fee,
1086
- discardChange
1087
- );
1088
-
1089
- const awaitTransactionPropagation =
1090
- !options ||
1091
- options.awaitTransactionPropagation === undefined ||
1092
- options.awaitTransactionPropagation;
1093
-
1094
- return await this._submitTransaction(
1095
- encodedTransaction,
1096
- awaitTransactionPropagation
1097
- );
1098
- }
1099
-
1100
- // Submit a raw transaction
1101
- private async _submitTransaction(
1102
- transaction: Uint8Array,
1103
- awaitPropagation: boolean = true
1104
- ): Promise<string> {
1105
- if (!this.provider) {
1106
- throw Error("Wallet network provider was not initialized");
1107
- }
1108
- let rawTransaction = binToHex(transaction);
1109
- return await this.provider.sendRawTransaction(
1110
- rawTransaction,
1111
- awaitPropagation
1112
- );
1113
- }
1114
1188
  //#endregion Private implementation details
1115
1189
 
1116
1190
  //#region Signing
@@ -5,3 +5,13 @@ export enum WalletTypeEnum {
5
5
  Watch = "watch",
6
6
  PrivateKey = "privkey",
7
7
  }
8
+
9
+ export enum FeePaidByEnum {
10
+ change = "change",
11
+ first = "firstOutput",
12
+ any = "anyOutputs",
13
+ last = "lastOutput",
14
+ changeThenFirst = "changeThenFirst",
15
+ changeThenAny = "changeThenAny",
16
+ changeThenLast = "changeThenLast",
17
+ }
@@ -1,4 +1,4 @@
1
- import { WalletTypeEnum } from "./enum";
1
+ import { WalletTypeEnum, FeePaidByEnum } from "./enum";
2
2
  import { NetworkEnum } from "../enum";
3
3
  import { ImageI } from "../qr/interface";
4
4
  import { ElectrumRawTransaction } from "../network/interface";
@@ -50,6 +50,7 @@ export interface SendRequestOptionsI {
50
50
  slpSemiAware?: boolean; // a flag which requires an utxo to have more than 546 sats to be spendable and counted in the balance
51
51
  queryBalance?: boolean;
52
52
  awaitTransactionPropagation?: boolean;
53
+ feePaidBy?: FeePaidByEnum;
53
54
  }
54
55
 
55
56
  export interface MnemonicI {