beignet 0.0.1

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 (329) hide show
  1. package/.eslintignore +4 -0
  2. package/.eslintrc +40 -0
  3. package/.prettierrc +9 -0
  4. package/LICENSE +21 -0
  5. package/README.md +166 -0
  6. package/dist/electrum/constants.js +31 -0
  7. package/dist/electrum/constants.js.map +1 -0
  8. package/dist/electrum/index.js +552 -0
  9. package/dist/electrum/index.js.map +1 -0
  10. package/dist/index.js +23 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/shapes/electrum.js +14 -0
  13. package/dist/shapes/electrum.js.map +1 -0
  14. package/dist/shapes/index.js +19 -0
  15. package/dist/shapes/index.js.map +1 -0
  16. package/dist/shapes/wallet.js +115 -0
  17. package/dist/shapes/wallet.js.map +1 -0
  18. package/dist/transaction/index.js +692 -0
  19. package/dist/transaction/index.js.map +1 -0
  20. package/dist/types/electrum/constants.d.ts +7 -0
  21. package/dist/types/electrum/index.d.ts +85 -0
  22. package/dist/types/electrum.js +9 -0
  23. package/dist/types/electrum.js.map +1 -0
  24. package/dist/types/index.d.ts +6 -0
  25. package/dist/types/index.js +20 -0
  26. package/dist/types/index.js.map +1 -0
  27. package/dist/types/shapes/electrum.d.ts +5 -0
  28. package/dist/types/shapes/index.d.ts +2 -0
  29. package/dist/types/shapes/wallet.d.ts +10 -0
  30. package/dist/types/transaction/index.d.ts +92 -0
  31. package/dist/types/transaction.js +12 -0
  32. package/dist/types/transaction.js.map +1 -0
  33. package/dist/types/types/electrum.d.ts +113 -0
  34. package/dist/types/types/index.d.ts +3 -0
  35. package/dist/types/types/transaction.d.ts +51 -0
  36. package/dist/types/types/wallet.d.ts +400 -0
  37. package/dist/types/utils/conversion.d.ts +10 -0
  38. package/dist/types/utils/derivation-path.d.ts +19 -0
  39. package/dist/types/utils/electrum.d.ts +10 -0
  40. package/dist/types/utils/exchange-rate.d.ts +30 -0
  41. package/dist/types/utils/helpers.d.ts +23 -0
  42. package/dist/types/utils/index.d.ts +7 -0
  43. package/dist/types/utils/result.d.ts +16 -0
  44. package/dist/types/utils/transaction.d.ts +21 -0
  45. package/dist/types/utils/wallet.d.ts +47 -0
  46. package/dist/types/wallet/constants.d.ts +12 -0
  47. package/dist/types/wallet/index.d.ts +214 -0
  48. package/dist/types/wallet.js +36 -0
  49. package/dist/types/wallet.js.map +1 -0
  50. package/dist/utils/conversion.js +52 -0
  51. package/dist/utils/conversion.js.map +1 -0
  52. package/dist/utils/derivation-path.js +104 -0
  53. package/dist/utils/derivation-path.js.map +1 -0
  54. package/dist/utils/electrum.js +149 -0
  55. package/dist/utils/electrum.js.map +1 -0
  56. package/dist/utils/exchange-rate.js +49 -0
  57. package/dist/utils/exchange-rate.js.map +1 -0
  58. package/dist/utils/helpers.js +137 -0
  59. package/dist/utils/helpers.js.map +1 -0
  60. package/dist/utils/index.js +24 -0
  61. package/dist/utils/index.js.map +1 -0
  62. package/dist/utils/result.js +36 -0
  63. package/dist/utils/result.js.map +1 -0
  64. package/dist/utils/transaction.js +327 -0
  65. package/dist/utils/transaction.js.map +1 -0
  66. package/dist/utils/wallet.js +227 -0
  67. package/dist/utils/wallet.js.map +1 -0
  68. package/dist/wallet/constants.js +15 -0
  69. package/dist/wallet/constants.js.map +1 -0
  70. package/dist/wallet/index.js +2113 -0
  71. package/dist/wallet/index.js.map +1 -0
  72. package/docs/html/.nojekyll +1 -0
  73. package/docs/html/assets/highlight.css +22 -0
  74. package/docs/html/assets/main.js +58 -0
  75. package/docs/html/assets/search.js +1 -0
  76. package/docs/html/assets/style.css +1367 -0
  77. package/docs/html/classes/Electrum.html +812 -0
  78. package/docs/html/classes/Transaction.html +687 -0
  79. package/docs/html/classes/Wallet.html +2030 -0
  80. package/docs/html/enums/EAddressType.html +227 -0
  81. package/docs/html/enums/EAvailableNetworks.html +255 -0
  82. package/docs/html/enums/EBoostType.html +220 -0
  83. package/docs/html/enums/EFeeId.html +241 -0
  84. package/docs/html/enums/EPaymentType.html +220 -0
  85. package/docs/html/enums/EProtocol.html +220 -0
  86. package/docs/html/enums/EUnit.html +227 -0
  87. package/docs/html/functions/availableNetworks.html +200 -0
  88. package/docs/html/functions/constructByteCountParam.html +210 -0
  89. package/docs/html/functions/decodeOpReturnMessage.html +202 -0
  90. package/docs/html/functions/decodeRawTransaction.html +210 -0
  91. package/docs/html/functions/err.html +214 -0
  92. package/docs/html/functions/formatKeyDerivationPath.html +219 -0
  93. package/docs/html/functions/formatPeerData.html +207 -0
  94. package/docs/html/functions/generateMnemonic.html +223 -0
  95. package/docs/html/functions/generateWalletId.html +202 -0
  96. package/docs/html/functions/getAddressFromScriptPubKey.html +209 -0
  97. package/docs/html/functions/getAddressTypeFromPath.html +206 -0
  98. package/docs/html/functions/getByteCount.html +206 -0
  99. package/docs/html/functions/getDataFallback.html +207 -0
  100. package/docs/html/functions/getDefaultPort.html +209 -0
  101. package/docs/html/functions/getDefaultWalletData.html +200 -0
  102. package/docs/html/functions/getDefaultWalletDataKeys.html +200 -0
  103. package/docs/html/functions/getExchangeRates.html +200 -0
  104. package/docs/html/functions/getHighestUsedIndexFromTxHashes.html +216 -0
  105. package/docs/html/functions/getKeyDerivationPath.html +211 -0
  106. package/docs/html/functions/getKeyDerivationPathObject.html +216 -0
  107. package/docs/html/functions/getKeyDerivationPathString.html +220 -0
  108. package/docs/html/functions/getKeyValue.html +206 -0
  109. package/docs/html/functions/getPeers.html +211 -0
  110. package/docs/html/functions/getProtocolForPort.html +209 -0
  111. package/docs/html/functions/getScriptHash.html +210 -0
  112. package/docs/html/functions/getSeed.html +209 -0
  113. package/docs/html/functions/getSeedHash.html +206 -0
  114. package/docs/html/functions/getSha256.html +206 -0
  115. package/docs/html/functions/getStorageKeyValues.html +209 -0
  116. package/docs/html/functions/getTxFee.html +210 -0
  117. package/docs/html/functions/getWalletDataStorageKey.html +206 -0
  118. package/docs/html/functions/isValidBech32mEncodedString.html +211 -0
  119. package/docs/html/functions/objectKeys-1.html +211 -0
  120. package/docs/html/functions/objectsMatch.html +210 -0
  121. package/docs/html/functions/ok.html +214 -0
  122. package/docs/html/functions/parseOnChainPaymentRequest.html +204 -0
  123. package/docs/html/functions/reduceValue.html +215 -0
  124. package/docs/html/functions/removeDustOutputs.html +206 -0
  125. package/docs/html/functions/setReplaceByFee.html +210 -0
  126. package/docs/html/functions/shuffleArray.html +211 -0
  127. package/docs/html/functions/validateAddress.html +216 -0
  128. package/docs/html/functions/validateMnemonic.html +206 -0
  129. package/docs/html/functions/validateTransaction.html +206 -0
  130. package/docs/html/index.html +360 -0
  131. package/docs/html/interfaces/IAddInput.html +231 -0
  132. package/docs/html/interfaces/IAddress.html +247 -0
  133. package/docs/html/interfaces/IAddressData.html +231 -0
  134. package/docs/html/interfaces/IAddressType.html +199 -0
  135. package/docs/html/interfaces/IAddressTypeData.html +252 -0
  136. package/docs/html/interfaces/IAddresses.html +199 -0
  137. package/docs/html/interfaces/IBoostedTransaction.html +238 -0
  138. package/docs/html/interfaces/IBoostedTransactions.html +199 -0
  139. package/docs/html/interfaces/ICreateTransaction.html +224 -0
  140. package/docs/html/interfaces/ICustomGetAddress.html +231 -0
  141. package/docs/html/interfaces/ICustomGetScriptHash.html +224 -0
  142. package/docs/html/interfaces/IElectrumGetAddressBalanceRes.html +235 -0
  143. package/docs/html/interfaces/IExchangeRates.html +210 -0
  144. package/docs/html/interfaces/IFormattedPeerData.html +245 -0
  145. package/docs/html/interfaces/IFormattedTransaction.html +343 -0
  146. package/docs/html/interfaces/IFormattedTransactions.html +199 -0
  147. package/docs/html/interfaces/IGenerateAddresses.html +252 -0
  148. package/docs/html/interfaces/IGenerateAddressesResponse.html +224 -0
  149. package/docs/html/interfaces/IGetAddress.html +231 -0
  150. package/docs/html/interfaces/IGetAddressBalanceRes.html +226 -0
  151. package/docs/html/interfaces/IGetAddressByPath.html +224 -0
  152. package/docs/html/interfaces/IGetAddressHistoryResponse.html +269 -0
  153. package/docs/html/interfaces/IGetAddressResponse.html +231 -0
  154. package/docs/html/interfaces/IGetAddressScriptHashesHistoryResponse.html +245 -0
  155. package/docs/html/interfaces/IGetDerivationPath.html +259 -0
  156. package/docs/html/interfaces/IGetFeeEstimatesResponse.html +238 -0
  157. package/docs/html/interfaces/IGetHeaderResponse.html +245 -0
  158. package/docs/html/interfaces/IGetNextAvailableAddressResponse.html +238 -0
  159. package/docs/html/interfaces/IGetTransactions.html +245 -0
  160. package/docs/html/interfaces/IGetTransactionsFromInputs.html +245 -0
  161. package/docs/html/interfaces/IGetUtxosResponse.html +224 -0
  162. package/docs/html/interfaces/IHeader.html +231 -0
  163. package/docs/html/interfaces/IIndexes.html +238 -0
  164. package/docs/html/interfaces/IKeyDerivationPath.html +247 -0
  165. package/docs/html/interfaces/IKeyDerivationPathData.html +224 -0
  166. package/docs/html/interfaces/INewBlock.html +224 -0
  167. package/docs/html/interfaces/IOnchainFees.html +245 -0
  168. package/docs/html/interfaces/IOutput.html +231 -0
  169. package/docs/html/interfaces/IPeerData.html +231 -0
  170. package/docs/html/interfaces/IRbfData.html +252 -0
  171. package/docs/html/interfaces/ISend.html +224 -0
  172. package/docs/html/interfaces/ISendTransaction.html +322 -0
  173. package/docs/html/interfaces/ISendTx.html +231 -0
  174. package/docs/html/interfaces/ISetupTransaction.html +238 -0
  175. package/docs/html/interfaces/ISubscribeToAddress.html +247 -0
  176. package/docs/html/interfaces/ISubscribeToHeader.html +245 -0
  177. package/docs/html/interfaces/ITargets.html +238 -0
  178. package/docs/html/interfaces/ITransaction.html +281 -0
  179. package/docs/html/interfaces/ITxHash.html +217 -0
  180. package/docs/html/interfaces/ITxHashes.html +235 -0
  181. package/docs/html/interfaces/IUtxo.html +275 -0
  182. package/docs/html/interfaces/IVin.html +252 -0
  183. package/docs/html/interfaces/IVout.html +246 -0
  184. package/docs/html/interfaces/IWallet.html +350 -0
  185. package/docs/html/interfaces/IWalletData.html +343 -0
  186. package/docs/html/types/ElectrumConnectionPubSub.html +233 -0
  187. package/docs/html/types/ElectrumConnectionSubscription.html +204 -0
  188. package/docs/html/types/InputData.html +203 -0
  189. package/docs/html/types/ObjectKeys.html +198 -0
  190. package/docs/html/types/Result.html +201 -0
  191. package/docs/html/types/TAddressIndexInfo.html +204 -0
  192. package/docs/html/types/TAddressLabel.html +193 -0
  193. package/docs/html/types/TAddressType.html +193 -0
  194. package/docs/html/types/TAddressTypeContent.html +198 -0
  195. package/docs/html/types/TAddressTypes.html +193 -0
  196. package/docs/html/types/TAvailableNetworks.html +193 -0
  197. package/docs/html/types/TConnectToElectrumRes.html +193 -0
  198. package/docs/html/types/TDecodeRawTx.html +214 -0
  199. package/docs/html/types/TElectrumNetworks.html +193 -0
  200. package/docs/html/types/TGetAddressHistory.html +200 -0
  201. package/docs/html/types/TGetByteCountInput.html +193 -0
  202. package/docs/html/types/TGetByteCountInputs.html +193 -0
  203. package/docs/html/types/TGetByteCountOutput.html +193 -0
  204. package/docs/html/types/TGetByteCountOutputs.html +193 -0
  205. package/docs/html/types/TGetData.html +211 -0
  206. package/docs/html/types/TGetTotalFeeObj.html +204 -0
  207. package/docs/html/types/TKeyDerivationAccount.html +193 -0
  208. package/docs/html/types/TKeyDerivationChange.html +193 -0
  209. package/docs/html/types/TKeyDerivationCoinType.html +193 -0
  210. package/docs/html/types/TKeyDerivationIndex.html +193 -0
  211. package/docs/html/types/TKeyDerivationPurpose.html +193 -0
  212. package/docs/html/types/TMessageDataMap.html +210 -0
  213. package/docs/html/types/TMessageKeys.html +193 -0
  214. package/docs/html/types/TOnMessage.html +213 -0
  215. package/docs/html/types/TProcessUnconfirmedTransactions.html +202 -0
  216. package/docs/html/types/TProtocol.html +193 -0
  217. package/docs/html/types/TServer.html +204 -0
  218. package/docs/html/types/TSetData.html +213 -0
  219. package/docs/html/types/TSetupTransactionResponse.html +193 -0
  220. package/docs/html/types/TStorage.html +200 -0
  221. package/docs/html/types/TSubscribedReceive.html +193 -0
  222. package/docs/html/types/TTransactionMessage.html +198 -0
  223. package/docs/html/types/TTxResponse.html +206 -0
  224. package/docs/html/types/TTxResult.html +200 -0
  225. package/docs/html/types/TUnspentAddressScriptHashData.html +198 -0
  226. package/docs/html/types/TWalletDataKeys.html +193 -0
  227. package/docs/html/variables/defaultElectrumPorts.html +193 -0
  228. package/docs/html/variables/electrumConnection.html +199 -0
  229. package/docs/html/variables/mostUsedExchangeTickers.html +241 -0
  230. package/docs/markdown/.nojekyll +1 -0
  231. package/docs/markdown/README.md +1875 -0
  232. package/docs/markdown/classes/Electrum.md +718 -0
  233. package/docs/markdown/classes/Transaction.md +536 -0
  234. package/docs/markdown/classes/Wallet.md +2189 -0
  235. package/docs/markdown/enums/EAddressType.md +41 -0
  236. package/docs/markdown/enums/EAvailableNetworks.md +85 -0
  237. package/docs/markdown/enums/EBoostType.md +30 -0
  238. package/docs/markdown/enums/EFeeId.md +63 -0
  239. package/docs/markdown/enums/EPaymentType.md +30 -0
  240. package/docs/markdown/enums/EProtocol.md +30 -0
  241. package/docs/markdown/enums/EUnit.md +41 -0
  242. package/docs/markdown/interfaces/IAddInput.md +41 -0
  243. package/docs/markdown/interfaces/IAddress.md +69 -0
  244. package/docs/markdown/interfaces/IAddressData.md +41 -0
  245. package/docs/markdown/interfaces/IAddressType.md +7 -0
  246. package/docs/markdown/interfaces/IAddressTypeData.md +74 -0
  247. package/docs/markdown/interfaces/IAddresses.md +7 -0
  248. package/docs/markdown/interfaces/IBoostedTransaction.md +52 -0
  249. package/docs/markdown/interfaces/IBoostedTransactions.md +7 -0
  250. package/docs/markdown/interfaces/ICreateTransaction.md +30 -0
  251. package/docs/markdown/interfaces/ICustomGetAddress.md +41 -0
  252. package/docs/markdown/interfaces/ICustomGetScriptHash.md +30 -0
  253. package/docs/markdown/interfaces/IElectrumGetAddressBalanceRes.md +55 -0
  254. package/docs/markdown/interfaces/IExchangeRates.md +7 -0
  255. package/docs/markdown/interfaces/IFormattedPeerData.md +63 -0
  256. package/docs/markdown/interfaces/IFormattedTransaction.md +217 -0
  257. package/docs/markdown/interfaces/IFormattedTransactions.md +7 -0
  258. package/docs/markdown/interfaces/IGenerateAddresses.md +74 -0
  259. package/docs/markdown/interfaces/IGenerateAddressesResponse.md +30 -0
  260. package/docs/markdown/interfaces/IGetAddress.md +41 -0
  261. package/docs/markdown/interfaces/IGetAddressBalanceRes.md +36 -0
  262. package/docs/markdown/interfaces/IGetAddressByPath.md +30 -0
  263. package/docs/markdown/interfaces/IGetAddressHistoryResponse.md +121 -0
  264. package/docs/markdown/interfaces/IGetAddressResponse.md +41 -0
  265. package/docs/markdown/interfaces/IGetAddressScriptHashesHistoryResponse.md +63 -0
  266. package/docs/markdown/interfaces/IGetDerivationPath.md +100 -0
  267. package/docs/markdown/interfaces/IGetFeeEstimatesResponse.md +52 -0
  268. package/docs/markdown/interfaces/IGetHeaderResponse.md +63 -0
  269. package/docs/markdown/interfaces/IGetNextAvailableAddressResponse.md +52 -0
  270. package/docs/markdown/interfaces/IGetTransactions.md +63 -0
  271. package/docs/markdown/interfaces/IGetTransactionsFromInputs.md +63 -0
  272. package/docs/markdown/interfaces/IGetUtxosResponse.md +30 -0
  273. package/docs/markdown/interfaces/IHeader.md +41 -0
  274. package/docs/markdown/interfaces/IIndexes.md +52 -0
  275. package/docs/markdown/interfaces/IKeyDerivationPath.md +69 -0
  276. package/docs/markdown/interfaces/IKeyDerivationPathData.md +30 -0
  277. package/docs/markdown/interfaces/INewBlock.md +30 -0
  278. package/docs/markdown/interfaces/IOnchainFees.md +63 -0
  279. package/docs/markdown/interfaces/IOutput.md +41 -0
  280. package/docs/markdown/interfaces/IPeerData.md +41 -0
  281. package/docs/markdown/interfaces/IRbfData.md +74 -0
  282. package/docs/markdown/interfaces/ISend.md +30 -0
  283. package/docs/markdown/interfaces/ISendTransaction.md +184 -0
  284. package/docs/markdown/interfaces/ISendTx.md +41 -0
  285. package/docs/markdown/interfaces/ISetupTransaction.md +52 -0
  286. package/docs/markdown/interfaces/ISubscribeToAddress.md +60 -0
  287. package/docs/markdown/interfaces/ISubscribeToHeader.md +59 -0
  288. package/docs/markdown/interfaces/ITargets.md +52 -0
  289. package/docs/markdown/interfaces/ITransaction.md +88 -0
  290. package/docs/markdown/interfaces/ITxHash.md +19 -0
  291. package/docs/markdown/interfaces/ITxHashes.md +55 -0
  292. package/docs/markdown/interfaces/IUtxo.md +112 -0
  293. package/docs/markdown/interfaces/IVin.md +70 -0
  294. package/docs/markdown/interfaces/IVout.md +52 -0
  295. package/docs/markdown/interfaces/IWallet.md +209 -0
  296. package/docs/markdown/interfaces/IWalletData.md +217 -0
  297. package/example/helpers.ts +76 -0
  298. package/example/index.ts +77 -0
  299. package/package.json +69 -0
  300. package/src/electrum/constants.ts +28 -0
  301. package/src/electrum/index.ts +838 -0
  302. package/src/index.ts +6 -0
  303. package/src/shapes/electrum.ts +13 -0
  304. package/src/shapes/index.ts +2 -0
  305. package/src/shapes/wallet.ts +133 -0
  306. package/src/transaction/index.ts +1078 -0
  307. package/src/types/electrum.ts +139 -0
  308. package/src/types/index.ts +3 -0
  309. package/src/types/transaction.ts +58 -0
  310. package/src/types/wallet.ts +503 -0
  311. package/src/utils/conversion.ts +88 -0
  312. package/src/utils/derivation-path.ts +171 -0
  313. package/src/utils/electrum.ts +188 -0
  314. package/src/utils/exchange-rate.ts +70 -0
  315. package/src/utils/helpers.ts +191 -0
  316. package/src/utils/index.ts +7 -0
  317. package/src/utils/result.ts +79 -0
  318. package/src/utils/transaction.ts +417 -0
  319. package/src/utils/wallet.ts +351 -0
  320. package/src/wallet/constants.ts +24 -0
  321. package/src/wallet/index.ts +3304 -0
  322. package/tests/constants.ts +9 -0
  323. package/tests/derivation.test.ts +146 -0
  324. package/tests/electrum.test.ts +137 -0
  325. package/tests/storage.test.ts +222 -0
  326. package/tests/transaction.test.ts +187 -0
  327. package/tests/wallet.test.ts +307 -0
  328. package/tsconfig.json +32 -0
  329. package/typedoc.json +5 -0
@@ -0,0 +1,2113 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.Wallet = void 0;
30
+ const bitcoin = __importStar(require("bitcoinjs-lib"));
31
+ const bitcoinjs_lib_1 = require("bitcoinjs-lib");
32
+ const bip32_1 = __importDefault(require("bip32"));
33
+ const ecc = __importStar(require("@bitcoinerlab/secp256k1"));
34
+ const types_1 = require("../types");
35
+ const utils_1 = require("../utils");
36
+ const shapes_1 = require("../shapes");
37
+ const electrum_1 = require("../electrum");
38
+ const transaction_1 = require("../transaction");
39
+ const constants_1 = require("./constants");
40
+ const lodash_clonedeep_1 = __importDefault(require("lodash.clonedeep"));
41
+ const conversion_1 = require("../utils/conversion");
42
+ const bip39 = __importStar(require("bip39"));
43
+ const bip32 = (0, bip32_1.default)(ecc);
44
+ class Wallet {
45
+ constructor({ mnemonic, passphrase, name, network = types_1.EAvailableNetworks.mainnet, addressType = types_1.EAddressType.p2wpkh, storage, electrumOptions, onMessage = () => null, customGetAddress, customGetScriptHash, rbf = false, selectedFeeId = types_1.EFeeId.normal }) {
46
+ var _a;
47
+ this._pendingRefreshPromises = [];
48
+ this.getReceiveAddress = async ({ addressType = this.data.addressType }) => {
49
+ try {
50
+ const wallet = this.data;
51
+ const addressIndex = wallet.addressIndex;
52
+ const receiveAddress = addressIndex[addressType].address;
53
+ if (receiveAddress) {
54
+ return (0, utils_1.ok)(receiveAddress);
55
+ }
56
+ const addresses = wallet === null || wallet === void 0 ? void 0 : wallet.addresses[addressType];
57
+ if (Object.keys(addresses).length > 0 &&
58
+ addressIndex[addressType].index < 0) {
59
+ const address = Object.values(addresses).find(({ index }) => index === 0);
60
+ if (address) {
61
+ return (0, utils_1.ok)(address.address);
62
+ }
63
+ }
64
+ const generatedAddress = await this.generateNewReceiveAddress({
65
+ addressType
66
+ });
67
+ if (generatedAddress.isOk()) {
68
+ return (0, utils_1.ok)(generatedAddress.value.address);
69
+ }
70
+ else {
71
+ console.log(generatedAddress.error.message);
72
+ }
73
+ return (0, utils_1.err)('No receive address available.');
74
+ }
75
+ catch (e) {
76
+ return (0, utils_1.err)(e);
77
+ }
78
+ };
79
+ this.getBoostedTransactionParents = ({ txid, boostedTransactions }) => {
80
+ var _a;
81
+ if (!boostedTransactions) {
82
+ boostedTransactions = this.getBoostedTransactions();
83
+ }
84
+ const boostObj = Object.values(boostedTransactions).find((boostObject) => {
85
+ return boostObject.childTransaction === txid;
86
+ });
87
+ return (_a = boostObj === null || boostObj === void 0 ? void 0 : boostObj.parentTransactions) !== null && _a !== void 0 ? _a : [];
88
+ };
89
+ this.getBoostedTransactions = () => {
90
+ return this.data.boostedTransactions;
91
+ };
92
+ this.getBip32Interface = async () => {
93
+ const network = bitcoinjs_lib_1.networks[this._network];
94
+ const seed = await bip39.mnemonicToSeed(this._mnemonic, this._passphrase);
95
+ const root = bip32.fromSeed(seed, network);
96
+ return (0, utils_1.ok)(root);
97
+ };
98
+ if (!mnemonic)
99
+ throw new Error('No mnemonic specified.');
100
+ if (!(0, utils_1.validateMnemonic)(mnemonic))
101
+ throw new Error('Invalid mnemonic.');
102
+ if (name && name.includes('-'))
103
+ throw new Error('Wallet name cannot include a hyphen (-).');
104
+ this._network = network;
105
+ this._mnemonic = mnemonic;
106
+ this._passphrase = passphrase !== null && passphrase !== void 0 ? passphrase : '';
107
+ this._seed = (0, utils_1.getSeed)(this._mnemonic, this._passphrase);
108
+ this._root = bip32.fromSeed(this._seed, this.getBitcoinNetwork(this._network));
109
+ this._data = Object.assign(Object.assign({}, (0, utils_1.getDefaultWalletData)()), { addressType });
110
+ this._getData = (_a = storage === null || storage === void 0 ? void 0 : storage.getData) !== null && _a !== void 0 ? _a : utils_1.getDataFallback;
111
+ this._setData = storage === null || storage === void 0 ? void 0 : storage.setData;
112
+ if (customGetAddress)
113
+ this._customGetAddress = customGetAddress;
114
+ if (customGetScriptHash)
115
+ this._customGetScriptHash = customGetScriptHash;
116
+ this.id = (0, utils_1.generateWalletId)(this._seed);
117
+ this.name = name !== null && name !== void 0 ? name : this.id;
118
+ this.exchangeRates = {};
119
+ this.transaction = new transaction_1.Transaction({
120
+ wallet: this
121
+ });
122
+ this.feeEstimates = (0, lodash_clonedeep_1.default)(shapes_1.defaultFeesShape);
123
+ this.onMessage = onMessage;
124
+ this.electrumOptions = electrumOptions;
125
+ this.electrum = new electrum_1.Electrum({
126
+ wallet: this,
127
+ network: this.network,
128
+ servers: electrumOptions === null || electrumOptions === void 0 ? void 0 : electrumOptions.servers,
129
+ tls: electrumOptions === null || electrumOptions === void 0 ? void 0 : electrumOptions.tls,
130
+ net: electrumOptions === null || electrumOptions === void 0 ? void 0 : electrumOptions.net
131
+ });
132
+ this.rbf = rbf;
133
+ this.selectedFeeId = selectedFeeId;
134
+ this.isRefreshing = false;
135
+ this.isSwitchingNetworks = false;
136
+ }
137
+ get data() {
138
+ return this._data;
139
+ }
140
+ get network() {
141
+ return this._network;
142
+ }
143
+ static async create(params) {
144
+ try {
145
+ const wallet = new Wallet(params);
146
+ const res = await wallet.setWalletData();
147
+ if (res.isErr())
148
+ return (0, utils_1.err)(res.error.message);
149
+ wallet.updateExchangeRates();
150
+ wallet.updateFeeEstimates();
151
+ console.log('Syncing Wallet...');
152
+ await wallet.refreshWallet({});
153
+ return (0, utils_1.ok)(wallet);
154
+ }
155
+ catch (e) {
156
+ return (0, utils_1.err)(e);
157
+ }
158
+ }
159
+ async switchNetwork(network, servers) {
160
+ var _a, _b;
161
+ this.isSwitchingNetworks = true;
162
+ await this.electrum.disconnect();
163
+ this._network = network;
164
+ this._data = (0, utils_1.getDefaultWalletData)();
165
+ const params = Object.assign(Object.assign({}, this), { mnemonic: this._mnemonic, passphrase: this._passphrase, network, electrumOptions: {
166
+ servers,
167
+ tls: (_a = this.electrumOptions) === null || _a === void 0 ? void 0 : _a.tls,
168
+ net: (_b = this.electrumOptions) === null || _b === void 0 ? void 0 : _b.net
169
+ }, storage: {
170
+ getData: this._getData,
171
+ setData: this._setData
172
+ }, data: (0, utils_1.getDefaultWalletData)() });
173
+ const createRes = await Wallet.create(params);
174
+ if (createRes.isErr())
175
+ return (0, utils_1.err)(createRes.error.message);
176
+ Object.assign(this, createRes.value);
177
+ await this.updateFeeEstimates(true);
178
+ this.isSwitchingNetworks = false;
179
+ return (0, utils_1.ok)(`Successfully switched to ${network}.`);
180
+ }
181
+ async updateAddressType(addressType) {
182
+ this._data.addressType = addressType;
183
+ await this.saveWalletData('addressType', addressType);
184
+ await this.refreshWallet({});
185
+ }
186
+ async refreshWallet({ scanAllAddresses = false, updateAllAddressTypes = true } = {}) {
187
+ if (this.isRefreshing) {
188
+ return new Promise((resolve) => {
189
+ this._pendingRefreshPromises.push(resolve);
190
+ });
191
+ }
192
+ this.isRefreshing = true;
193
+ try {
194
+ await this.setZeroIndexAddresses();
195
+ const addressType = updateAllAddressTypes
196
+ ? undefined
197
+ : this.data.addressType;
198
+ const r1 = await this.updateAddressIndexes({ addressType });
199
+ if (r1.isErr()) {
200
+ return this._handleRefreshError(r1.error.message);
201
+ }
202
+ const r2 = await this.getUtxos({ scanAllAddresses });
203
+ if (r2.isErr()) {
204
+ return this._handleRefreshError(r2.error.message);
205
+ }
206
+ const r3 = await this.updateTransactions({ scanAllAddresses });
207
+ if (r3.isErr()) {
208
+ return this._handleRefreshError(r3.error.message);
209
+ }
210
+ await this.electrum.subscribeToAddresses();
211
+ this._resolveAllPendingRefreshPromises((0, utils_1.ok)(this.data));
212
+ return (0, utils_1.ok)(this.data);
213
+ }
214
+ catch (e) {
215
+ return this._handleRefreshError(e);
216
+ }
217
+ }
218
+ _resolveAllPendingRefreshPromises(result) {
219
+ this.isRefreshing = false;
220
+ while (this._pendingRefreshPromises.length > 0) {
221
+ const resolve = this._pendingRefreshPromises.shift();
222
+ if (resolve) {
223
+ resolve(result);
224
+ }
225
+ }
226
+ }
227
+ _handleRefreshError(errorMessage) {
228
+ this.isRefreshing = false;
229
+ this._resolveAllPendingRefreshPromises((0, utils_1.err)(errorMessage));
230
+ return (0, utils_1.err)(errorMessage);
231
+ }
232
+ async setWalletData() {
233
+ try {
234
+ const storageIdCheckRes = await this.storageIdCheck(this.id);
235
+ if (storageIdCheckRes.isErr())
236
+ return (0, utils_1.err)(storageIdCheckRes.error.message);
237
+ this._data = (0, utils_1.getDefaultWalletData)();
238
+ const walletDataResponse = await this.getWalletData();
239
+ if (walletDataResponse.isErr())
240
+ return (0, utils_1.err)(walletDataResponse.error.message);
241
+ this._data = walletDataResponse.value;
242
+ return (0, utils_1.ok)(true);
243
+ }
244
+ catch (e) {
245
+ return (0, utils_1.err)(e);
246
+ }
247
+ }
248
+ async storageIdCheck(id) {
249
+ const storageKey = this.getWalletDataKey('id');
250
+ const res = await this._getData(storageKey);
251
+ if (res.isErr() || !res.value) {
252
+ this._data.id = id;
253
+ await this.saveWalletData('id', id);
254
+ return (0, utils_1.ok)('Saved ID to storage.');
255
+ }
256
+ if (res.value !== id) {
257
+ const msg = 'Mismatched id found in storage. Change the wallet name or delete the old wallet from storage and try again.';
258
+ console.log(msg);
259
+ return (0, utils_1.err)(msg);
260
+ }
261
+ return (0, utils_1.ok)("ID's match, it's safe to continue.");
262
+ }
263
+ getWalletDataKey(key) {
264
+ return (0, utils_1.getWalletDataStorageKey)(this.name, this._network, key);
265
+ }
266
+ async getWalletData() {
267
+ try {
268
+ const walletDataKeys = (0, utils_1.getDefaultWalletDataKeys)();
269
+ const walletData = (0, utils_1.getDefaultWalletData)();
270
+ for (const key of walletDataKeys) {
271
+ let dataResult;
272
+ try {
273
+ const walletDataKey = this.getWalletDataKey(key);
274
+ const getDataRes = await this._getData(walletDataKey);
275
+ if (getDataRes.isErr()) {
276
+ return (0, utils_1.err)(dataResult.error.message);
277
+ }
278
+ dataResult = getDataRes === null || getDataRes === void 0 ? void 0 : getDataRes.value;
279
+ }
280
+ catch (e) {
281
+ console.log(e);
282
+ }
283
+ const data = dataResult !== null && dataResult !== void 0 ? dataResult : walletData[key];
284
+ switch (key) {
285
+ case 'id':
286
+ walletData[key] = data;
287
+ break;
288
+ case 'addressType':
289
+ walletData[key] = data;
290
+ break;
291
+ case 'addresses':
292
+ case 'changeAddresses':
293
+ walletData[key] = data;
294
+ break;
295
+ case 'addressIndex':
296
+ case 'changeAddressIndex':
297
+ walletData[key] = data;
298
+ break;
299
+ case 'lastUsedAddressIndex':
300
+ case 'lastUsedChangeAddressIndex':
301
+ walletData[key] = data;
302
+ break;
303
+ case 'utxos':
304
+ walletData[key] = data;
305
+ break;
306
+ case 'blacklistedUtxos':
307
+ walletData[key] = data;
308
+ break;
309
+ case 'unconfirmedTransactions':
310
+ case 'transactions':
311
+ walletData[key] = data;
312
+ break;
313
+ case 'transaction':
314
+ walletData[key] = data;
315
+ break;
316
+ case 'balance':
317
+ walletData[key] = data;
318
+ break;
319
+ case 'header':
320
+ walletData[key] = data;
321
+ break;
322
+ case 'boostedTransactions':
323
+ walletData[key] = data;
324
+ break;
325
+ case 'selectedFeeId':
326
+ walletData[key] = data;
327
+ break;
328
+ case 'exchangeRates':
329
+ walletData[key] = data;
330
+ break;
331
+ case 'feeEstimates':
332
+ walletData[key] = data;
333
+ break;
334
+ default:
335
+ return (0, utils_1.err)(`Unhandled key in getWalletData: ${key}`);
336
+ }
337
+ }
338
+ return (0, utils_1.ok)(walletData);
339
+ }
340
+ catch (e) {
341
+ console.log(e);
342
+ return (0, utils_1.err)(e);
343
+ }
344
+ }
345
+ getBitcoinNetwork(network) {
346
+ if (!network)
347
+ network = this._network;
348
+ return bitcoin.networks[network];
349
+ }
350
+ isValid(mnemonic) {
351
+ return mnemonic === this._mnemonic && (0, utils_1.validateMnemonic)(mnemonic);
352
+ }
353
+ async _getAddress(path, addressType) {
354
+ var _a, _b, _c;
355
+ if (this._customGetAddress) {
356
+ const data = {
357
+ path,
358
+ type: addressType,
359
+ selectedNetwork: this.electrum.getElectrumNetwork(this._network)
360
+ };
361
+ const res = await this._customGetAddress(data);
362
+ if (res.isErr()) {
363
+ return {
364
+ address: '',
365
+ path,
366
+ publicKey: ''
367
+ };
368
+ }
369
+ return res.value;
370
+ }
371
+ const keyPair = this._root.derivePath(path);
372
+ let address;
373
+ switch (addressType) {
374
+ case types_1.EAddressType.p2wpkh:
375
+ address =
376
+ (_a = bitcoin.payments.p2wpkh({
377
+ pubkey: keyPair.publicKey,
378
+ network: this.getBitcoinNetwork()
379
+ }).address) !== null && _a !== void 0 ? _a : '';
380
+ break;
381
+ case types_1.EAddressType.p2sh:
382
+ address =
383
+ (_b = bitcoin.payments.p2sh({
384
+ redeem: bitcoin.payments.p2wpkh({
385
+ pubkey: keyPair.publicKey,
386
+ network: this.getBitcoinNetwork()
387
+ }),
388
+ network: this.getBitcoinNetwork()
389
+ }).address) !== null && _b !== void 0 ? _b : '';
390
+ break;
391
+ case types_1.EAddressType.p2pkh:
392
+ address =
393
+ (_c = bitcoin.payments.p2pkh({
394
+ pubkey: keyPair.publicKey,
395
+ network: this.getBitcoinNetwork()
396
+ }).address) !== null && _c !== void 0 ? _c : '';
397
+ break;
398
+ }
399
+ return {
400
+ address,
401
+ path,
402
+ publicKey: keyPair.publicKey.toString('hex')
403
+ };
404
+ }
405
+ async getAddress({ index, changeAddress = false, addressType = this.data.addressType } = {}) {
406
+ try {
407
+ if (index === undefined) {
408
+ const addressIndex = this.data.addressIndex[addressType];
409
+ index = addressIndex.index >= 0 ? String(addressIndex.index) : '0';
410
+ }
411
+ const pathRes = (0, utils_1.getKeyDerivationPathString)({
412
+ addressType,
413
+ changeAddress,
414
+ index,
415
+ network: this._network
416
+ });
417
+ if (pathRes.isErr()) {
418
+ return '';
419
+ }
420
+ const path = pathRes.value;
421
+ const res = await this._getAddress(path, addressType);
422
+ if (!(res === null || res === void 0 ? void 0 : res.address))
423
+ return '';
424
+ return res.address;
425
+ }
426
+ catch (_a) {
427
+ return '';
428
+ }
429
+ }
430
+ async getAddressByPath({ path, addressType }) {
431
+ if (!path) {
432
+ return (0, utils_1.err)('No path specified');
433
+ }
434
+ if (!addressType) {
435
+ const res = (0, utils_1.getAddressTypeFromPath)(path);
436
+ if (res.isErr())
437
+ return (0, utils_1.err)(res.error.message);
438
+ addressType = res.value;
439
+ }
440
+ try {
441
+ const getAddressRes = await this._getAddress(path, addressType);
442
+ if (!(getAddressRes === null || getAddressRes === void 0 ? void 0 : getAddressRes.address))
443
+ return (0, utils_1.err)('Unable to get address.');
444
+ return (0, utils_1.ok)(getAddressRes);
445
+ }
446
+ catch (e) {
447
+ return (0, utils_1.err)(e);
448
+ }
449
+ }
450
+ async connectToElectrum(servers) {
451
+ var _a;
452
+ const res = await this.electrum.connectToElectrum({
453
+ network: this._network,
454
+ servers: servers !== null && servers !== void 0 ? servers : (_a = this.electrumOptions) === null || _a === void 0 ? void 0 : _a.servers
455
+ });
456
+ let msg = 'Unable to connect to Electrum server.';
457
+ if (res.isErr()) {
458
+ console.log(msg);
459
+ return (0, utils_1.err)(msg);
460
+ }
461
+ msg = 'Connected to Electrum server.';
462
+ return (0, utils_1.ok)(msg);
463
+ }
464
+ async getAddressBalance(address) {
465
+ const scriptHash = await this.getScriptHash({
466
+ address,
467
+ network: this._network
468
+ });
469
+ const res = await this.electrum.getAddressBalance(scriptHash);
470
+ if (res.error)
471
+ return (0, utils_1.err)('Unable to get address balance at this time.');
472
+ return (0, utils_1.ok)({ unconfirmed: res.unconfirmed, confirmed: res.confirmed });
473
+ }
474
+ async getAddressesBalance(addresses = []) {
475
+ try {
476
+ const network = this._network;
477
+ const scriptHashes = await Promise.all(addresses.map(async (address) => {
478
+ return await this.getScriptHash({ address, network });
479
+ }));
480
+ const res = await this.electrum.getAddressScriptHashBalances(scriptHashes);
481
+ if (res.error) {
482
+ return (0, utils_1.err)(res.data);
483
+ }
484
+ return (0, utils_1.ok)(res.data.reduce((acc, cur) => {
485
+ var _a, _b, _c, _d;
486
+ return (acc +
487
+ Number((_b = (_a = cur.result) === null || _a === void 0 ? void 0 : _a.confirmed) !== null && _b !== void 0 ? _b : 0) +
488
+ Number((_d = (_c = cur.result) === null || _c === void 0 ? void 0 : _c.unconfirmed) !== null && _d !== void 0 ? _d : 0));
489
+ }, 0) || 0);
490
+ }
491
+ catch (e) {
492
+ return (0, utils_1.err)(e);
493
+ }
494
+ }
495
+ async getScriptHash({ address, network }) {
496
+ if (this._customGetScriptHash) {
497
+ const selectedNetwork = this.electrum.getElectrumNetwork(network);
498
+ return await this._customGetScriptHash({ address, selectedNetwork });
499
+ }
500
+ return (0, utils_1.getScriptHash)({ address, network });
501
+ }
502
+ getPrivateKey(path) {
503
+ const keyPair = this._root.derivePath(path);
504
+ return keyPair.toWIF();
505
+ }
506
+ async getScriptHashBalance(scriptHash) {
507
+ const res = await this.electrum.getAddressBalance(scriptHash);
508
+ if (res.error)
509
+ return (0, utils_1.err)('Unable to get address balance at this time.');
510
+ return (0, utils_1.ok)({ unconfirmed: res.unconfirmed, confirmed: res.confirmed });
511
+ }
512
+ getBalance() {
513
+ var _a, _b;
514
+ return (_b = (_a = this === null || this === void 0 ? void 0 : this.data) === null || _a === void 0 ? void 0 : _a.balance) !== null && _b !== void 0 ? _b : 0;
515
+ }
516
+ async generateAddresses({ addressAmount = 10, changeAddressAmount = 10, addressIndex = 0, changeAddressIndex = 0, keyDerivationPath, addressType = this.data.addressType }) {
517
+ const network = this._network;
518
+ try {
519
+ if (!keyDerivationPath) {
520
+ const keyDerivationPathResponse = (0, utils_1.getKeyDerivationPath)({
521
+ network,
522
+ addressType
523
+ });
524
+ if (keyDerivationPathResponse.isErr())
525
+ return (0, utils_1.err)(keyDerivationPathResponse.error.message);
526
+ keyDerivationPath = keyDerivationPathResponse.value;
527
+ }
528
+ const addresses = {};
529
+ const changeAddresses = {};
530
+ const addressArray = new Array(addressAmount).fill(null);
531
+ const changeAddressArray = new Array(changeAddressAmount).fill(null);
532
+ await Promise.all(addressArray.map(async (_item, i) => {
533
+ const index = i + addressIndex;
534
+ const path = Object.assign({}, keyDerivationPath);
535
+ path.index = `${index}`;
536
+ const addressPath = (0, utils_1.formatKeyDerivationPath)({
537
+ path,
538
+ network,
539
+ changeAddress: false,
540
+ index: `${index}`
541
+ });
542
+ if (addressPath.isErr()) {
543
+ throw addressPath.error;
544
+ }
545
+ const address = await this.getAddressByPath({
546
+ path: addressPath.value.pathString
547
+ });
548
+ if (address.isErr()) {
549
+ throw address.error;
550
+ }
551
+ const scriptHash = await this.getScriptHash({
552
+ address: address.value.address,
553
+ network
554
+ });
555
+ if (!scriptHash) {
556
+ throw new Error('Unable to get script hash.');
557
+ }
558
+ addresses[scriptHash] = Object.assign(Object.assign({}, address.value), { index,
559
+ scriptHash });
560
+ }));
561
+ await Promise.all(changeAddressArray.map(async (_item, i) => {
562
+ const index = i + changeAddressIndex;
563
+ const path = Object.assign({}, keyDerivationPath);
564
+ path.index = `${index}`;
565
+ const changeAddressPath = (0, utils_1.formatKeyDerivationPath)({
566
+ path,
567
+ network,
568
+ changeAddress: true,
569
+ index: `${index}`
570
+ });
571
+ if (changeAddressPath.isErr()) {
572
+ throw changeAddressPath.error;
573
+ }
574
+ const address = await this.getAddressByPath({
575
+ path: changeAddressPath.value.pathString
576
+ });
577
+ if (address.isErr()) {
578
+ throw address.error;
579
+ }
580
+ const scriptHash = await this.getScriptHash({
581
+ address: address.value.address,
582
+ network
583
+ });
584
+ if (!scriptHash) {
585
+ throw new Error('Unable to get script hash.');
586
+ }
587
+ changeAddresses[scriptHash] = Object.assign(Object.assign({}, address.value), { index,
588
+ scriptHash });
589
+ }));
590
+ return (0, utils_1.ok)({ addresses, changeAddresses });
591
+ }
592
+ catch (e) {
593
+ return (0, utils_1.err)(e);
594
+ }
595
+ }
596
+ async checkElectrumConnection() {
597
+ const isConnected = this.electrum.connectedToElectrum;
598
+ if (!isConnected) {
599
+ return await this.connectToElectrum();
600
+ }
601
+ const pingRes = await this.electrum.isConnected();
602
+ if (pingRes)
603
+ return (0, utils_1.ok)('Is connected to Electrum.Z');
604
+ return (0, utils_1.err)('Failed Electrum connection check.');
605
+ }
606
+ async getNextAvailableAddress(addressType) {
607
+ const checkRes = await this.checkElectrumConnection();
608
+ if (checkRes.isErr())
609
+ return (0, utils_1.err)(checkRes.error.message);
610
+ try {
611
+ const network = this._network;
612
+ addressType = addressType !== null && addressType !== void 0 ? addressType : this.data.addressType;
613
+ const currentWallet = this.data;
614
+ const { path } = shapes_1.addressTypes[addressType];
615
+ const result = (0, utils_1.formatKeyDerivationPath)({ path, network });
616
+ if (result.isErr()) {
617
+ return (0, utils_1.err)(result.error.message);
618
+ }
619
+ const { pathObject: keyDerivationPath } = result.value;
620
+ let addressIndex = currentWallet.addressIndex[addressType];
621
+ let lastUsedAddressIndex = currentWallet.lastUsedAddressIndex[addressType];
622
+ let changeAddressIndex = currentWallet.changeAddressIndex[addressType];
623
+ let lastUsedChangeAddressIndex = currentWallet.lastUsedChangeAddressIndex[addressType];
624
+ if ((addressIndex === null || addressIndex === void 0 ? void 0 : addressIndex.index) < 0 || !(addressIndex === null || addressIndex === void 0 ? void 0 : addressIndex.address)) {
625
+ const generatedAddresses = await this.generateAddresses({
626
+ addressAmount: constants_1.GENERATE_ADDRESS_AMOUNT,
627
+ addressIndex: 0,
628
+ changeAddressAmount: 0,
629
+ keyDerivationPath,
630
+ addressType
631
+ });
632
+ if (generatedAddresses.isErr()) {
633
+ return (0, utils_1.err)(generatedAddresses.error);
634
+ }
635
+ const addresses = generatedAddresses.value.addresses;
636
+ const sorted = Object.values(addresses).sort((a, b) => a.index - b.index);
637
+ addressIndex = sorted[0];
638
+ }
639
+ if ((changeAddressIndex === null || changeAddressIndex === void 0 ? void 0 : changeAddressIndex.index) < 0 || !(changeAddressIndex === null || changeAddressIndex === void 0 ? void 0 : changeAddressIndex.address)) {
640
+ const generatedAddresses = await this.generateAddresses({
641
+ addressAmount: 0,
642
+ changeAddressAmount: constants_1.GENERATE_ADDRESS_AMOUNT,
643
+ changeAddressIndex: 0,
644
+ keyDerivationPath,
645
+ addressType
646
+ });
647
+ if (generatedAddresses.isErr()) {
648
+ return (0, utils_1.err)(generatedAddresses.error);
649
+ }
650
+ const addresses = generatedAddresses.value.changeAddresses;
651
+ const sorted = Object.values(addresses).sort((a, b) => a.index - b.index);
652
+ changeAddressIndex = sorted[0];
653
+ }
654
+ let addresses = currentWallet.addresses[addressType];
655
+ let changeAddresses = currentWallet.changeAddresses[addressType];
656
+ const addressCount = Object.values(addresses).length;
657
+ const changeAddressCount = Object.values(changeAddresses).length;
658
+ if (addressCount < constants_1.GENERATE_ADDRESS_AMOUNT ||
659
+ addressIndex.index === addressCount) {
660
+ const newAddresses = await this.addAddresses({
661
+ addressAmount: constants_1.GENERATE_ADDRESS_AMOUNT,
662
+ changeAddressAmount: 0,
663
+ addressIndex: addressIndex.index,
664
+ changeAddressIndex: 0,
665
+ keyDerivationPath,
666
+ addressType
667
+ });
668
+ if (newAddresses.isOk()) {
669
+ addresses = newAddresses.value.addresses;
670
+ }
671
+ }
672
+ if (changeAddressCount < constants_1.GENERATE_ADDRESS_AMOUNT ||
673
+ changeAddressIndex.index === changeAddressCount) {
674
+ const newChangeAddresses = await this.addAddresses({
675
+ addressAmount: 0,
676
+ changeAddressAmount: constants_1.GENERATE_ADDRESS_AMOUNT,
677
+ addressIndex: 0,
678
+ changeAddressIndex: changeAddressIndex.index,
679
+ keyDerivationPath,
680
+ addressType
681
+ });
682
+ if (newChangeAddresses.isOk()) {
683
+ changeAddresses = newChangeAddresses.value.changeAddresses;
684
+ }
685
+ }
686
+ let allAddresses = Object.values(addresses).filter(({ index }) => index >= addressIndex.index);
687
+ let addressesToScan = allAddresses;
688
+ let allChangeAddresses = Object.values(changeAddresses).filter(({ index }) => index >= changeAddressIndex.index);
689
+ let changeAddressesToScan = allChangeAddresses;
690
+ let combinedAddressesToScan = [
691
+ ...addressesToScan,
692
+ ...changeAddressesToScan
693
+ ];
694
+ let foundLastUsedAddress = false;
695
+ let foundLastUsedChangeAddress = false;
696
+ let addressHasBeenUsed = false;
697
+ let changeAddressHasBeenUsed = false;
698
+ const lastKnownIndexes = (0, utils_1.ok)({
699
+ addressIndex,
700
+ lastUsedAddressIndex,
701
+ changeAddressIndex,
702
+ lastUsedChangeAddressIndex
703
+ });
704
+ while (!foundLastUsedAddress || !foundLastUsedChangeAddress) {
705
+ const addressHistory = await this.electrum.getAddressHistory({
706
+ scriptHashes: combinedAddressesToScan
707
+ });
708
+ if (addressHistory.isErr()) {
709
+ console.log(addressHistory.error.message);
710
+ return lastKnownIndexes;
711
+ }
712
+ const txHashes = addressHistory.value;
713
+ const highestUsedIndex = (0, utils_1.getHighestUsedIndexFromTxHashes)({
714
+ txHashes,
715
+ addresses,
716
+ changeAddresses,
717
+ addressIndex,
718
+ changeAddressIndex
719
+ });
720
+ if (highestUsedIndex.isErr()) {
721
+ console.log(highestUsedIndex.error.message);
722
+ return lastKnownIndexes;
723
+ }
724
+ addressIndex = highestUsedIndex.value.addressIndex;
725
+ changeAddressIndex = highestUsedIndex.value.changeAddressIndex;
726
+ if (highestUsedIndex.value.foundAddressIndex) {
727
+ addressHasBeenUsed = true;
728
+ }
729
+ if (highestUsedIndex.value.foundChangeAddressIndex) {
730
+ changeAddressHasBeenUsed = true;
731
+ }
732
+ const highestStoredIndex = this.getHighestStoredAddressIndex({
733
+ addressType
734
+ });
735
+ if (highestStoredIndex.isErr()) {
736
+ console.log(highestStoredIndex.error.message);
737
+ return lastKnownIndexes;
738
+ }
739
+ const { addressIndex: highestUsedAddressIndex, changeAddressIndex: highestUsedChangeAddressIndex } = highestUsedIndex.value;
740
+ const { addressIndex: highestStoredAddressIndex, changeAddressIndex: highestStoredChangeAddressIndex } = highestStoredIndex.value;
741
+ if (highestUsedAddressIndex.index < highestStoredAddressIndex.index) {
742
+ foundLastUsedAddress = true;
743
+ }
744
+ if (highestUsedChangeAddressIndex.index <
745
+ highestStoredChangeAddressIndex.index) {
746
+ foundLastUsedChangeAddress = true;
747
+ }
748
+ if (foundLastUsedAddress && foundLastUsedChangeAddress) {
749
+ let newAddressIndex = addressIndex.index;
750
+ if (highestUsedAddressIndex.index > addressIndex.index ||
751
+ addressHasBeenUsed) {
752
+ const index = highestUsedAddressIndex.index;
753
+ if (highestUsedAddressIndex && index >= 0) {
754
+ lastUsedAddressIndex = highestUsedAddressIndex;
755
+ }
756
+ newAddressIndex = index >= 0 ? index + 1 : index;
757
+ }
758
+ let newChangeAddressIndex = changeAddressIndex.index;
759
+ if (highestUsedChangeAddressIndex.index > changeAddressIndex.index ||
760
+ changeAddressHasBeenUsed) {
761
+ const index = highestUsedChangeAddressIndex.index;
762
+ if (highestUsedChangeAddressIndex && index >= 0) {
763
+ lastUsedChangeAddressIndex = highestUsedChangeAddressIndex;
764
+ }
765
+ newChangeAddressIndex = index >= 0 ? index + 1 : index;
766
+ }
767
+ const nextAvailableAddress = Object.values(allAddresses).find(({ index }) => index === newAddressIndex);
768
+ const nextAvailableChangeAddress = Object.values(allChangeAddresses).find(({ index }) => index === newChangeAddressIndex);
769
+ if (!nextAvailableAddress || !nextAvailableChangeAddress) {
770
+ return lastKnownIndexes;
771
+ }
772
+ return (0, utils_1.ok)({
773
+ addressIndex: nextAvailableAddress,
774
+ lastUsedAddressIndex,
775
+ changeAddressIndex: nextAvailableChangeAddress,
776
+ lastUsedChangeAddressIndex
777
+ });
778
+ }
779
+ if (!foundLastUsedAddress) {
780
+ const newAddresses = await this.addAddresses({
781
+ addressAmount: constants_1.GENERATE_ADDRESS_AMOUNT,
782
+ changeAddressAmount: 0,
783
+ addressIndex: highestStoredIndex.value.addressIndex.index,
784
+ changeAddressIndex: 0,
785
+ keyDerivationPath,
786
+ addressType
787
+ });
788
+ if (newAddresses.isOk()) {
789
+ addresses = newAddresses.value.addresses || {};
790
+ }
791
+ }
792
+ if (!foundLastUsedChangeAddress) {
793
+ const newChangeAddresses = await this.addAddresses({
794
+ addressAmount: 0,
795
+ changeAddressAmount: constants_1.GENERATE_ADDRESS_AMOUNT,
796
+ addressIndex: 0,
797
+ changeAddressIndex: highestStoredIndex.value.changeAddressIndex.index,
798
+ keyDerivationPath,
799
+ addressType
800
+ });
801
+ if (newChangeAddresses.isOk()) {
802
+ changeAddresses = newChangeAddresses.value.changeAddresses || {};
803
+ }
804
+ }
805
+ addressesToScan = Object.values(addresses);
806
+ changeAddressesToScan = Object.values(changeAddresses);
807
+ combinedAddressesToScan = [
808
+ ...addressesToScan,
809
+ ...changeAddressesToScan
810
+ ];
811
+ allAddresses = [...allAddresses, ...addressesToScan];
812
+ allChangeAddresses = [...allChangeAddresses, ...changeAddressesToScan];
813
+ }
814
+ return lastKnownIndexes;
815
+ }
816
+ catch (e) {
817
+ return (0, utils_1.err)(e);
818
+ }
819
+ }
820
+ getHighestStoredAddressIndex({ addressType }) {
821
+ try {
822
+ const currentWallet = this.data;
823
+ const addresses = currentWallet.addresses[addressType];
824
+ const changeAddresses = currentWallet.changeAddresses[addressType];
825
+ const addressIndex = Object.values(addresses).reduce((prev, current) => {
826
+ return prev.index > current.index ? prev : current;
827
+ });
828
+ const changeAddressIndex = Object.values(changeAddresses).reduce((prev, current) => (prev.index > current.index ? prev : current));
829
+ return (0, utils_1.ok)({ addressIndex, changeAddressIndex });
830
+ }
831
+ catch (e) {
832
+ return (0, utils_1.err)(e);
833
+ }
834
+ }
835
+ async addAddresses({ addressAmount = 5, changeAddressAmount = 5, addressIndex = 0, changeAddressIndex = 0, addressType, keyDerivationPath }) {
836
+ if (!addressType) {
837
+ addressType = this.data.addressType;
838
+ }
839
+ const network = this._network;
840
+ const { path, type } = shapes_1.addressTypes[addressType];
841
+ if (!keyDerivationPath) {
842
+ const keyDerivationPathResponse = (0, utils_1.getKeyDerivationPathObject)({
843
+ path,
844
+ network
845
+ });
846
+ if (keyDerivationPathResponse.isErr()) {
847
+ return (0, utils_1.err)(keyDerivationPathResponse.error.message);
848
+ }
849
+ keyDerivationPath = keyDerivationPathResponse.value;
850
+ }
851
+ const generatedAddresses = await this.generateAddresses({
852
+ addressAmount,
853
+ changeAddressAmount,
854
+ addressIndex,
855
+ changeAddressIndex,
856
+ keyDerivationPath,
857
+ addressType: type
858
+ });
859
+ if (generatedAddresses.isErr()) {
860
+ return (0, utils_1.err)(generatedAddresses.error);
861
+ }
862
+ const removeDuplicateResponse = await this.removeDuplicateAddresses({
863
+ addresses: generatedAddresses.value.addresses,
864
+ changeAddresses: generatedAddresses.value.changeAddresses
865
+ });
866
+ if (removeDuplicateResponse.isErr()) {
867
+ return (0, utils_1.err)(removeDuplicateResponse.error.message);
868
+ }
869
+ const addresses = removeDuplicateResponse.value.addresses;
870
+ const changeAddresses = removeDuplicateResponse.value.changeAddresses;
871
+ if (Object.keys(addresses).length) {
872
+ this._data.addresses[addressType] = Object.assign(Object.assign({}, this.data.addresses[addressType]), addresses);
873
+ await this.saveWalletData('addresses', this._data.addresses);
874
+ }
875
+ if (Object.keys(changeAddresses).length) {
876
+ this._data.changeAddresses[addressType] = Object.assign(Object.assign({}, this.data.changeAddresses[addressType]), changeAddresses);
877
+ await this.saveWalletData('changeAddresses', this._data.changeAddresses);
878
+ }
879
+ return (0, utils_1.ok)(Object.assign(Object.assign({}, generatedAddresses.value), { addressType: type }));
880
+ }
881
+ async removeDuplicateAddresses({ addresses = {}, changeAddresses = {} }) {
882
+ try {
883
+ const currentWallet = this.data;
884
+ const currentAddressTypeContent = currentWallet.addresses;
885
+ const currentChangeAddressTypeContent = currentWallet.changeAddresses;
886
+ await Promise.all([
887
+ (0, utils_1.objectKeys)(currentAddressTypeContent).map(async (addressType) => {
888
+ await Promise.all((0, utils_1.objectKeys)(addresses).map((scriptHash) => {
889
+ if (scriptHash in currentAddressTypeContent[addressType]) {
890
+ delete addresses[scriptHash];
891
+ }
892
+ }));
893
+ }),
894
+ (0, utils_1.objectKeys)(currentChangeAddressTypeContent).map(async (addressType) => {
895
+ await Promise.all((0, utils_1.objectKeys)(changeAddresses).map((scriptHash) => {
896
+ if (scriptHash in currentChangeAddressTypeContent[addressType]) {
897
+ delete changeAddresses[scriptHash];
898
+ }
899
+ }));
900
+ })
901
+ ]);
902
+ return (0, utils_1.ok)({ addresses, changeAddresses });
903
+ }
904
+ catch (e) {
905
+ return (0, utils_1.err)(e);
906
+ }
907
+ }
908
+ async updateAddressIndexes({ addressType } = {}) {
909
+ const checkRes = await this.checkElectrumConnection();
910
+ if (checkRes.isErr())
911
+ return (0, utils_1.err)(checkRes.error.message);
912
+ const currentWallet = this.data;
913
+ let addressTypeKeys = Object.values(types_1.EAddressType);
914
+ if (addressType) {
915
+ addressTypeKeys = [addressType];
916
+ }
917
+ let updated = false;
918
+ const promises = addressTypeKeys.map(async (addressTypeKey) => {
919
+ const response = await this.getNextAvailableAddress(addressTypeKey);
920
+ if (response.isErr()) {
921
+ throw response.error;
922
+ }
923
+ const result = response.value;
924
+ let addressIndex = currentWallet.addressIndex[addressTypeKey];
925
+ let changeAddressIndex = currentWallet.changeAddressIndex[addressTypeKey];
926
+ let lastUsedAddressIndex = currentWallet.lastUsedAddressIndex[addressTypeKey];
927
+ let lastUsedChangeAddressIndex = currentWallet.lastUsedChangeAddressIndex[addressTypeKey];
928
+ if (addressIndex.index < 0 ||
929
+ changeAddressIndex.index < 0 ||
930
+ result.addressIndex.index > addressIndex.index ||
931
+ result.changeAddressIndex.index > changeAddressIndex.index ||
932
+ result.lastUsedAddressIndex.index > lastUsedAddressIndex.index ||
933
+ result.lastUsedChangeAddressIndex.index >
934
+ (lastUsedChangeAddressIndex === null || lastUsedChangeAddressIndex === void 0 ? void 0 : lastUsedChangeAddressIndex.index)) {
935
+ if (result.addressIndex) {
936
+ addressIndex = result.addressIndex;
937
+ }
938
+ if (result.changeAddressIndex) {
939
+ changeAddressIndex = result.changeAddressIndex;
940
+ }
941
+ if (result.lastUsedAddressIndex) {
942
+ lastUsedAddressIndex = result.lastUsedAddressIndex;
943
+ }
944
+ if (result.lastUsedChangeAddressIndex) {
945
+ lastUsedChangeAddressIndex = result.lastUsedChangeAddressIndex;
946
+ }
947
+ const lastUsedIndex = lastUsedAddressIndex.index > 0 ? lastUsedAddressIndex.index : 0;
948
+ const currentGap = Math.abs(addressIndex.index - lastUsedIndex);
949
+ if (currentGap > constants_1.GAP_LIMIT) {
950
+ const excessAmount = currentGap - constants_1.GAP_LIMIT;
951
+ const newIndex = addressIndex.index - excessAmount;
952
+ const _addressIndex = await this.generateAddresses({
953
+ addressType: addressTypeKey,
954
+ addressAmount: 1,
955
+ changeAddressAmount: 0,
956
+ addressIndex: newIndex
957
+ });
958
+ if (_addressIndex.isErr()) {
959
+ return (0, utils_1.err)(_addressIndex.error.message);
960
+ }
961
+ addressIndex = Object.values(_addressIndex.value.addresses)[0];
962
+ }
963
+ const lastUsedChangeIndex = lastUsedChangeAddressIndex.index > 0
964
+ ? lastUsedChangeAddressIndex.index
965
+ : 0;
966
+ const currentChangeAddressGap = Math.abs(changeAddressIndex.index - lastUsedChangeIndex);
967
+ if (currentChangeAddressGap > constants_1.GAP_LIMIT) {
968
+ const excessAmount = currentGap - constants_1.GAP_LIMIT;
969
+ const newIndex = addressIndex.index - excessAmount;
970
+ const _changeAddressIndex = await this.generateAddresses({
971
+ addressType: addressTypeKey,
972
+ addressAmount: 0,
973
+ changeAddressAmount: 1,
974
+ changeAddressIndex: newIndex
975
+ });
976
+ if (_changeAddressIndex.isErr()) {
977
+ return (0, utils_1.err)(_changeAddressIndex.error.message);
978
+ }
979
+ changeAddressIndex = Object.values(_changeAddressIndex.value.changeAddresses)[0];
980
+ }
981
+ this._data.addressIndex[addressTypeKey] = addressIndex;
982
+ this._data.changeAddressIndex[addressTypeKey] = changeAddressIndex;
983
+ this._data.lastUsedAddressIndex[addressTypeKey] = lastUsedAddressIndex;
984
+ this._data.lastUsedChangeAddressIndex[addressTypeKey] =
985
+ lastUsedChangeAddressIndex;
986
+ await Promise.all([
987
+ this.saveWalletData('addressIndex', this._data.addressIndex),
988
+ this.saveWalletData('changeAddressIndex', this._data.changeAddressIndex),
989
+ this.saveWalletData('lastUsedAddressIndex', this._data.lastUsedAddressIndex),
990
+ this.saveWalletData('lastUsedChangeAddressIndex', this._data.lastUsedChangeAddressIndex)
991
+ ]);
992
+ updated = true;
993
+ }
994
+ });
995
+ try {
996
+ await Promise.all(promises);
997
+ return (0, utils_1.ok)(updated ? 'Successfully updated indexes.' : 'No update needed.');
998
+ }
999
+ catch (e) {
1000
+ return (0, utils_1.err)(e);
1001
+ }
1002
+ }
1003
+ async resetAddressIndexes() {
1004
+ const defaultWalletShape = (0, utils_1.getDefaultWalletData)();
1005
+ this._data.addressIndex = defaultWalletShape.addressIndex;
1006
+ this._data.changeAddressIndex = defaultWalletShape.changeAddressIndex;
1007
+ this._data.lastUsedAddressIndex = defaultWalletShape.lastUsedAddressIndex;
1008
+ this._data.lastUsedChangeAddressIndex =
1009
+ defaultWalletShape.lastUsedChangeAddressIndex;
1010
+ await Promise.all([
1011
+ this.saveWalletData('addressIndex', this._data.addressIndex),
1012
+ this.saveWalletData('changeAddressIndex', this._data.changeAddressIndex),
1013
+ this.saveWalletData('lastUsedAddressIndex', this._data.lastUsedAddressIndex),
1014
+ this.saveWalletData('lastUsedChangeAddressIndex', this._data.lastUsedChangeAddressIndex)
1015
+ ]);
1016
+ }
1017
+ async generateNewReceiveAddress({ addressType = this.data.addressType, keyDerivationPath }) {
1018
+ try {
1019
+ const network = this._network;
1020
+ const currentWallet = this.data;
1021
+ const getGapLimitResponse = this.getGapLimit({
1022
+ addressType
1023
+ });
1024
+ if (getGapLimitResponse.isErr()) {
1025
+ return (0, utils_1.err)(getGapLimitResponse.error.message);
1026
+ }
1027
+ const { addressDelta } = getGapLimitResponse.value;
1028
+ if (addressDelta >= constants_1.GAP_LIMIT) {
1029
+ const addressIndex = currentWallet.addressIndex;
1030
+ const receiveAddress = addressIndex[addressType];
1031
+ return (0, utils_1.ok)(receiveAddress);
1032
+ }
1033
+ const { path } = shapes_1.addressTypes[addressType];
1034
+ if (!keyDerivationPath) {
1035
+ const keyDerivationPathResponse = (0, utils_1.getKeyDerivationPathObject)({
1036
+ network,
1037
+ path
1038
+ });
1039
+ if (keyDerivationPathResponse.isErr()) {
1040
+ return (0, utils_1.err)(keyDerivationPathResponse.error.message);
1041
+ }
1042
+ keyDerivationPath = keyDerivationPathResponse.value;
1043
+ }
1044
+ const addresses = currentWallet.addresses[addressType];
1045
+ const currentAddressIndex = currentWallet.addressIndex[addressType].index;
1046
+ const nextAddressIndex = Object.values(addresses).find((address) => {
1047
+ return address.index === currentAddressIndex + 1;
1048
+ });
1049
+ if (nextAddressIndex) {
1050
+ this._data.addressIndex[addressType] = nextAddressIndex;
1051
+ await Promise.all([
1052
+ this.saveWalletData('addressIndex', this._data.addressIndex)
1053
+ ]);
1054
+ return (0, utils_1.ok)(nextAddressIndex);
1055
+ }
1056
+ const addAddressesRes = await this.addAddresses({
1057
+ addressAmount: 1,
1058
+ changeAddressAmount: 0,
1059
+ addressIndex: currentAddressIndex + 1,
1060
+ changeAddressIndex: 0,
1061
+ keyDerivationPath,
1062
+ addressType
1063
+ });
1064
+ if (addAddressesRes.isErr()) {
1065
+ return (0, utils_1.err)(addAddressesRes.error.message);
1066
+ }
1067
+ const addressKeys = Object.keys(addAddressesRes.value.addresses);
1068
+ if (!addressKeys.length) {
1069
+ return (0, utils_1.err)('Unable to generate addresses at this time.');
1070
+ }
1071
+ const newAddressIndex = addAddressesRes.value.addresses[addressKeys[0]];
1072
+ this._data.addressIndex[addressType] = newAddressIndex;
1073
+ await this.saveWalletData('addressIndex', this._data.addressIndex);
1074
+ return (0, utils_1.ok)(newAddressIndex);
1075
+ }
1076
+ catch (e) {
1077
+ return (0, utils_1.err)(e);
1078
+ }
1079
+ }
1080
+ getGapLimit({ addressType }) {
1081
+ try {
1082
+ if (!addressType) {
1083
+ addressType = this.data.addressType;
1084
+ }
1085
+ const currentWallet = this.data;
1086
+ const addressIndex = currentWallet.addressIndex[addressType].index;
1087
+ const lastUsedAddressIndex = currentWallet.lastUsedAddressIndex[addressType].index;
1088
+ const changeAddressIndex = currentWallet.changeAddressIndex[addressType].index;
1089
+ const lastUsedChangeAddressIndex = currentWallet.lastUsedChangeAddressIndex[addressType].index;
1090
+ const addressDelta = Math.abs(addressIndex - (lastUsedAddressIndex > 0 ? lastUsedAddressIndex : 0));
1091
+ const changeAddressDelta = Math.abs(changeAddressIndex -
1092
+ (lastUsedChangeAddressIndex > 0 ? lastUsedChangeAddressIndex : 0));
1093
+ return (0, utils_1.ok)({ addressDelta, changeAddressDelta });
1094
+ }
1095
+ catch (e) {
1096
+ return (0, utils_1.err)(e);
1097
+ }
1098
+ }
1099
+ async getUtxos({ scanAllAddresses = false }) {
1100
+ var _a, _b, _c, _d;
1101
+ const checkRes = await this.checkElectrumConnection();
1102
+ if (checkRes.isErr())
1103
+ return (0, utils_1.err)(checkRes.error.message);
1104
+ const getUtxosRes = await this.electrum.getUtxos({ scanAllAddresses });
1105
+ if (getUtxosRes.isErr()) {
1106
+ return (0, utils_1.err)(getUtxosRes.error.message);
1107
+ }
1108
+ const utxos = (_b = (_a = getUtxosRes.value) === null || _a === void 0 ? void 0 : _a.utxos) !== null && _b !== void 0 ? _b : [];
1109
+ const balance = (_d = (_c = getUtxosRes.value) === null || _c === void 0 ? void 0 : _c.balance) !== null && _d !== void 0 ? _d : 0;
1110
+ this._data.utxos = utxos;
1111
+ this._data.balance = balance;
1112
+ await Promise.all([
1113
+ this.saveWalletData('utxos', this._data.utxos),
1114
+ this.saveWalletData('balance', this._data.balance)
1115
+ ]);
1116
+ return (0, utils_1.ok)({ utxos, balance });
1117
+ }
1118
+ listUtxos() {
1119
+ return this.data.utxos;
1120
+ }
1121
+ async saveWalletData(key, data) {
1122
+ if (!this._setData)
1123
+ return;
1124
+ const walletDataKey = this.getWalletDataKey(key);
1125
+ await this._setData(walletDataKey, data);
1126
+ }
1127
+ async updateAndSaveWalletData(key, data, addressType) {
1128
+ if (addressType) {
1129
+ this.data[key][addressType] = data;
1130
+ await this.saveWalletData(key, this._data[key]);
1131
+ }
1132
+ else {
1133
+ this.data[key] = data;
1134
+ await this.saveWalletData(key, this._data[key]);
1135
+ }
1136
+ }
1137
+ async updateTransactions({ scanAllAddresses = false, replaceStoredTransactions = false }) {
1138
+ await this.checkUnconfirmedTransactions();
1139
+ const history = await this.electrum.getAddressHistory({
1140
+ scanAllAddresses: scanAllAddresses || replaceStoredTransactions
1141
+ });
1142
+ if (history.isErr()) {
1143
+ return (0, utils_1.err)(history.error.message);
1144
+ }
1145
+ if (!history.value.length) {
1146
+ return (0, utils_1.ok)(undefined);
1147
+ }
1148
+ const getTransactionsResponse = await this.electrum.getTransactions({
1149
+ txHashes: history.value
1150
+ });
1151
+ if (getTransactionsResponse.isErr()) {
1152
+ return (0, utils_1.err)(getTransactionsResponse.error.message);
1153
+ }
1154
+ const formatTransactionsResponse = await this.formatTransactions({
1155
+ transactions: getTransactionsResponse.value.data
1156
+ });
1157
+ if (formatTransactionsResponse.isErr()) {
1158
+ return (0, utils_1.err)(formatTransactionsResponse.error.message);
1159
+ }
1160
+ const transactions = formatTransactionsResponse.value;
1161
+ this.addUnconfirmedTransactions({
1162
+ transactions
1163
+ });
1164
+ if (replaceStoredTransactions) {
1165
+ this._data.transactions = transactions;
1166
+ await this.saveWalletData('transactions', this._data.transactions);
1167
+ return (0, utils_1.ok)(undefined);
1168
+ }
1169
+ const formattedTransactions = {};
1170
+ let notificationTxid;
1171
+ const storedTransactions = this.data.transactions;
1172
+ const confirmedTxs = [];
1173
+ const receivedTxs = [];
1174
+ const sentTxs = [];
1175
+ Object.keys(transactions).forEach((txid) => {
1176
+ var _a, _b, _c, _d, _e;
1177
+ if (!storedTransactions[txid] ||
1178
+ storedTransactions[txid].height !== transactions[txid].height) {
1179
+ formattedTransactions[txid] = Object.assign(Object.assign({}, transactions[txid]), { timestamp: (_d = (_b = (_a = storedTransactions[txid]) === null || _a === void 0 ? void 0 : _a.timestamp) !== null && _b !== void 0 ? _b : (_c = transactions[txid]) === null || _c === void 0 ? void 0 : _c.timestamp) !== null && _d !== void 0 ? _d : Date.now() });
1180
+ if (this.onMessage && ((_e = formattedTransactions[txid]) === null || _e === void 0 ? void 0 : _e.height) > 0)
1181
+ confirmedTxs.push({ transaction: formattedTransactions[txid] });
1182
+ }
1183
+ if (!(txid in storedTransactions)) {
1184
+ if (this.onMessage) {
1185
+ if (transactions[txid].type === types_1.EPaymentType.received) {
1186
+ receivedTxs.push({ transaction: transactions[txid] });
1187
+ }
1188
+ else if (transactions[txid].type === types_1.EPaymentType.sent) {
1189
+ sentTxs.push({ transaction: transactions[txid] });
1190
+ }
1191
+ }
1192
+ notificationTxid = txid;
1193
+ }
1194
+ });
1195
+ if (!Object.keys(formattedTransactions).length) {
1196
+ return (0, utils_1.ok)(undefined);
1197
+ }
1198
+ this._data.transactions = Object.assign(Object.assign({}, this._data.transactions), formattedTransactions);
1199
+ await this.saveWalletData('transactions', this._data.transactions);
1200
+ if (this.onMessage) {
1201
+ confirmedTxs.forEach((tx) => {
1202
+ this.onMessage('transactionConfirmed', tx);
1203
+ });
1204
+ sentTxs.forEach((tx) => {
1205
+ this.onMessage('transactionSent', tx);
1206
+ });
1207
+ receivedTxs.forEach((tx) => {
1208
+ this.onMessage('transactionReceived', tx);
1209
+ });
1210
+ }
1211
+ return (0, utils_1.ok)(notificationTxid);
1212
+ }
1213
+ async checkUnconfirmedTransactions() {
1214
+ try {
1215
+ const processRes = await this.processUnconfirmedTransactions();
1216
+ if (processRes.isErr()) {
1217
+ return (0, utils_1.err)(processRes.error.message);
1218
+ }
1219
+ const { unconfirmedTxs, outdatedTxs, ghostTxs } = processRes.value;
1220
+ if (outdatedTxs.length > 0) {
1221
+ if (this.onMessage)
1222
+ this.onMessage('reorg', outdatedTxs);
1223
+ await this.updateTransactionHeights(outdatedTxs);
1224
+ }
1225
+ if (ghostTxs.length > 0) {
1226
+ if (this.onMessage)
1227
+ this.onMessage('rbf', ghostTxs);
1228
+ await this.updateGhostTransactions({
1229
+ txIds: ghostTxs
1230
+ });
1231
+ }
1232
+ else {
1233
+ this._data.unconfirmedTransactions = unconfirmedTxs;
1234
+ await Promise.all([
1235
+ this.saveWalletData('unconfirmedTransactions', this._data.unconfirmedTransactions)
1236
+ ]);
1237
+ }
1238
+ return (0, utils_1.ok)('Successfully updated unconfirmed transactions.');
1239
+ }
1240
+ catch (e) {
1241
+ return (0, utils_1.err)(e);
1242
+ }
1243
+ }
1244
+ async processUnconfirmedTransactions() {
1245
+ try {
1246
+ const oldUnconfirmedTxs = this.getUnconfirmedTransactions();
1247
+ const tx_hashes = Object.values(oldUnconfirmedTxs).map((transaction) => {
1248
+ return { tx_hash: transaction.txid };
1249
+ });
1250
+ const txs = await this.electrum.getTransactions({
1251
+ txHashes: tx_hashes
1252
+ });
1253
+ if (txs.isErr()) {
1254
+ return (0, utils_1.err)(txs.error);
1255
+ }
1256
+ const unconfirmedTxs = {};
1257
+ const outdatedTxs = [];
1258
+ const ghostTxs = [];
1259
+ txs.value.data.forEach((txData) => {
1260
+ var _a, _b, _c, _d, _e, _f;
1261
+ if (!this.electrum.transactionExists(txData)) {
1262
+ ghostTxs.push(txData.data.tx_hash);
1263
+ return;
1264
+ }
1265
+ const newHeight = this.confirmationsToBlockHeight({
1266
+ confirmations: (_b = (_a = txData.result) === null || _a === void 0 ? void 0 : _a.confirmations) !== null && _b !== void 0 ? _b : 0
1267
+ });
1268
+ if (!((_c = txData.result) === null || _c === void 0 ? void 0 : _c.confirmations)) {
1269
+ const oldHeight = (_e = (_d = oldUnconfirmedTxs[txData.data.tx_hash]) === null || _d === void 0 ? void 0 : _d.height) !== null && _e !== void 0 ? _e : 0;
1270
+ if (oldHeight > newHeight) {
1271
+ outdatedTxs.push(txData.data);
1272
+ }
1273
+ unconfirmedTxs[txData.data.tx_hash] = Object.assign(Object.assign({}, oldUnconfirmedTxs[txData.data.tx_hash]), { height: newHeight });
1274
+ return;
1275
+ }
1276
+ if (((_f = txData.result) === null || _f === void 0 ? void 0 : _f.confirmations) < 6) {
1277
+ unconfirmedTxs[txData.data.tx_hash] = Object.assign(Object.assign({}, oldUnconfirmedTxs[txData.data.tx_hash]), { height: newHeight });
1278
+ }
1279
+ });
1280
+ return (0, utils_1.ok)({
1281
+ unconfirmedTxs,
1282
+ outdatedTxs,
1283
+ ghostTxs
1284
+ });
1285
+ }
1286
+ catch (e) {
1287
+ return (0, utils_1.err)(e);
1288
+ }
1289
+ }
1290
+ getUnconfirmedTransactions() {
1291
+ var _a;
1292
+ const currentWallet = this.data;
1293
+ return (_a = currentWallet === null || currentWallet === void 0 ? void 0 : currentWallet.unconfirmedTransactions) !== null && _a !== void 0 ? _a : {};
1294
+ }
1295
+ confirmationsToBlockHeight({ confirmations, currentHeight }) {
1296
+ if (!currentHeight) {
1297
+ const header = this.data.header;
1298
+ currentHeight = header.height;
1299
+ }
1300
+ if (confirmations > currentHeight) {
1301
+ return 0;
1302
+ }
1303
+ return currentHeight - confirmations;
1304
+ }
1305
+ async updateHeader(headerData) {
1306
+ this._data.header = headerData;
1307
+ await this.saveWalletData('header', headerData);
1308
+ }
1309
+ async updateGhostTransactions({ txIds }) {
1310
+ try {
1311
+ const transactions = this.data.transactions;
1312
+ const unconfirmedTransactions = this.data.unconfirmedTransactions;
1313
+ txIds.forEach((txId) => {
1314
+ if (txId in transactions) {
1315
+ transactions[txId]['exists'] = false;
1316
+ }
1317
+ if (txId in unconfirmedTransactions) {
1318
+ delete unconfirmedTransactions[txId];
1319
+ }
1320
+ });
1321
+ this._data.transactions = transactions;
1322
+ await this.saveWalletData('transactions', transactions);
1323
+ this._data.unconfirmedTransactions = unconfirmedTransactions;
1324
+ await this.saveWalletData('unconfirmedTransactions', unconfirmedTransactions);
1325
+ await this.rescanAddresses({
1326
+ shouldClearAddresses: false
1327
+ });
1328
+ return (0, utils_1.ok)('Successfully deleted transactions.');
1329
+ }
1330
+ catch (e) {
1331
+ return (0, utils_1.err)(e);
1332
+ }
1333
+ }
1334
+ async rescanAddresses({ shouldClearAddresses = true, shouldClearTransactions = false }) {
1335
+ if (shouldClearAddresses) {
1336
+ await this.clearAddresses();
1337
+ }
1338
+ if (shouldClearTransactions) {
1339
+ await this.clearTransactions();
1340
+ }
1341
+ await this.clearUtxos();
1342
+ await this.resetAddressIndexes();
1343
+ await this.setZeroIndexAddresses();
1344
+ return await this.refreshWallet({
1345
+ scanAllAddresses: true
1346
+ });
1347
+ }
1348
+ async clearUtxos() {
1349
+ this._data.balance = 0;
1350
+ this._data.utxos = [];
1351
+ await Promise.all([
1352
+ this.saveWalletData('balance', this._data.balance),
1353
+ this.saveWalletData('utxos', this._data.utxos)
1354
+ ]);
1355
+ return "Successfully cleared UTXO's.";
1356
+ }
1357
+ async clearTransactions() {
1358
+ this._data.transactions = (0, utils_1.getDefaultWalletData)().transactions;
1359
+ await this.saveWalletData('transactions', this._data.transactions);
1360
+ return 'Successfully reset transactions.';
1361
+ }
1362
+ async clearAddresses() {
1363
+ this._data.addresses = (0, shapes_1.getAddressTypeContent)({});
1364
+ this._data.changeAddresses = (0, shapes_1.getAddressTypeContent)({});
1365
+ await Promise.all([
1366
+ this.saveWalletData('addresses', this._data.addresses),
1367
+ this.saveWalletData('changeAddresses', this._data.changeAddresses)
1368
+ ]);
1369
+ return 'Successfully reset transactions.';
1370
+ }
1371
+ async updateTransactionHeights(txs) {
1372
+ let needsSave = false;
1373
+ const transactions = this.data.transactions;
1374
+ txs.forEach((tx) => {
1375
+ const txId = tx.tx_hash;
1376
+ if (txId in transactions) {
1377
+ transactions[txId].confirmTimestamp = 0;
1378
+ needsSave = true;
1379
+ }
1380
+ });
1381
+ if (needsSave) {
1382
+ await this.saveWalletData('transactions', transactions);
1383
+ }
1384
+ return 'Successfully updated reorg transactions.';
1385
+ }
1386
+ async addUnconfirmedTransactions({ transactions }) {
1387
+ try {
1388
+ const unconfirmedTransactions = {};
1389
+ Object.keys(transactions).forEach((key) => {
1390
+ const confirmations = this.blockHeightToConfirmations({
1391
+ blockHeight: transactions[key].height
1392
+ });
1393
+ if (confirmations < 6) {
1394
+ unconfirmedTransactions[key] = transactions[key];
1395
+ }
1396
+ });
1397
+ if (!Object.keys(unconfirmedTransactions).length) {
1398
+ return (0, utils_1.ok)('No unconfirmed transactions found.');
1399
+ }
1400
+ this._data.unconfirmedTransactions = Object.assign(Object.assign({}, this.data.unconfirmedTransactions), unconfirmedTransactions);
1401
+ await this.saveWalletData('unconfirmedTransactions', this._data.unconfirmedTransactions);
1402
+ return (0, utils_1.ok)('Successfully updated unconfirmed transactions.');
1403
+ }
1404
+ catch (e) {
1405
+ console.log(e);
1406
+ return (0, utils_1.err)(e);
1407
+ }
1408
+ }
1409
+ blockHeightToConfirmations({ blockHeight, currentHeight }) {
1410
+ if (!blockHeight) {
1411
+ return 0;
1412
+ }
1413
+ if (!currentHeight) {
1414
+ const header = this.electrum.getBlockHeader();
1415
+ currentHeight = header.height;
1416
+ }
1417
+ if (currentHeight < blockHeight) {
1418
+ return 0;
1419
+ }
1420
+ return currentHeight - blockHeight + 1;
1421
+ }
1422
+ async formatTransactions({ transactions }) {
1423
+ if (transactions.length < 1) {
1424
+ return (0, utils_1.ok)({});
1425
+ }
1426
+ const currentWallet = this.data;
1427
+ const inputs = [];
1428
+ transactions.forEach(({ result }) => {
1429
+ if (result === null || result === void 0 ? void 0 : result.vin) {
1430
+ result.vin.forEach((v) => inputs.push({ tx_hash: v.txid, vout: v.vout }));
1431
+ }
1432
+ });
1433
+ const inputDataResponse = await this.getInputData({
1434
+ inputs
1435
+ });
1436
+ if (inputDataResponse.isErr()) {
1437
+ return (0, utils_1.err)(inputDataResponse.error.message);
1438
+ }
1439
+ const addressTypeKeys = Object.values(types_1.EAddressType);
1440
+ const inputData = inputDataResponse.value;
1441
+ const currentAddresses = currentWallet.addresses;
1442
+ const currentChangeAddresses = currentWallet.changeAddresses;
1443
+ let addresses = {};
1444
+ let changeAddresses = {};
1445
+ let rbf = false;
1446
+ addressTypeKeys.map((addressType) => {
1447
+ var _a, _b;
1448
+ if (((_a = Object.keys(currentAddresses[addressType])) === null || _a === void 0 ? void 0 : _a.length) > 0) {
1449
+ addresses = Object.assign(Object.assign({}, addresses), currentAddresses[addressType]);
1450
+ }
1451
+ if (((_b = Object.keys(currentChangeAddresses[addressType])) === null || _b === void 0 ? void 0 : _b.length) > 0) {
1452
+ changeAddresses = Object.assign(Object.assign({}, changeAddresses), currentChangeAddresses[addressType]);
1453
+ }
1454
+ });
1455
+ const combinedAddressObj = {};
1456
+ [...Object.values(addresses), ...Object.values(changeAddresses)].map((data) => {
1457
+ combinedAddressObj[data.address] = data;
1458
+ });
1459
+ const formattedTransactions = {};
1460
+ transactions.map(async ({ data, result }) => {
1461
+ if (!result.txid) {
1462
+ return;
1463
+ }
1464
+ let totalInputValue = 0;
1465
+ let matchedInputValue = 0;
1466
+ let totalOutputValue = 0;
1467
+ let matchedOutputValue = 0;
1468
+ let messages = [];
1469
+ result.vin.map(({ txid, scriptSig, vout, sequence }) => {
1470
+ try {
1471
+ const asm = scriptSig.asm;
1472
+ if (asm !== '' && asm.includes('OP_RETURN')) {
1473
+ const OpReturnMessages = (0, utils_1.decodeOpReturnMessage)(asm);
1474
+ messages = messages.concat(OpReturnMessages);
1475
+ }
1476
+ }
1477
+ catch (_a) { }
1478
+ try {
1479
+ if (sequence < 0xffffffff - 1)
1480
+ rbf = true;
1481
+ }
1482
+ catch (_b) { }
1483
+ const { addresses: _addresses, value } = inputData[`${txid}${vout}`];
1484
+ totalInputValue = totalInputValue + value;
1485
+ _addresses.map((address) => {
1486
+ if (address in combinedAddressObj) {
1487
+ matchedInputValue = matchedInputValue + value;
1488
+ }
1489
+ });
1490
+ });
1491
+ result.vout.map(({ scriptPubKey, value }) => {
1492
+ const _addresses = scriptPubKey.addresses
1493
+ ? scriptPubKey.addresses
1494
+ : scriptPubKey.address
1495
+ ? [scriptPubKey.address]
1496
+ : [];
1497
+ totalOutputValue = totalOutputValue + value;
1498
+ _addresses.map((address) => {
1499
+ if (address in combinedAddressObj) {
1500
+ matchedOutputValue = matchedOutputValue + value;
1501
+ }
1502
+ });
1503
+ });
1504
+ const txid = result.txid;
1505
+ const type = matchedInputValue > matchedOutputValue
1506
+ ? types_1.EPaymentType.sent
1507
+ : types_1.EPaymentType.received;
1508
+ const totalMatchedValue = matchedOutputValue - matchedInputValue;
1509
+ const value = Number(totalMatchedValue.toFixed(8));
1510
+ const totalValue = totalInputValue - totalOutputValue;
1511
+ const fee = Number(Math.abs(totalValue).toFixed(8));
1512
+ const vsize = result.vsize;
1513
+ const satsPerByte = Math.round((0, conversion_1.btcToSats)(fee) / vsize);
1514
+ const { address, height, scriptHash } = data;
1515
+ let timestamp = Date.now();
1516
+ let confirmTimestamp;
1517
+ if (height > 0 && result.blocktime) {
1518
+ confirmTimestamp = result.blocktime * 1000;
1519
+ if (confirmTimestamp < timestamp) {
1520
+ timestamp = confirmTimestamp;
1521
+ }
1522
+ }
1523
+ formattedTransactions[txid] = {
1524
+ address,
1525
+ height,
1526
+ scriptHash,
1527
+ totalInputValue,
1528
+ matchedInputValue,
1529
+ totalOutputValue,
1530
+ matchedOutputValue,
1531
+ fee,
1532
+ satsPerByte,
1533
+ type,
1534
+ value,
1535
+ txid,
1536
+ messages,
1537
+ timestamp,
1538
+ confirmTimestamp,
1539
+ vin: result.vin,
1540
+ rbf,
1541
+ exists: true,
1542
+ vsize
1543
+ };
1544
+ });
1545
+ return (0, utils_1.ok)(formattedTransactions);
1546
+ }
1547
+ async getInputData({ inputs }) {
1548
+ try {
1549
+ const inputData = {};
1550
+ for (let i = 0; i < inputs.length; i += constants_1.CHUNK_LIMIT) {
1551
+ const chunk = inputs.slice(i, i + constants_1.CHUNK_LIMIT);
1552
+ const getTransactionsResponse = await this.electrum.getTransactionsFromInputs({
1553
+ txHashes: chunk
1554
+ });
1555
+ if (getTransactionsResponse.isErr()) {
1556
+ return (0, utils_1.err)(getTransactionsResponse.error.message);
1557
+ }
1558
+ getTransactionsResponse.value.data.map(({ data, result }) => {
1559
+ const vout = result.vout[data.vout];
1560
+ const addresses = vout.scriptPubKey.addresses
1561
+ ? vout.scriptPubKey.addresses
1562
+ : vout.scriptPubKey.address
1563
+ ? [vout.scriptPubKey.address]
1564
+ : [];
1565
+ const value = vout.value;
1566
+ const key = `${data.tx_hash}${vout.n}`;
1567
+ inputData[key] = { addresses, value };
1568
+ });
1569
+ }
1570
+ return (0, utils_1.ok)(inputData);
1571
+ }
1572
+ catch (e) {
1573
+ return (0, utils_1.err)(e);
1574
+ }
1575
+ }
1576
+ getExchangeRate(currency = 'EUR') {
1577
+ var _a, _b;
1578
+ try {
1579
+ if (currency in this.exchangeRates) {
1580
+ return (_b = (_a = this.exchangeRates[currency]) === null || _a === void 0 ? void 0 : _a.rate) !== null && _b !== void 0 ? _b : 0;
1581
+ }
1582
+ return 0;
1583
+ }
1584
+ catch (_c) {
1585
+ return 0;
1586
+ }
1587
+ }
1588
+ validateAddress(address) {
1589
+ return (0, utils_1.validateAddress)({ address, network: this._network }).isValid;
1590
+ }
1591
+ async getChangeAddress(addressType = this.data.addressType) {
1592
+ const currentWallet = this.data;
1593
+ const changeAddressIndexContent = currentWallet.changeAddressIndex[addressType];
1594
+ if ((changeAddressIndexContent === null || changeAddressIndexContent === void 0 ? void 0 : changeAddressIndexContent.address) &&
1595
+ changeAddressIndexContent.index >= 0) {
1596
+ return (0, utils_1.ok)(changeAddressIndexContent);
1597
+ }
1598
+ const generateAddressResponse = await this.generateAddresses({
1599
+ addressAmount: 0,
1600
+ changeAddressAmount: 1,
1601
+ addressType
1602
+ });
1603
+ if (generateAddressResponse.isErr()) {
1604
+ console.log(generateAddressResponse.error.message);
1605
+ return (0, utils_1.err)('Unable to successfully generate a change address.');
1606
+ }
1607
+ return (0, utils_1.ok)(generateAddressResponse.value.changeAddresses[0]);
1608
+ }
1609
+ async getFeeEstimates(network = this._network) {
1610
+ try {
1611
+ if (network === types_1.EAvailableNetworks.bitcoinRegtest) {
1612
+ return {
1613
+ fast: 60,
1614
+ normal: 50,
1615
+ slow: 40,
1616
+ minimum: 30,
1617
+ timestamp: Date.now()
1618
+ };
1619
+ }
1620
+ const urlModifier = network === 'bitcoin' ? '' : 'testnet/';
1621
+ const response = await fetch(`https://mempool.space/${urlModifier}api/v1/fees/recommended`);
1622
+ const res = await response.json();
1623
+ return {
1624
+ fast: res.fastestFee,
1625
+ normal: res.halfHourFee,
1626
+ slow: res.hourFee,
1627
+ minimum: res.minimumFee,
1628
+ timestamp: Date.now()
1629
+ };
1630
+ }
1631
+ catch (_a) {
1632
+ return shapes_1.defaultFeesShape;
1633
+ }
1634
+ }
1635
+ async setupTransaction(params = {}) {
1636
+ return await this.transaction.setupTransaction(params);
1637
+ }
1638
+ getFeeInfo({ satsPerByte = this.feeEstimates.normal, message = '', transaction, fundingLightning = false } = {}) {
1639
+ return this.transaction.getTotalFeeObj({
1640
+ satsPerByte,
1641
+ message,
1642
+ transaction,
1643
+ fundingLightning
1644
+ });
1645
+ }
1646
+ async sendMany({ txs = [], satsPerByte = this.feeEstimates.normal, rbf, broadcast = true, shuffleOutputs = true }) {
1647
+ const setupTransactionRes = await this.transaction.setupTransaction({
1648
+ rbf
1649
+ });
1650
+ if (setupTransactionRes.isErr()) {
1651
+ return (0, utils_1.err)(setupTransactionRes.error.message);
1652
+ }
1653
+ if (!Array.isArray(txs))
1654
+ txs = [txs];
1655
+ const shuffledTxs = shuffleOutputs ? (0, utils_1.shuffleArray)(txs) : txs;
1656
+ let index = 0;
1657
+ for (const tx of shuffledTxs) {
1658
+ const updateSendTransactionRes = this.transaction.updateSendTransaction({
1659
+ transaction: {
1660
+ label: tx.message,
1661
+ outputs: [{ address: tx.address, value: tx.amount, index }]
1662
+ }
1663
+ });
1664
+ if (updateSendTransactionRes.isErr())
1665
+ (0, utils_1.err)(updateSendTransactionRes.error.message);
1666
+ index++;
1667
+ }
1668
+ const updateFeeRes = this.transaction.updateFee({ satsPerByte });
1669
+ if (updateFeeRes.isErr()) {
1670
+ if (updateFeeRes.error.message.includes('Unable to increase the fee')) {
1671
+ const feeInfo = this.getFeeInfo({ satsPerByte: 1 });
1672
+ if (feeInfo.isOk()) {
1673
+ return (0, utils_1.err)(`Fee is too high. The maximum fee for this transaction is ${feeInfo.value.maxSatPerByte}`);
1674
+ }
1675
+ }
1676
+ else {
1677
+ return (0, utils_1.err)(updateFeeRes.error.message);
1678
+ }
1679
+ }
1680
+ const createRes = await this.transaction.createTransaction({
1681
+ shuffleOutputs
1682
+ });
1683
+ if (createRes.isErr())
1684
+ return (0, utils_1.err)(createRes.error.message);
1685
+ const { hex } = createRes.value;
1686
+ if (!broadcast) {
1687
+ return (0, utils_1.ok)(hex);
1688
+ }
1689
+ const broadcastRes = await this.electrum.broadcastTransaction({
1690
+ rawTx: hex
1691
+ });
1692
+ if (broadcastRes.isErr())
1693
+ return (0, utils_1.err)(broadcastRes.error.message);
1694
+ return (0, utils_1.ok)(broadcastRes.value);
1695
+ }
1696
+ async send({ address, amount, message = '', satsPerByte = this.feeEstimates.normal, rbf, broadcast = true, shuffleOutputs = true }) {
1697
+ return await this.sendMany({
1698
+ txs: [{ address, amount, message }],
1699
+ satsPerByte,
1700
+ rbf,
1701
+ broadcast,
1702
+ shuffleOutputs
1703
+ });
1704
+ }
1705
+ getAddressFromScriptHash(scriptHash) {
1706
+ const addresses = this.data.addresses;
1707
+ const changeAddresses = this.data.changeAddresses;
1708
+ const combinedAddresses = [
1709
+ ...Object.values(addresses),
1710
+ ...Object.values(changeAddresses)
1711
+ ].flatMap((addressGroup) => Object.values(addressGroup));
1712
+ return combinedAddresses.find((addressObj) => addressObj.scriptHash === scriptHash);
1713
+ }
1714
+ async setZeroIndexAddresses() {
1715
+ const types = Object.values(types_1.EAddressType);
1716
+ const currentWallet = this.data;
1717
+ let saveAddressIndexes = false;
1718
+ let saveChangeAddressIndexes = false;
1719
+ for (const addressType of types) {
1720
+ const addressIndex = currentWallet.addressIndex[addressType];
1721
+ const changeAddressIndex = currentWallet.changeAddressIndex[addressType];
1722
+ if ((addressIndex === null || addressIndex === void 0 ? void 0 : addressIndex.index) < 0) {
1723
+ await this.updateAddressIndex(addressType, false);
1724
+ saveAddressIndexes = true;
1725
+ }
1726
+ if ((changeAddressIndex === null || changeAddressIndex === void 0 ? void 0 : changeAddressIndex.index) < 0) {
1727
+ await this.updateAddressIndex(addressType, true);
1728
+ saveChangeAddressIndexes = true;
1729
+ }
1730
+ }
1731
+ if (saveAddressIndexes) {
1732
+ await this.saveWalletData('addressIndex', this._data.addressIndex);
1733
+ }
1734
+ if (saveChangeAddressIndexes) {
1735
+ await this.saveWalletData('changeAddressIndex', this._data.changeAddressIndex);
1736
+ }
1737
+ return (0, utils_1.ok)('Set Zero Index Addresses.');
1738
+ }
1739
+ async updateAddressIndex(addressType, isChangeAddress, index = 0) {
1740
+ const address = await this.generateAddresses({
1741
+ addressAmount: isChangeAddress ? 0 : 1,
1742
+ addressIndex: index,
1743
+ changeAddressAmount: isChangeAddress ? 1 : 0,
1744
+ changeAddressIndex: index,
1745
+ addressType
1746
+ });
1747
+ const indexToUpdate = isChangeAddress
1748
+ ? 'changeAddressIndex'
1749
+ : 'addressIndex';
1750
+ if (address.isOk()) {
1751
+ const key = isChangeAddress ? 'changeAddresses' : 'addresses';
1752
+ this._data[indexToUpdate][addressType] =
1753
+ address.value[key][Object.keys(address.value[key])[0]];
1754
+ }
1755
+ let addresses = {};
1756
+ if (indexToUpdate === 'addressIndex') {
1757
+ addresses = this.data.addresses[addressType];
1758
+ }
1759
+ else {
1760
+ addresses = this.data.changeAddresses[addressType];
1761
+ }
1762
+ if (!Object.keys(addresses).length) {
1763
+ await this.addAddresses({
1764
+ addressAmount: indexToUpdate === 'addressIndex' ? constants_1.GENERATE_ADDRESS_AMOUNT : 0,
1765
+ addressIndex: index,
1766
+ changeAddressAmount: indexToUpdate === 'changeAddressIndex' ? constants_1.GENERATE_ADDRESS_AMOUNT : 0,
1767
+ changeAddressIndex: index,
1768
+ addressType
1769
+ });
1770
+ }
1771
+ }
1772
+ getAddressIndexInfo() {
1773
+ const addressType = this.data.addressType;
1774
+ const currentWallet = this.data;
1775
+ const addressIndex = currentWallet.addressIndex[addressType];
1776
+ const changeAddressIndex = currentWallet.addressIndex[addressType];
1777
+ const lastUsedAddressIndex = currentWallet.lastUsedAddressIndex[addressType];
1778
+ const lastUsedChangeAddressIndex = currentWallet.lastUsedChangeAddressIndex[addressType];
1779
+ return {
1780
+ addressIndex,
1781
+ changeAddressIndex,
1782
+ lastUsedAddressIndex,
1783
+ lastUsedChangeAddressIndex
1784
+ };
1785
+ }
1786
+ async getRbfData({ txHash }) {
1787
+ var _a, _b, _c, _d, _e;
1788
+ const txResponse = await this.electrum.getTransactions({
1789
+ txHashes: [txHash]
1790
+ });
1791
+ if (txResponse.isErr()) {
1792
+ return (0, utils_1.err)(txResponse.error.message);
1793
+ }
1794
+ const txData = txResponse.value.data;
1795
+ const wallet = this.data;
1796
+ const addressTypeKeys = (0, utils_1.objectKeys)(types_1.EAddressType);
1797
+ const addresses = wallet.addresses;
1798
+ const changeAddresses = wallet.changeAddresses;
1799
+ let allAddresses = {};
1800
+ let allChangeAddresses = {};
1801
+ await Promise.all(addressTypeKeys.map((addressType) => {
1802
+ allAddresses = Object.assign(Object.assign(Object.assign({}, allAddresses), addresses[addressType]), changeAddresses[addressType]);
1803
+ allChangeAddresses = Object.assign(Object.assign({}, allChangeAddresses), changeAddresses[addressType]);
1804
+ }));
1805
+ let changeAddressData = {
1806
+ address: '',
1807
+ value: 0,
1808
+ index: 0
1809
+ };
1810
+ const inputs = [];
1811
+ let address = '';
1812
+ let scriptHash = '';
1813
+ let path = '';
1814
+ let value = 0;
1815
+ const addressType = types_1.EAddressType.p2wpkh;
1816
+ const outputs = [];
1817
+ let message = '';
1818
+ let inputTotal = 0;
1819
+ let outputTotal = 0;
1820
+ let fee = 0;
1821
+ const insAndOuts = await Promise.all(txData.map(({ result }) => {
1822
+ var _a, _b;
1823
+ const vin = (_a = result.vin) !== null && _a !== void 0 ? _a : [];
1824
+ const vout = (_b = result.vout) !== null && _b !== void 0 ? _b : [];
1825
+ return { vins: vin, vouts: vout };
1826
+ }));
1827
+ const { vins, vouts } = insAndOuts[0];
1828
+ for (let i = 0; i < vins.length; i++) {
1829
+ try {
1830
+ const input = vins[i];
1831
+ const txId = input.txid;
1832
+ const tx = await this.electrum.getTransactions({
1833
+ txHashes: [{ tx_hash: txId }]
1834
+ });
1835
+ if (tx.isErr()) {
1836
+ return (0, utils_1.err)(tx.error.message);
1837
+ }
1838
+ if (tx.value.data[0].data.height > 0) {
1839
+ return (0, utils_1.err)('Transaction is already confirmed. Unable to RBF.');
1840
+ }
1841
+ const txVout = tx.value.data[0].result.vout[input.vout];
1842
+ if ((_a = txVout.scriptPubKey) === null || _a === void 0 ? void 0 : _a.address) {
1843
+ address = txVout.scriptPubKey.address;
1844
+ }
1845
+ else if (((_b = txVout.scriptPubKey) === null || _b === void 0 ? void 0 : _b.addresses) &&
1846
+ txVout.scriptPubKey.addresses.length) {
1847
+ address = txVout.scriptPubKey.addresses[0];
1848
+ }
1849
+ if (!address) {
1850
+ continue;
1851
+ }
1852
+ scriptHash = (0, utils_1.getScriptHash)({ address, network: this._network });
1853
+ if (!(scriptHash in allAddresses)) {
1854
+ continue;
1855
+ }
1856
+ path = allAddresses[scriptHash].path;
1857
+ value = (0, conversion_1.btcToSats)(txVout.value);
1858
+ inputs.push({
1859
+ tx_hash: input.txid,
1860
+ index: input.vout,
1861
+ tx_pos: input.vout,
1862
+ height: 0,
1863
+ address,
1864
+ scriptHash,
1865
+ path,
1866
+ value
1867
+ });
1868
+ if (value) {
1869
+ inputTotal = inputTotal + value;
1870
+ }
1871
+ }
1872
+ catch (e) {
1873
+ console.log(e);
1874
+ }
1875
+ }
1876
+ for (let i = 0; i < vouts.length; i++) {
1877
+ const vout = vouts[i];
1878
+ const voutValue = (0, conversion_1.btcToSats)(vout.value);
1879
+ if ((_c = vout.scriptPubKey) === null || _c === void 0 ? void 0 : _c.addresses) {
1880
+ address = vout.scriptPubKey.addresses[0];
1881
+ }
1882
+ else if ((_d = vout.scriptPubKey) === null || _d === void 0 ? void 0 : _d.address) {
1883
+ address = vout.scriptPubKey.address;
1884
+ }
1885
+ else {
1886
+ try {
1887
+ if (vout.scriptPubKey.asm.includes('OP_RETURN')) {
1888
+ message = (0, utils_1.decodeOpReturnMessage)(vout.scriptPubKey.asm)[0] || '';
1889
+ }
1890
+ }
1891
+ catch (_f) { }
1892
+ }
1893
+ if (!address) {
1894
+ continue;
1895
+ }
1896
+ const changeAddressScriptHash = await (0, utils_1.getScriptHash)({
1897
+ address,
1898
+ network: this._network
1899
+ });
1900
+ if (Object.keys(allAddresses).includes(changeAddressScriptHash)) {
1901
+ changeAddressData = {
1902
+ address,
1903
+ value: voutValue,
1904
+ index: i
1905
+ };
1906
+ }
1907
+ const index = (_e = outputs === null || outputs === void 0 ? void 0 : outputs.length) !== null && _e !== void 0 ? _e : 0;
1908
+ outputs.push({
1909
+ address,
1910
+ value: voutValue,
1911
+ index
1912
+ });
1913
+ outputTotal = outputTotal + voutValue;
1914
+ }
1915
+ if (!(changeAddressData === null || changeAddressData === void 0 ? void 0 : changeAddressData.address) && outputs.length >= 2) {
1916
+ return (0, utils_1.err)('cpfp');
1917
+ }
1918
+ if (outputTotal > inputTotal) {
1919
+ return (0, utils_1.err)('Outputs should not be greater than the inputs.');
1920
+ }
1921
+ fee = Math.abs(Number(inputTotal - outputTotal));
1922
+ return (0, utils_1.ok)({
1923
+ changeAddress: changeAddressData.address,
1924
+ inputs,
1925
+ balance: inputTotal,
1926
+ outputs,
1927
+ fee,
1928
+ message,
1929
+ addressType,
1930
+ rbf: true
1931
+ });
1932
+ }
1933
+ async deleteOnChainTransactionById({ txid }) {
1934
+ const transactions = this.data.transactions;
1935
+ if (txid in transactions) {
1936
+ delete transactions[txid];
1937
+ }
1938
+ await this.saveWalletData('transactions', transactions);
1939
+ }
1940
+ async addGhostTransaction({ txid }) {
1941
+ if (txid in this._data.transactions) {
1942
+ this._data.transactions[txid].exists = false;
1943
+ }
1944
+ await this.saveWalletData('transactions', this._data.transactions);
1945
+ }
1946
+ async addBoostedTransaction({ newTxId, oldTxId, type = types_1.EBoostType.cpfp, fee }) {
1947
+ try {
1948
+ const boostedTransactions = this.data.boostedTransactions;
1949
+ const parentTransactions = this.getBoostedTransactionParents({
1950
+ txid: oldTxId,
1951
+ boostedTransactions
1952
+ });
1953
+ parentTransactions.push(oldTxId);
1954
+ const boostedTx = {
1955
+ parentTransactions: parentTransactions,
1956
+ childTransaction: newTxId,
1957
+ type,
1958
+ fee
1959
+ };
1960
+ const boostedTransaction = {
1961
+ [oldTxId]: boostedTx
1962
+ };
1963
+ this._data.boostedTransactions = Object.assign(Object.assign({}, this.data.boostedTransactions), boostedTransaction);
1964
+ await this.saveWalletData('boostedTransactions', this._data.boostedTransactions);
1965
+ return (0, utils_1.ok)(boostedTx);
1966
+ }
1967
+ catch (e) {
1968
+ return (0, utils_1.err)(e);
1969
+ }
1970
+ }
1971
+ async resetSendTransaction() {
1972
+ return await this.transaction.resetSendTransaction();
1973
+ }
1974
+ getBoostableTransactions() {
1975
+ const cpfp = [];
1976
+ const rbf = [];
1977
+ Object.values(this.data.unconfirmedTransactions).map((tx) => {
1978
+ if (tx.rbf)
1979
+ rbf.push(tx);
1980
+ cpfp.push(tx);
1981
+ });
1982
+ return { cpfp, rbf };
1983
+ }
1984
+ addTxInput({ input }) {
1985
+ var _a;
1986
+ try {
1987
+ const txData = this.transaction.data;
1988
+ const inputs = (_a = txData === null || txData === void 0 ? void 0 : txData.inputs) !== null && _a !== void 0 ? _a : [];
1989
+ const newInputs = [...inputs, input];
1990
+ this.transaction.updateSendTransaction({
1991
+ transaction: {
1992
+ inputs: newInputs
1993
+ }
1994
+ });
1995
+ return (0, utils_1.ok)(newInputs);
1996
+ }
1997
+ catch (e) {
1998
+ console.log(e);
1999
+ return (0, utils_1.err)(e);
2000
+ }
2001
+ }
2002
+ removeTxInput({ input }) {
2003
+ var _a;
2004
+ try {
2005
+ const txData = this.transaction.data;
2006
+ const txInputs = (_a = txData === null || txData === void 0 ? void 0 : txData.inputs) !== null && _a !== void 0 ? _a : [];
2007
+ const newInputs = txInputs.filter((txInput) => {
2008
+ if (!(0, utils_1.objectsMatch)(input, txInput)) {
2009
+ return txInput;
2010
+ }
2011
+ });
2012
+ this.transaction.updateSendTransaction({
2013
+ transaction: {
2014
+ inputs: newInputs
2015
+ }
2016
+ });
2017
+ return (0, utils_1.ok)(newInputs);
2018
+ }
2019
+ catch (e) {
2020
+ console.log(e);
2021
+ return (0, utils_1.err)(e);
2022
+ }
2023
+ }
2024
+ addTxTag({ tag }) {
2025
+ try {
2026
+ const txData = this.transaction.data;
2027
+ let tags = [...txData.tags, tag];
2028
+ tags = [...new Set(tags)];
2029
+ this.transaction.updateSendTransaction({
2030
+ transaction: Object.assign(Object.assign({}, txData), { tags })
2031
+ });
2032
+ return (0, utils_1.ok)('Tag successfully added');
2033
+ }
2034
+ catch (e) {
2035
+ console.log(e);
2036
+ return (0, utils_1.err)(e);
2037
+ }
2038
+ }
2039
+ removeTxTag({ tag }) {
2040
+ try {
2041
+ const txData = this.transaction.data;
2042
+ const tags = txData.tags;
2043
+ const newTags = tags.filter((t) => t !== tag);
2044
+ this.transaction.updateSendTransaction({
2045
+ transaction: Object.assign(Object.assign({}, txData), { tags: newTags })
2046
+ });
2047
+ return (0, utils_1.ok)('Tag successfully added');
2048
+ }
2049
+ catch (e) {
2050
+ console.log(e);
2051
+ return (0, utils_1.err)(e);
2052
+ }
2053
+ }
2054
+ setupFeeForOnChainTransaction({ satsPerByte, selectedFeeId }) {
2055
+ var _a;
2056
+ try {
2057
+ const transactionData = this.transaction.data;
2058
+ if (!satsPerByte) {
2059
+ satsPerByte = (_a = transactionData === null || transactionData === void 0 ? void 0 : transactionData.satsPerByte) !== null && _a !== void 0 ? _a : 1;
2060
+ satsPerByte =
2061
+ this.selectedFeeId === types_1.EFeeId.none
2062
+ ? satsPerByte
2063
+ : this.feeEstimates[this.selectedFeeId];
2064
+ }
2065
+ const res = this.transaction.updateFee({
2066
+ satsPerByte: satsPerByte !== null && satsPerByte !== void 0 ? satsPerByte : 1,
2067
+ selectedFeeId
2068
+ });
2069
+ if (res.isErr()) {
2070
+ console.log(res.error.message);
2071
+ return (0, utils_1.err)(res.error.message);
2072
+ }
2073
+ return (0, utils_1.ok)('Fee has been changed successfully');
2074
+ }
2075
+ catch (e) {
2076
+ return (0, utils_1.err)(e);
2077
+ }
2078
+ }
2079
+ updateWalletBalance({ balance }) {
2080
+ try {
2081
+ this._data.balance = balance;
2082
+ this.saveWalletData('balance', balance);
2083
+ return (0, utils_1.ok)('Successfully updated balance.');
2084
+ }
2085
+ catch (e) {
2086
+ return (0, utils_1.err)(e);
2087
+ }
2088
+ }
2089
+ async updateExchangeRates() {
2090
+ const exchangeRates = await (0, utils_1.getExchangeRates)();
2091
+ if (exchangeRates.isErr())
2092
+ return (0, utils_1.err)(exchangeRates.error.message);
2093
+ this.exchangeRates = exchangeRates.value;
2094
+ await this.saveWalletData('exchangeRates', this.exchangeRates);
2095
+ return (0, utils_1.ok)(this.exchangeRates);
2096
+ }
2097
+ async updateFeeEstimates(forceUpdate = false) {
2098
+ const timestamp = this.feeEstimates.timestamp;
2099
+ const difference = Math.floor((Date.now() - timestamp) / 1000);
2100
+ if (!forceUpdate && difference < 1800) {
2101
+ return (0, utils_1.ok)(this.feeEstimates);
2102
+ }
2103
+ const feeEstimates = await this.getFeeEstimates();
2104
+ if (!feeEstimates) {
2105
+ return (0, utils_1.err)('Unable to retrieve fee estimates.');
2106
+ }
2107
+ this.feeEstimates = feeEstimates;
2108
+ await this.saveWalletData('feeEstimates', feeEstimates);
2109
+ return (0, utils_1.ok)(feeEstimates);
2110
+ }
2111
+ }
2112
+ exports.Wallet = Wallet;
2113
+ //# sourceMappingURL=index.js.map