@bitpay-labs/bitcore-wallet-service 11.5.2

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 (949) hide show
  1. package/.coveralls.yml +1 -0
  2. package/.travis.yml +27 -0
  3. package/DKG-flow.png +0 -0
  4. package/DSG-flow.png +0 -0
  5. package/Dockerfile +18 -0
  6. package/Installation.md +138 -0
  7. package/LICENCE +22 -0
  8. package/Makefile +5 -0
  9. package/README.md +429 -0
  10. package/TSS.md +136 -0
  11. package/bws.example.config.js +451 -0
  12. package/package.json +119 -0
  13. package/scripts/checkCopayerIds.js +118 -0
  14. package/scripts/clean_db.mongodb +5 -0
  15. package/scripts/deleteDupAddresses.mongo +6 -0
  16. package/scripts/deleteWallet.mongo +18 -0
  17. package/scripts/delme.ts +468 -0
  18. package/scripts/findEmail.js +32 -0
  19. package/scripts/fixAddressType.js +98 -0
  20. package/scripts/getSolStats2.js +81 -0
  21. package/scripts/migrateToNamedTestnets.js +191 -0
  22. package/scripts/migrateWalletsNetwork.js +204 -0
  23. package/scripts/preview-email.js +359 -0
  24. package/scripts/purgeNotifications.js +107 -0
  25. package/scripts/resetV8registration.mongo +21 -0
  26. package/scripts/v8tool-list.ts +93 -0
  27. package/scripts/v8tool.ts +82 -0
  28. package/scripts/walletStats.js +290 -0
  29. package/src/app.ts +28 -0
  30. package/src/bcmonitor/bcmonitor.ts +11 -0
  31. package/src/bws.ts +85 -0
  32. package/src/cleanfiatrates/cleanfiatrates.ts +9 -0
  33. package/src/config.ts +540 -0
  34. package/src/db/.empty +0 -0
  35. package/src/deprecated-serverMessages.ts +15 -0
  36. package/src/emailservice/emailservice.ts +11 -0
  37. package/src/externalservices/banxa.ts +261 -0
  38. package/src/externalservices/changelly.ts +371 -0
  39. package/src/externalservices/coingecko.ts +453 -0
  40. package/src/externalservices/moonpay.ts +435 -0
  41. package/src/externalservices/oneInch.ts +169 -0
  42. package/src/externalservices/ramp.ts +259 -0
  43. package/src/externalservices/sardine.ts +237 -0
  44. package/src/externalservices/simplex.ts +281 -0
  45. package/src/externalservices/thorswap.ts +197 -0
  46. package/src/externalservices/transak.ts +320 -0
  47. package/src/externalservices/wyre.ts +131 -0
  48. package/src/fiatrateservice/fiatrateservice.ts +15 -0
  49. package/src/index.ts +9 -0
  50. package/src/lib/bchaddresstranslator.ts +59 -0
  51. package/src/lib/blockchainexplorer.ts +84 -0
  52. package/src/lib/blockchainexplorers/v8/client.ts +177 -0
  53. package/src/lib/blockchainexplorers/v8.ts +730 -0
  54. package/src/lib/blockchainmonitor.ts +423 -0
  55. package/src/lib/chain/arb/index.ts +8 -0
  56. package/src/lib/chain/base/index.ts +8 -0
  57. package/src/lib/chain/bch/index.ts +40 -0
  58. package/src/lib/chain/btc/index.ts +991 -0
  59. package/src/lib/chain/doge/index.ts +387 -0
  60. package/src/lib/chain/eth/abi-erc20.ts +222 -0
  61. package/src/lib/chain/eth/abi-invoice.ts +277 -0
  62. package/src/lib/chain/eth/index.ts +657 -0
  63. package/src/lib/chain/index.ts +178 -0
  64. package/src/lib/chain/ltc/index.ts +9 -0
  65. package/src/lib/chain/matic/index.ts +8 -0
  66. package/src/lib/chain/op/index.ts +8 -0
  67. package/src/lib/chain/sol/index.ts +349 -0
  68. package/src/lib/chain/xrp/index.ts +338 -0
  69. package/src/lib/cleanfiatrates.ts +160 -0
  70. package/src/lib/common/constants.ts +231 -0
  71. package/src/lib/common/defaults.ts +436 -0
  72. package/src/lib/common/index.ts +11 -0
  73. package/src/lib/common/services.ts +43 -0
  74. package/src/lib/common/utils.ts +506 -0
  75. package/src/lib/emailservice.ts +741 -0
  76. package/src/lib/errors/clienterror.ts +44 -0
  77. package/src/lib/errors/errordefinitions.ts +158 -0
  78. package/src/lib/expressapp.ts +2415 -0
  79. package/src/lib/fiatrateproviders/bitpay.ts +20 -0
  80. package/src/lib/fiatrateproviders/bitstamp.ts +16 -0
  81. package/src/lib/fiatrateproviders/index.ts +8 -0
  82. package/src/lib/fiatrateproviders/provider.d.ts +10 -0
  83. package/src/lib/fiatrateservice.ts +338 -0
  84. package/src/lib/iconsconfig.ts +31 -0
  85. package/src/lib/index.ts +0 -0
  86. package/src/lib/lock.ts +112 -0
  87. package/src/lib/logger.ts +77 -0
  88. package/src/lib/messagebroker.ts +42 -0
  89. package/src/lib/model/address.ts +226 -0
  90. package/src/lib/model/addressmanager.ts +138 -0
  91. package/src/lib/model/advertisement.ts +84 -0
  92. package/src/lib/model/copayer.ts +162 -0
  93. package/src/lib/model/email.ts +103 -0
  94. package/src/lib/model/index.ts +12 -0
  95. package/src/lib/model/notification.ts +77 -0
  96. package/src/lib/model/preferences.ts +79 -0
  97. package/src/lib/model/pushnotificationsub.ts +50 -0
  98. package/src/lib/model/session.ts +65 -0
  99. package/src/lib/model/tsskeygen.ts +154 -0
  100. package/src/lib/model/tsssign.ts +136 -0
  101. package/src/lib/model/txconfirmationsub.ts +50 -0
  102. package/src/lib/model/txnote.ts +60 -0
  103. package/src/lib/model/txproposal.ts +561 -0
  104. package/src/lib/model/txproposal_legacy.ts +236 -0
  105. package/src/lib/model/txproposalaction.ts +48 -0
  106. package/src/lib/model/wallet.ts +359 -0
  107. package/src/lib/notificationbroadcaster.ts +17 -0
  108. package/src/lib/pushnotificationsservice.ts +802 -0
  109. package/src/lib/routes/helpers/error.ts +51 -0
  110. package/src/lib/routes/helpers/index.ts +1 -0
  111. package/src/lib/routes/middleware/authRequest.ts +117 -0
  112. package/src/lib/routes/middleware/authTssRequest.ts +66 -0
  113. package/src/lib/routes/middleware/createWalletLimiter.ts +21 -0
  114. package/src/lib/routes/middleware/log.ts +63 -0
  115. package/src/lib/routes/middleware/verifyTssMessage.ts +37 -0
  116. package/src/lib/routes/tss.ts +123 -0
  117. package/src/lib/server.ts +5342 -0
  118. package/src/lib/stats.ts +174 -0
  119. package/src/lib/storage.ts +1919 -0
  120. package/src/lib/tss.ts +446 -0
  121. package/src/lib/updatestats.ts +291 -0
  122. package/src/messagebroker/messagebroker.ts +18 -0
  123. package/src/pushnotificationsservice/pushnotificationsservice.ts +11 -0
  124. package/src/serverMessages.ts +30 -0
  125. package/src/types/chain.d.ts +62 -0
  126. package/src/types/emailservice.d.ts +11 -0
  127. package/src/types/expressapp.d.ts +15 -0
  128. package/src/types/externalservices.d.ts +41 -0
  129. package/src/types/notifications.d.ts +8 -0
  130. package/src/types/pushnotificationservice.d.ts +51 -0
  131. package/src/types/server.d.ts +24 -0
  132. package/src/updatestats/updatestats.ts +10 -0
  133. package/start-docker.sh +18 -0
  134. package/start.sh +38 -0
  135. package/static/images/down-arrow-green.png +0 -0
  136. package/static/images/failed-icon.png +0 -0
  137. package/static/images/green-check.png +0 -0
  138. package/static/images/person-plus.png +0 -0
  139. package/static/images/up-arrow-gray.png +0 -0
  140. package/static/images/writing-gray.png +0 -0
  141. package/stop.sh +19 -0
  142. package/templates/en/new_copayer.html +13 -0
  143. package/templates/en/new_copayer.plain +2 -0
  144. package/templates/en/new_incoming_tx.html +11 -0
  145. package/templates/en/new_incoming_tx.plain +2 -0
  146. package/templates/en/new_incoming_tx_testnet.html +13 -0
  147. package/templates/en/new_incoming_tx_testnet.plain +2 -0
  148. package/templates/en/new_outgoing_tx.html +11 -0
  149. package/templates/en/new_outgoing_tx.plain +2 -0
  150. package/templates/en/new_tx_proposal.html +13 -0
  151. package/templates/en/new_tx_proposal.plain +2 -0
  152. package/templates/en/new_zero_outgoing_tx.html +13 -0
  153. package/templates/en/new_zero_outgoing_tx.plain +2 -0
  154. package/templates/en/tx_confirmation.html +13 -0
  155. package/templates/en/tx_confirmation.plain +2 -0
  156. package/templates/en/tx_confirmation_receiver.html +13 -0
  157. package/templates/en/tx_confirmation_receiver.plain +2 -0
  158. package/templates/en/tx_confirmation_sender.html +13 -0
  159. package/templates/en/tx_confirmation_sender.plain +2 -0
  160. package/templates/en/txp_finally_rejected.html +13 -0
  161. package/templates/en/txp_finally_rejected.plain +2 -0
  162. package/templates/en/wallet_complete.html +13 -0
  163. package/templates/en/wallet_complete.plain +2 -0
  164. package/templates/es/new_copayer.html +13 -0
  165. package/templates/es/new_copayer.plain +2 -0
  166. package/templates/es/new_incoming_tx.html +11 -0
  167. package/templates/es/new_incoming_tx.plain +2 -0
  168. package/templates/es/new_incoming_tx_testnet.html +13 -0
  169. package/templates/es/new_incoming_tx_testnet.plain +2 -0
  170. package/templates/es/new_outgoing_tx.html +11 -0
  171. package/templates/es/new_outgoing_tx.plain +2 -0
  172. package/templates/es/new_tx_proposal.html +13 -0
  173. package/templates/es/new_tx_proposal.plain +2 -0
  174. package/templates/es/new_zero_outgoing_tx.html +13 -0
  175. package/templates/es/new_zero_outgoing_tx.plain +2 -0
  176. package/templates/es/tx_confirmation.html +13 -0
  177. package/templates/es/tx_confirmation.plain +2 -0
  178. package/templates/es/tx_confirmation_receiver.html +13 -0
  179. package/templates/es/tx_confirmation_receiver.plain +2 -0
  180. package/templates/es/tx_confirmation_sender.html +13 -0
  181. package/templates/es/tx_confirmation_sender.plain +2 -0
  182. package/templates/es/txp_finally_rejected.html +13 -0
  183. package/templates/es/txp_finally_rejected.plain +2 -0
  184. package/templates/es/wallet_complete.html +13 -0
  185. package/templates/es/wallet_complete.plain +2 -0
  186. package/templates/fr/new_copayer.html +13 -0
  187. package/templates/fr/new_copayer.plain +2 -0
  188. package/templates/fr/new_incoming_tx.html +11 -0
  189. package/templates/fr/new_incoming_tx.plain +2 -0
  190. package/templates/fr/new_incoming_tx_testnet.html +13 -0
  191. package/templates/fr/new_incoming_tx_testnet.plain +2 -0
  192. package/templates/fr/new_outgoing_tx.html +11 -0
  193. package/templates/fr/new_outgoing_tx.plain +2 -0
  194. package/templates/fr/new_tx_proposal.html +13 -0
  195. package/templates/fr/new_tx_proposal.plain +2 -0
  196. package/templates/fr/new_zero_outgoing_tx.html +13 -0
  197. package/templates/fr/new_zero_outgoing_tx.plain +2 -0
  198. package/templates/fr/tx_confirmation.html +13 -0
  199. package/templates/fr/tx_confirmation.plain +2 -0
  200. package/templates/fr/tx_confirmation_receiver.html +13 -0
  201. package/templates/fr/tx_confirmation_receiver.plain +2 -0
  202. package/templates/fr/tx_confirmation_sender.html +13 -0
  203. package/templates/fr/tx_confirmation_sender.plain +2 -0
  204. package/templates/fr/txp_finally_rejected.html +13 -0
  205. package/templates/fr/txp_finally_rejected.plain +2 -0
  206. package/templates/fr/wallet_complete.html +13 -0
  207. package/templates/fr/wallet_complete.plain +2 -0
  208. package/templates/ja/new_copayer.html +13 -0
  209. package/templates/ja/new_copayer.plain +2 -0
  210. package/templates/ja/new_incoming_tx.html +11 -0
  211. package/templates/ja/new_incoming_tx.plain +2 -0
  212. package/templates/ja/new_incoming_tx_testnet.html +13 -0
  213. package/templates/ja/new_incoming_tx_testnet.plain +2 -0
  214. package/templates/ja/new_outgoing_tx.html +11 -0
  215. package/templates/ja/new_outgoing_tx.plain +2 -0
  216. package/templates/ja/new_tx_proposal.html +13 -0
  217. package/templates/ja/new_tx_proposal.plain +2 -0
  218. package/templates/ja/new_zero_outgoing_tx.html +13 -0
  219. package/templates/ja/new_zero_outgoing_tx.plain +2 -0
  220. package/templates/ja/tx_confirmation.html +13 -0
  221. package/templates/ja/tx_confirmation.plain +2 -0
  222. package/templates/ja/tx_confirmation_receiver.html +13 -0
  223. package/templates/ja/tx_confirmation_receiver.plain +2 -0
  224. package/templates/ja/tx_confirmation_sender.html +13 -0
  225. package/templates/ja/tx_confirmation_sender.plain +2 -0
  226. package/templates/ja/txp_finally_rejected.html +13 -0
  227. package/templates/ja/txp_finally_rejected.plain +2 -0
  228. package/templates/ja/wallet_complete.html +13 -0
  229. package/templates/ja/wallet_complete.plain +2 -0
  230. package/templates/master-template.html +494 -0
  231. package/test/bchaddresstranslator.test.ts +50 -0
  232. package/test/blockchainexplorer.test.ts +66 -0
  233. package/test/chain/bch.test.ts +115 -0
  234. package/test/chain/btc.test.ts +331 -0
  235. package/test/chain/doge.test.ts +347 -0
  236. package/test/chain/eth.test.ts +21 -0
  237. package/test/chain/ltc.test.ts +328 -0
  238. package/test/chain/matic.test.ts +21 -0
  239. package/test/chain/xrp.test.ts +206 -0
  240. package/test/expressapp.test.ts +513 -0
  241. package/test/integration/bcmonitor.test.ts +381 -0
  242. package/test/integration/cashAddrMigration.test.ts +127 -0
  243. package/test/integration/data/tss/2of3/index.ts +3 -0
  244. package/test/integration/data/tss/2of3/party0.key.ts +5 -0
  245. package/test/integration/data/tss/2of3/party1.key.ts +5 -0
  246. package/test/integration/data/tss/2of3/party2.key.ts +5 -0
  247. package/test/integration/emailnotifications.test.ts +864 -0
  248. package/test/integration/externalservices/banxa.test.ts +373 -0
  249. package/test/integration/externalservices/changelly.test.ts +515 -0
  250. package/test/integration/externalservices/coinGecko.test.ts +284 -0
  251. package/test/integration/externalservices/moonpay.test.ts +569 -0
  252. package/test/integration/externalservices/oneInch.test.ts +162 -0
  253. package/test/integration/externalservices/ramp.test.ts +475 -0
  254. package/test/integration/externalservices/sardine.test.ts +352 -0
  255. package/test/integration/externalservices/simplex.test.ts +384 -0
  256. package/test/integration/externalservices/thorswap.test.ts +309 -0
  257. package/test/integration/externalservices/transak.test.ts +410 -0
  258. package/test/integration/externalservices/wyre.test.ts +270 -0
  259. package/test/integration/fiatrateservice.test.ts +979 -0
  260. package/test/integration/helpers.ts +694 -0
  261. package/test/integration/history.test.ts +1142 -0
  262. package/test/integration/hugetx.ts +6986 -0
  263. package/test/integration/pushNotifications.test.ts +1523 -0
  264. package/test/integration/server.test.ts +10740 -0
  265. package/test/integration/tss.test.ts +340 -0
  266. package/test/lock.test.ts +224 -0
  267. package/test/model/address.test.ts +187 -0
  268. package/test/model/addressmanager.test.ts +146 -0
  269. package/test/model/advertisement.test.ts +31 -0
  270. package/test/model/copayer.test.ts +131 -0
  271. package/test/model/txproposal.test.ts +185 -0
  272. package/test/model/wallet.test.ts +191 -0
  273. package/test/storage.test.ts +430 -0
  274. package/test/test-config.ts +12 -0
  275. package/test/testdata.ts +388 -0
  276. package/test/utils.test.ts +457 -0
  277. package/test/v8.test.ts +332 -0
  278. package/ts_build/package.json +119 -0
  279. package/ts_build/scripts/delme.d.ts +2 -0
  280. package/ts_build/scripts/delme.d.ts.map +1 -0
  281. package/ts_build/scripts/delme.js +453 -0
  282. package/ts_build/scripts/delme.js.map +1 -0
  283. package/ts_build/scripts/v8tool-list.d.ts +3 -0
  284. package/ts_build/scripts/v8tool-list.d.ts.map +1 -0
  285. package/ts_build/scripts/v8tool-list.js +80 -0
  286. package/ts_build/scripts/v8tool-list.js.map +1 -0
  287. package/ts_build/scripts/v8tool.d.ts +3 -0
  288. package/ts_build/scripts/v8tool.d.ts.map +1 -0
  289. package/ts_build/scripts/v8tool.js +69 -0
  290. package/ts_build/scripts/v8tool.js.map +1 -0
  291. package/ts_build/src/app.d.ts +3 -0
  292. package/ts_build/src/app.d.ts.map +1 -0
  293. package/ts_build/src/app.js +29 -0
  294. package/ts_build/src/app.js.map +1 -0
  295. package/ts_build/src/bcmonitor/bcmonitor.d.ts +3 -0
  296. package/ts_build/src/bcmonitor/bcmonitor.d.ts.map +1 -0
  297. package/ts_build/src/bcmonitor/bcmonitor.js +16 -0
  298. package/ts_build/src/bcmonitor/bcmonitor.js.map +1 -0
  299. package/ts_build/src/bws.d.ts +3 -0
  300. package/ts_build/src/bws.d.ts.map +1 -0
  301. package/ts_build/src/bws.js +98 -0
  302. package/ts_build/src/bws.js.map +1 -0
  303. package/ts_build/src/cleanfiatrates/cleanfiatrates.d.ts +3 -0
  304. package/ts_build/src/cleanfiatrates/cleanfiatrates.d.ts.map +1 -0
  305. package/ts_build/src/cleanfiatrates/cleanfiatrates.js +11 -0
  306. package/ts_build/src/cleanfiatrates/cleanfiatrates.js.map +1 -0
  307. package/ts_build/src/config.d.ts +3 -0
  308. package/ts_build/src/config.d.ts.map +1 -0
  309. package/ts_build/src/config.js +256 -0
  310. package/ts_build/src/config.js.map +1 -0
  311. package/ts_build/src/deprecated-serverMessages.d.ts +10 -0
  312. package/ts_build/src/deprecated-serverMessages.d.ts.map +1 -0
  313. package/ts_build/src/deprecated-serverMessages.js +20 -0
  314. package/ts_build/src/deprecated-serverMessages.js.map +1 -0
  315. package/ts_build/src/emailservice/emailservice.d.ts +3 -0
  316. package/ts_build/src/emailservice/emailservice.d.ts.map +1 -0
  317. package/ts_build/src/emailservice/emailservice.js +16 -0
  318. package/ts_build/src/emailservice/emailservice.js.map +1 -0
  319. package/ts_build/src/externalservices/banxa.d.ts +11 -0
  320. package/ts_build/src/externalservices/banxa.d.ts.map +1 -0
  321. package/ts_build/src/externalservices/banxa.js +254 -0
  322. package/ts_build/src/externalservices/banxa.js.map +1 -0
  323. package/ts_build/src/externalservices/changelly.d.ts +18 -0
  324. package/ts_build/src/externalservices/changelly.d.ts.map +1 -0
  325. package/ts_build/src/externalservices/changelly.js +356 -0
  326. package/ts_build/src/externalservices/changelly.js.map +1 -0
  327. package/ts_build/src/externalservices/coingecko.d.ts +43 -0
  328. package/ts_build/src/externalservices/coingecko.d.ts.map +1 -0
  329. package/ts_build/src/externalservices/coingecko.js +416 -0
  330. package/ts_build/src/externalservices/coingecko.js.map +1 -0
  331. package/ts_build/src/externalservices/moonpay.d.ts +19 -0
  332. package/ts_build/src/externalservices/moonpay.d.ts.map +1 -0
  333. package/ts_build/src/externalservices/moonpay.js +397 -0
  334. package/ts_build/src/externalservices/moonpay.js.map +1 -0
  335. package/ts_build/src/externalservices/oneInch.d.ts +11 -0
  336. package/ts_build/src/externalservices/oneInch.d.ts.map +1 -0
  337. package/ts_build/src/externalservices/oneInch.js +179 -0
  338. package/ts_build/src/externalservices/oneInch.js.map +1 -0
  339. package/ts_build/src/externalservices/ramp.d.ts +12 -0
  340. package/ts_build/src/externalservices/ramp.d.ts.map +1 -0
  341. package/ts_build/src/externalservices/ramp.js +256 -0
  342. package/ts_build/src/externalservices/ramp.js.map +1 -0
  343. package/ts_build/src/externalservices/sardine.d.ts +10 -0
  344. package/ts_build/src/externalservices/sardine.d.ts.map +1 -0
  345. package/ts_build/src/externalservices/sardine.js +232 -0
  346. package/ts_build/src/externalservices/sardine.js.map +1 -0
  347. package/ts_build/src/externalservices/simplex.d.ts +11 -0
  348. package/ts_build/src/externalservices/simplex.d.ts.map +1 -0
  349. package/ts_build/src/externalservices/simplex.js +261 -0
  350. package/ts_build/src/externalservices/simplex.js.map +1 -0
  351. package/ts_build/src/externalservices/thorswap.d.ts +9 -0
  352. package/ts_build/src/externalservices/thorswap.d.ts.map +1 -0
  353. package/ts_build/src/externalservices/thorswap.js +206 -0
  354. package/ts_build/src/externalservices/thorswap.js.map +1 -0
  355. package/ts_build/src/externalservices/transak.d.ts +13 -0
  356. package/ts_build/src/externalservices/transak.d.ts.map +1 -0
  357. package/ts_build/src/externalservices/transak.js +311 -0
  358. package/ts_build/src/externalservices/transak.js.map +1 -0
  359. package/ts_build/src/externalservices/wyre.d.ts +7 -0
  360. package/ts_build/src/externalservices/wyre.d.ts.map +1 -0
  361. package/ts_build/src/externalservices/wyre.js +144 -0
  362. package/ts_build/src/externalservices/wyre.js.map +1 -0
  363. package/ts_build/src/fiatrateservice/fiatrateservice.d.ts +3 -0
  364. package/ts_build/src/fiatrateservice/fiatrateservice.d.ts.map +1 -0
  365. package/ts_build/src/fiatrateservice/fiatrateservice.js +20 -0
  366. package/ts_build/src/fiatrateservice/fiatrateservice.js.map +1 -0
  367. package/ts_build/src/index.d.ts +8 -0
  368. package/ts_build/src/index.d.ts.map +1 -0
  369. package/ts_build/src/index.js +11 -0
  370. package/ts_build/src/index.js.map +1 -0
  371. package/ts_build/src/lib/bchaddresstranslator.d.ts +5 -0
  372. package/ts_build/src/lib/bchaddresstranslator.d.ts.map +1 -0
  373. package/ts_build/src/lib/bchaddresstranslator.js +66 -0
  374. package/ts_build/src/lib/bchaddresstranslator.js.map +1 -0
  375. package/ts_build/src/lib/blockchainexplorer.d.ts +3 -0
  376. package/ts_build/src/lib/blockchainexplorer.d.ts.map +1 -0
  377. package/ts_build/src/lib/blockchainexplorer.js +87 -0
  378. package/ts_build/src/lib/blockchainexplorer.js.map +1 -0
  379. package/ts_build/src/lib/blockchainexplorers/v8/client.d.ts +31 -0
  380. package/ts_build/src/lib/blockchainexplorers/v8/client.d.ts.map +1 -0
  381. package/ts_build/src/lib/blockchainexplorers/v8/client.js +191 -0
  382. package/ts_build/src/lib/blockchainexplorers/v8/client.js.map +1 -0
  383. package/ts_build/src/lib/blockchainexplorers/v8.d.ts +91 -0
  384. package/ts_build/src/lib/blockchainexplorers/v8.d.ts.map +1 -0
  385. package/ts_build/src/lib/blockchainexplorers/v8.js +662 -0
  386. package/ts_build/src/lib/blockchainexplorers/v8.js.map +1 -0
  387. package/ts_build/src/lib/blockchainmonitor.d.ts +32 -0
  388. package/ts_build/src/lib/blockchainmonitor.d.ts.map +1 -0
  389. package/ts_build/src/lib/blockchainmonitor.js +413 -0
  390. package/ts_build/src/lib/blockchainmonitor.js.map +1 -0
  391. package/ts_build/src/lib/chain/arb/index.d.ts +5 -0
  392. package/ts_build/src/lib/chain/arb/index.d.ts.map +1 -0
  393. package/ts_build/src/lib/chain/arb/index.js +12 -0
  394. package/ts_build/src/lib/chain/arb/index.js.map +1 -0
  395. package/ts_build/src/lib/chain/base/index.d.ts +5 -0
  396. package/ts_build/src/lib/chain/base/index.d.ts.map +1 -0
  397. package/ts_build/src/lib/chain/base/index.js +12 -0
  398. package/ts_build/src/lib/chain/base/index.js.map +1 -0
  399. package/ts_build/src/lib/chain/bch/index.d.ts +9 -0
  400. package/ts_build/src/lib/chain/bch/index.d.ts.map +1 -0
  401. package/ts_build/src/lib/chain/bch/index.js +43 -0
  402. package/ts_build/src/lib/chain/bch/index.js.map +1 -0
  403. package/ts_build/src/lib/chain/btc/index.d.ts +65 -0
  404. package/ts_build/src/lib/chain/btc/index.d.ts.map +1 -0
  405. package/ts_build/src/lib/chain/btc/index.js +829 -0
  406. package/ts_build/src/lib/chain/btc/index.js.map +1 -0
  407. package/ts_build/src/lib/chain/doge/index.d.ts +9 -0
  408. package/ts_build/src/lib/chain/doge/index.d.ts.map +1 -0
  409. package/ts_build/src/lib/chain/doge/index.js +338 -0
  410. package/ts_build/src/lib/chain/doge/index.js.map +1 -0
  411. package/ts_build/src/lib/chain/eth/abi-erc20.d.ts +39 -0
  412. package/ts_build/src/lib/chain/eth/abi-erc20.d.ts.map +1 -0
  413. package/ts_build/src/lib/chain/eth/abi-erc20.js +226 -0
  414. package/ts_build/src/lib/chain/eth/abi-erc20.js.map +1 -0
  415. package/ts_build/src/lib/chain/eth/abi-invoice.d.ts +42 -0
  416. package/ts_build/src/lib/chain/eth/abi-invoice.d.ts.map +1 -0
  417. package/ts_build/src/lib/chain/eth/abi-invoice.js +281 -0
  418. package/ts_build/src/lib/chain/eth/abi-invoice.js.map +1 -0
  419. package/ts_build/src/lib/chain/eth/index.d.ts +66 -0
  420. package/ts_build/src/lib/chain/eth/index.d.ts.map +1 -0
  421. package/ts_build/src/lib/chain/eth/index.js +516 -0
  422. package/ts_build/src/lib/chain/eth/index.js.map +1 -0
  423. package/ts_build/src/lib/chain/index.d.ts +40 -0
  424. package/ts_build/src/lib/chain/index.d.ts.map +1 -0
  425. package/ts_build/src/lib/chain/index.js +143 -0
  426. package/ts_build/src/lib/chain/index.js.map +1 -0
  427. package/ts_build/src/lib/chain/ltc/index.d.ts +6 -0
  428. package/ts_build/src/lib/chain/ltc/index.d.ts.map +1 -0
  429. package/ts_build/src/lib/chain/ltc/index.js +12 -0
  430. package/ts_build/src/lib/chain/ltc/index.js.map +1 -0
  431. package/ts_build/src/lib/chain/matic/index.d.ts +5 -0
  432. package/ts_build/src/lib/chain/matic/index.d.ts.map +1 -0
  433. package/ts_build/src/lib/chain/matic/index.js +12 -0
  434. package/ts_build/src/lib/chain/matic/index.js.map +1 -0
  435. package/ts_build/src/lib/chain/op/index.d.ts +5 -0
  436. package/ts_build/src/lib/chain/op/index.d.ts.map +1 -0
  437. package/ts_build/src/lib/chain/op/index.js +12 -0
  438. package/ts_build/src/lib/chain/op/index.js.map +1 -0
  439. package/ts_build/src/lib/chain/sol/index.d.ts +52 -0
  440. package/ts_build/src/lib/chain/sol/index.d.ts.map +1 -0
  441. package/ts_build/src/lib/chain/sol/index.js +305 -0
  442. package/ts_build/src/lib/chain/sol/index.js.map +1 -0
  443. package/ts_build/src/lib/chain/xrp/index.d.ts +46 -0
  444. package/ts_build/src/lib/chain/xrp/index.d.ts.map +1 -0
  445. package/ts_build/src/lib/chain/xrp/index.js +300 -0
  446. package/ts_build/src/lib/chain/xrp/index.js.map +1 -0
  447. package/ts_build/src/lib/cleanfiatrates.d.ts +13 -0
  448. package/ts_build/src/lib/cleanfiatrates.d.ts.map +1 -0
  449. package/ts_build/src/lib/cleanfiatrates.js +176 -0
  450. package/ts_build/src/lib/cleanfiatrates.js.map +1 -0
  451. package/ts_build/src/lib/common/constants.d.ts +387 -0
  452. package/ts_build/src/lib/common/constants.d.ts.map +1 -0
  453. package/ts_build/src/lib/common/constants.js +234 -0
  454. package/ts_build/src/lib/common/constants.js.map +1 -0
  455. package/ts_build/src/lib/common/defaults.d.ts +326 -0
  456. package/ts_build/src/lib/common/defaults.d.ts.map +1 -0
  457. package/ts_build/src/lib/common/defaults.js +356 -0
  458. package/ts_build/src/lib/common/defaults.js.map +1 -0
  459. package/ts_build/src/lib/common/index.d.ts +793 -0
  460. package/ts_build/src/lib/common/index.d.ts.map +1 -0
  461. package/ts_build/src/lib/common/index.js +14 -0
  462. package/ts_build/src/lib/common/index.js.map +1 -0
  463. package/ts_build/src/lib/common/services.d.ts +34 -0
  464. package/ts_build/src/lib/common/services.d.ts.map +1 -0
  465. package/ts_build/src/lib/common/services.js +44 -0
  466. package/ts_build/src/lib/common/services.js.map +1 -0
  467. package/ts_build/src/lib/common/utils.d.ts +47 -0
  468. package/ts_build/src/lib/common/utils.d.ts.map +1 -0
  469. package/ts_build/src/lib/common/utils.js +385 -0
  470. package/ts_build/src/lib/common/utils.js.map +1 -0
  471. package/ts_build/src/lib/emailservice.d.ts +62 -0
  472. package/ts_build/src/lib/emailservice.d.ts.map +1 -0
  473. package/ts_build/src/lib/emailservice.js +727 -0
  474. package/ts_build/src/lib/emailservice.js.map +1 -0
  475. package/ts_build/src/lib/errors/clienterror.d.ts +11 -0
  476. package/ts_build/src/lib/errors/clienterror.d.ts.map +1 -0
  477. package/ts_build/src/lib/errors/clienterror.js +46 -0
  478. package/ts_build/src/lib/errors/clienterror.js.map +1 -0
  479. package/ts_build/src/lib/errors/errordefinitions.d.ts +76 -0
  480. package/ts_build/src/lib/errors/errordefinitions.d.ts.map +1 -0
  481. package/ts_build/src/lib/errors/errordefinitions.js +82 -0
  482. package/ts_build/src/lib/errors/errordefinitions.js.map +1 -0
  483. package/ts_build/src/lib/expressapp.d.ts +8 -0
  484. package/ts_build/src/lib/expressapp.d.ts.map +1 -0
  485. package/ts_build/src/lib/expressapp.js +2221 -0
  486. package/ts_build/src/lib/expressapp.js.map +1 -0
  487. package/ts_build/src/lib/fiatrateproviders/bitpay.d.ts +3 -0
  488. package/ts_build/src/lib/fiatrateproviders/bitpay.d.ts.map +1 -0
  489. package/ts_build/src/lib/fiatrateproviders/bitpay.js +22 -0
  490. package/ts_build/src/lib/fiatrateproviders/bitpay.js.map +1 -0
  491. package/ts_build/src/lib/fiatrateproviders/bitstamp.d.ts +3 -0
  492. package/ts_build/src/lib/fiatrateproviders/bitstamp.d.ts.map +1 -0
  493. package/ts_build/src/lib/fiatrateproviders/bitstamp.js +18 -0
  494. package/ts_build/src/lib/fiatrateproviders/bitstamp.js.map +1 -0
  495. package/ts_build/src/lib/fiatrateproviders/index.d.ts +3 -0
  496. package/ts_build/src/lib/fiatrateproviders/index.d.ts.map +1 -0
  497. package/ts_build/src/lib/fiatrateproviders/index.js +8 -0
  498. package/ts_build/src/lib/fiatrateproviders/index.js.map +1 -0
  499. package/ts_build/src/lib/fiatrateservice.d.ts +18 -0
  500. package/ts_build/src/lib/fiatrateservice.d.ts.map +1 -0
  501. package/ts_build/src/lib/fiatrateservice.js +313 -0
  502. package/ts_build/src/lib/fiatrateservice.js.map +1 -0
  503. package/ts_build/src/lib/iconsconfig.d.ts +2 -0
  504. package/ts_build/src/lib/iconsconfig.d.ts.map +1 -0
  505. package/ts_build/src/lib/iconsconfig.js +31 -0
  506. package/ts_build/src/lib/iconsconfig.js.map +1 -0
  507. package/ts_build/src/lib/index.d.ts +1 -0
  508. package/ts_build/src/lib/index.d.ts.map +1 -0
  509. package/ts_build/src/lib/index.js +1 -0
  510. package/ts_build/src/lib/index.js.map +1 -0
  511. package/ts_build/src/lib/lock.d.ts +14 -0
  512. package/ts_build/src/lib/lock.d.ts.map +1 -0
  513. package/ts_build/src/lib/lock.js +55 -0
  514. package/ts_build/src/lib/lock.js.map +1 -0
  515. package/ts_build/src/lib/logger.d.ts +7 -0
  516. package/ts_build/src/lib/logger.d.ts.map +1 -0
  517. package/ts_build/src/lib/logger.js +95 -0
  518. package/ts_build/src/lib/logger.js.map +1 -0
  519. package/ts_build/src/lib/messagebroker.d.ts +11 -0
  520. package/ts_build/src/lib/messagebroker.d.ts.map +1 -0
  521. package/ts_build/src/lib/messagebroker.js +77 -0
  522. package/ts_build/src/lib/messagebroker.js.map +1 -0
  523. package/ts_build/src/lib/model/address.d.ts +47 -0
  524. package/ts_build/src/lib/model/address.d.ts.map +1 -0
  525. package/ts_build/src/lib/model/address.js +158 -0
  526. package/ts_build/src/lib/model/address.js.map +1 -0
  527. package/ts_build/src/lib/model/addressmanager.d.ts +41 -0
  528. package/ts_build/src/lib/model/addressmanager.d.ts.map +1 -0
  529. package/ts_build/src/lib/model/addressmanager.js +103 -0
  530. package/ts_build/src/lib/model/addressmanager.js.map +1 -0
  531. package/ts_build/src/lib/model/advertisement.d.ts +38 -0
  532. package/ts_build/src/lib/model/advertisement.d.ts.map +1 -0
  533. package/ts_build/src/lib/model/advertisement.js +68 -0
  534. package/ts_build/src/lib/model/advertisement.js.map +1 -0
  535. package/ts_build/src/lib/model/copayer.d.ts +48 -0
  536. package/ts_build/src/lib/model/copayer.d.ts.map +1 -0
  537. package/ts_build/src/lib/model/copayer.js +116 -0
  538. package/ts_build/src/lib/model/copayer.js.map +1 -0
  539. package/ts_build/src/lib/model/email.d.ts +23 -0
  540. package/ts_build/src/lib/model/email.d.ts.map +1 -0
  541. package/ts_build/src/lib/model/email.js +84 -0
  542. package/ts_build/src/lib/model/email.js.map +1 -0
  543. package/ts_build/src/lib/model/index.d.ts +13 -0
  544. package/ts_build/src/lib/model/index.d.ts.map +1 -0
  545. package/ts_build/src/lib/model/index.js +28 -0
  546. package/ts_build/src/lib/model/index.js.map +1 -0
  547. package/ts_build/src/lib/model/notification.d.ts +23 -0
  548. package/ts_build/src/lib/model/notification.d.ts.map +1 -0
  549. package/ts_build/src/lib/model/notification.js +40 -0
  550. package/ts_build/src/lib/model/notification.js.map +1 -0
  551. package/ts_build/src/lib/model/preferences.d.ts +37 -0
  552. package/ts_build/src/lib/model/preferences.d.ts.map +1 -0
  553. package/ts_build/src/lib/model/preferences.js +61 -0
  554. package/ts_build/src/lib/model/preferences.js.map +1 -0
  555. package/ts_build/src/lib/model/pushnotificationsub.d.ts +23 -0
  556. package/ts_build/src/lib/model/pushnotificationsub.d.ts.map +1 -0
  557. package/ts_build/src/lib/model/pushnotificationsub.js +40 -0
  558. package/ts_build/src/lib/model/pushnotificationsub.js.map +1 -0
  559. package/ts_build/src/lib/model/session.d.ts +22 -0
  560. package/ts_build/src/lib/model/session.d.ts.map +1 -0
  561. package/ts_build/src/lib/model/session.js +52 -0
  562. package/ts_build/src/lib/model/session.js.map +1 -0
  563. package/ts_build/src/lib/model/tsskeygen.d.ts +67 -0
  564. package/ts_build/src/lib/model/tsskeygen.d.ts.map +1 -0
  565. package/ts_build/src/lib/model/tsskeygen.js +69 -0
  566. package/ts_build/src/lib/model/tsskeygen.js.map +1 -0
  567. package/ts_build/src/lib/model/tsssign.d.ts +70 -0
  568. package/ts_build/src/lib/model/tsssign.d.ts.map +1 -0
  569. package/ts_build/src/lib/model/tsssign.js +54 -0
  570. package/ts_build/src/lib/model/tsssign.js.map +1 -0
  571. package/ts_build/src/lib/model/txconfirmationsub.d.ts +23 -0
  572. package/ts_build/src/lib/model/txconfirmationsub.d.ts.map +1 -0
  573. package/ts_build/src/lib/model/txconfirmationsub.js +40 -0
  574. package/ts_build/src/lib/model/txconfirmationsub.js.map +1 -0
  575. package/ts_build/src/lib/model/txnote.d.ts +23 -0
  576. package/ts_build/src/lib/model/txnote.d.ts.map +1 -0
  577. package/ts_build/src/lib/model/txnote.js +46 -0
  578. package/ts_build/src/lib/model/txnote.js.map +1 -0
  579. package/ts_build/src/lib/model/txproposal.d.ts +196 -0
  580. package/ts_build/src/lib/model/txproposal.d.ts.map +1 -0
  581. package/ts_build/src/lib/model/txproposal.js +382 -0
  582. package/ts_build/src/lib/model/txproposal.js.map +1 -0
  583. package/ts_build/src/lib/model/txproposal_legacy.d.ts +93 -0
  584. package/ts_build/src/lib/model/txproposal_legacy.d.ts.map +1 -0
  585. package/ts_build/src/lib/model/txproposal_legacy.js +185 -0
  586. package/ts_build/src/lib/model/txproposal_legacy.js.map +1 -0
  587. package/ts_build/src/lib/model/txproposalaction.d.ts +21 -0
  588. package/ts_build/src/lib/model/txproposalaction.d.ts.map +1 -0
  589. package/ts_build/src/lib/model/txproposalaction.js +37 -0
  590. package/ts_build/src/lib/model/txproposalaction.js.map +1 -0
  591. package/ts_build/src/lib/model/wallet.d.ts +110 -0
  592. package/ts_build/src/lib/model/wallet.d.ts.map +1 -0
  593. package/ts_build/src/lib/model/wallet.js +224 -0
  594. package/ts_build/src/lib/model/wallet.js.map +1 -0
  595. package/ts_build/src/lib/notificationbroadcaster.d.ts +6 -0
  596. package/ts_build/src/lib/notificationbroadcaster.d.ts.map +1 -0
  597. package/ts_build/src/lib/notificationbroadcaster.js +19 -0
  598. package/ts_build/src/lib/notificationbroadcaster.js.map +1 -0
  599. package/ts_build/src/lib/pushnotificationsservice.d.ts +56 -0
  600. package/ts_build/src/lib/pushnotificationsservice.d.ts.map +1 -0
  601. package/ts_build/src/lib/pushnotificationsservice.js +721 -0
  602. package/ts_build/src/lib/pushnotificationsservice.js.map +1 -0
  603. package/ts_build/src/lib/routes/helpers/error.d.ts +10 -0
  604. package/ts_build/src/lib/routes/helpers/error.d.ts.map +1 -0
  605. package/ts_build/src/lib/routes/helpers/error.js +54 -0
  606. package/ts_build/src/lib/routes/helpers/error.js.map +1 -0
  607. package/ts_build/src/lib/routes/helpers/index.d.ts +2 -0
  608. package/ts_build/src/lib/routes/helpers/index.d.ts.map +1 -0
  609. package/ts_build/src/lib/routes/helpers/index.js +18 -0
  610. package/ts_build/src/lib/routes/helpers/index.js.map +1 -0
  611. package/ts_build/src/lib/routes/middleware/authRequest.d.ts +6 -0
  612. package/ts_build/src/lib/routes/middleware/authRequest.d.ts.map +1 -0
  613. package/ts_build/src/lib/routes/middleware/authRequest.js +106 -0
  614. package/ts_build/src/lib/routes/middleware/authRequest.js.map +1 -0
  615. package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts +3 -0
  616. package/ts_build/src/lib/routes/middleware/authTssRequest.d.ts.map +1 -0
  617. package/ts_build/src/lib/routes/middleware/authTssRequest.js +56 -0
  618. package/ts_build/src/lib/routes/middleware/authTssRequest.js.map +1 -0
  619. package/ts_build/src/lib/routes/middleware/createWalletLimiter.d.ts +4 -0
  620. package/ts_build/src/lib/routes/middleware/createWalletLimiter.d.ts.map +1 -0
  621. package/ts_build/src/lib/routes/middleware/createWalletLimiter.js +28 -0
  622. package/ts_build/src/lib/routes/middleware/createWalletLimiter.js.map +1 -0
  623. package/ts_build/src/lib/routes/middleware/log.d.ts +9 -0
  624. package/ts_build/src/lib/routes/middleware/log.d.ts.map +1 -0
  625. package/ts_build/src/lib/routes/middleware/log.js +52 -0
  626. package/ts_build/src/lib/routes/middleware/log.js.map +1 -0
  627. package/ts_build/src/lib/routes/middleware/verifyTssMessage.d.ts +2 -0
  628. package/ts_build/src/lib/routes/middleware/verifyTssMessage.d.ts.map +1 -0
  629. package/ts_build/src/lib/routes/middleware/verifyTssMessage.js +34 -0
  630. package/ts_build/src/lib/routes/middleware/verifyTssMessage.js.map +1 -0
  631. package/ts_build/src/lib/routes/tss.d.ts +14 -0
  632. package/ts_build/src/lib/routes/tss.d.ts.map +1 -0
  633. package/ts_build/src/lib/routes/tss.js +120 -0
  634. package/ts_build/src/lib/routes/tss.js.map +1 -0
  635. package/ts_build/src/lib/server.d.ts +250 -0
  636. package/ts_build/src/lib/server.d.ts.map +1 -0
  637. package/ts_build/src/lib/server.js +4115 -0
  638. package/ts_build/src/lib/server.js.map +1 -0
  639. package/ts_build/src/lib/stats.d.ts +17 -0
  640. package/ts_build/src/lib/stats.d.ts.map +1 -0
  641. package/ts_build/src/lib/stats.js +203 -0
  642. package/ts_build/src/lib/stats.js.map +1 -0
  643. package/ts_build/src/lib/storage.d.ts +163 -0
  644. package/ts_build/src/lib/storage.d.ts.map +1 -0
  645. package/ts_build/src/lib/storage.js +1513 -0
  646. package/ts_build/src/lib/storage.js.map +1 -0
  647. package/ts_build/src/lib/tss.d.ts +70 -0
  648. package/ts_build/src/lib/tss.d.ts.map +1 -0
  649. package/ts_build/src/lib/tss.js +379 -0
  650. package/ts_build/src/lib/tss.js.map +1 -0
  651. package/ts_build/src/lib/updatestats.d.ts +16 -0
  652. package/ts_build/src/lib/updatestats.d.ts.map +1 -0
  653. package/ts_build/src/lib/updatestats.js +308 -0
  654. package/ts_build/src/lib/updatestats.js.map +1 -0
  655. package/ts_build/src/messagebroker/messagebroker.d.ts +3 -0
  656. package/ts_build/src/messagebroker/messagebroker.d.ts.map +1 -0
  657. package/ts_build/src/messagebroker/messagebroker.js +20 -0
  658. package/ts_build/src/messagebroker/messagebroker.js.map +1 -0
  659. package/ts_build/src/pushnotificationsservice/pushnotificationsservice.d.ts +3 -0
  660. package/ts_build/src/pushnotificationsservice/pushnotificationsservice.d.ts.map +1 -0
  661. package/ts_build/src/pushnotificationsservice/pushnotificationsservice.js +16 -0
  662. package/ts_build/src/pushnotificationsservice/pushnotificationsservice.js.map +1 -0
  663. package/ts_build/src/serverMessages.d.ts +2 -0
  664. package/ts_build/src/serverMessages.d.ts.map +1 -0
  665. package/ts_build/src/serverMessages.js +35 -0
  666. package/ts_build/src/serverMessages.js.map +1 -0
  667. package/ts_build/src/updatestats/updatestats.d.ts +3 -0
  668. package/ts_build/src/updatestats/updatestats.d.ts.map +1 -0
  669. package/ts_build/src/updatestats/updatestats.js +15 -0
  670. package/ts_build/src/updatestats/updatestats.js.map +1 -0
  671. package/ts_build/templates/en/new_copayer.html +13 -0
  672. package/ts_build/templates/en/new_copayer.plain +2 -0
  673. package/ts_build/templates/en/new_incoming_tx.html +11 -0
  674. package/ts_build/templates/en/new_incoming_tx.plain +2 -0
  675. package/ts_build/templates/en/new_incoming_tx_testnet.html +13 -0
  676. package/ts_build/templates/en/new_incoming_tx_testnet.plain +2 -0
  677. package/ts_build/templates/en/new_outgoing_tx.html +11 -0
  678. package/ts_build/templates/en/new_outgoing_tx.plain +2 -0
  679. package/ts_build/templates/en/new_tx_proposal.html +13 -0
  680. package/ts_build/templates/en/new_tx_proposal.plain +2 -0
  681. package/ts_build/templates/en/new_zero_outgoing_tx.html +13 -0
  682. package/ts_build/templates/en/new_zero_outgoing_tx.plain +2 -0
  683. package/ts_build/templates/en/tx_confirmation.html +13 -0
  684. package/ts_build/templates/en/tx_confirmation.plain +2 -0
  685. package/ts_build/templates/en/tx_confirmation_receiver.html +13 -0
  686. package/ts_build/templates/en/tx_confirmation_receiver.plain +2 -0
  687. package/ts_build/templates/en/tx_confirmation_sender.html +13 -0
  688. package/ts_build/templates/en/tx_confirmation_sender.plain +2 -0
  689. package/ts_build/templates/en/txp_finally_rejected.html +13 -0
  690. package/ts_build/templates/en/txp_finally_rejected.plain +2 -0
  691. package/ts_build/templates/en/wallet_complete.html +13 -0
  692. package/ts_build/templates/en/wallet_complete.plain +2 -0
  693. package/ts_build/templates/es/new_copayer.html +13 -0
  694. package/ts_build/templates/es/new_copayer.plain +2 -0
  695. package/ts_build/templates/es/new_incoming_tx.html +11 -0
  696. package/ts_build/templates/es/new_incoming_tx.plain +2 -0
  697. package/ts_build/templates/es/new_incoming_tx_testnet.html +13 -0
  698. package/ts_build/templates/es/new_incoming_tx_testnet.plain +2 -0
  699. package/ts_build/templates/es/new_outgoing_tx.html +11 -0
  700. package/ts_build/templates/es/new_outgoing_tx.plain +2 -0
  701. package/ts_build/templates/es/new_tx_proposal.html +13 -0
  702. package/ts_build/templates/es/new_tx_proposal.plain +2 -0
  703. package/ts_build/templates/es/new_zero_outgoing_tx.html +13 -0
  704. package/ts_build/templates/es/new_zero_outgoing_tx.plain +2 -0
  705. package/ts_build/templates/es/tx_confirmation.html +13 -0
  706. package/ts_build/templates/es/tx_confirmation.plain +2 -0
  707. package/ts_build/templates/es/tx_confirmation_receiver.html +13 -0
  708. package/ts_build/templates/es/tx_confirmation_receiver.plain +2 -0
  709. package/ts_build/templates/es/tx_confirmation_sender.html +13 -0
  710. package/ts_build/templates/es/tx_confirmation_sender.plain +2 -0
  711. package/ts_build/templates/es/txp_finally_rejected.html +13 -0
  712. package/ts_build/templates/es/txp_finally_rejected.plain +2 -0
  713. package/ts_build/templates/es/wallet_complete.html +13 -0
  714. package/ts_build/templates/es/wallet_complete.plain +2 -0
  715. package/ts_build/templates/fr/new_copayer.html +13 -0
  716. package/ts_build/templates/fr/new_copayer.plain +2 -0
  717. package/ts_build/templates/fr/new_incoming_tx.html +11 -0
  718. package/ts_build/templates/fr/new_incoming_tx.plain +2 -0
  719. package/ts_build/templates/fr/new_incoming_tx_testnet.html +13 -0
  720. package/ts_build/templates/fr/new_incoming_tx_testnet.plain +2 -0
  721. package/ts_build/templates/fr/new_outgoing_tx.html +11 -0
  722. package/ts_build/templates/fr/new_outgoing_tx.plain +2 -0
  723. package/ts_build/templates/fr/new_tx_proposal.html +13 -0
  724. package/ts_build/templates/fr/new_tx_proposal.plain +2 -0
  725. package/ts_build/templates/fr/new_zero_outgoing_tx.html +13 -0
  726. package/ts_build/templates/fr/new_zero_outgoing_tx.plain +2 -0
  727. package/ts_build/templates/fr/tx_confirmation.html +13 -0
  728. package/ts_build/templates/fr/tx_confirmation.plain +2 -0
  729. package/ts_build/templates/fr/tx_confirmation_receiver.html +13 -0
  730. package/ts_build/templates/fr/tx_confirmation_receiver.plain +2 -0
  731. package/ts_build/templates/fr/tx_confirmation_sender.html +13 -0
  732. package/ts_build/templates/fr/tx_confirmation_sender.plain +2 -0
  733. package/ts_build/templates/fr/txp_finally_rejected.html +13 -0
  734. package/ts_build/templates/fr/txp_finally_rejected.plain +2 -0
  735. package/ts_build/templates/fr/wallet_complete.html +13 -0
  736. package/ts_build/templates/fr/wallet_complete.plain +2 -0
  737. package/ts_build/templates/ja/new_copayer.html +13 -0
  738. package/ts_build/templates/ja/new_copayer.plain +2 -0
  739. package/ts_build/templates/ja/new_incoming_tx.html +11 -0
  740. package/ts_build/templates/ja/new_incoming_tx.plain +2 -0
  741. package/ts_build/templates/ja/new_incoming_tx_testnet.html +13 -0
  742. package/ts_build/templates/ja/new_incoming_tx_testnet.plain +2 -0
  743. package/ts_build/templates/ja/new_outgoing_tx.html +11 -0
  744. package/ts_build/templates/ja/new_outgoing_tx.plain +2 -0
  745. package/ts_build/templates/ja/new_tx_proposal.html +13 -0
  746. package/ts_build/templates/ja/new_tx_proposal.plain +2 -0
  747. package/ts_build/templates/ja/new_zero_outgoing_tx.html +13 -0
  748. package/ts_build/templates/ja/new_zero_outgoing_tx.plain +2 -0
  749. package/ts_build/templates/ja/tx_confirmation.html +13 -0
  750. package/ts_build/templates/ja/tx_confirmation.plain +2 -0
  751. package/ts_build/templates/ja/tx_confirmation_receiver.html +13 -0
  752. package/ts_build/templates/ja/tx_confirmation_receiver.plain +2 -0
  753. package/ts_build/templates/ja/tx_confirmation_sender.html +13 -0
  754. package/ts_build/templates/ja/tx_confirmation_sender.plain +2 -0
  755. package/ts_build/templates/ja/txp_finally_rejected.html +13 -0
  756. package/ts_build/templates/ja/txp_finally_rejected.plain +2 -0
  757. package/ts_build/templates/ja/wallet_complete.html +13 -0
  758. package/ts_build/templates/ja/wallet_complete.plain +2 -0
  759. package/ts_build/templates/master-template.html +494 -0
  760. package/ts_build/test/bchaddresstranslator.test.d.ts +2 -0
  761. package/ts_build/test/bchaddresstranslator.test.d.ts.map +1 -0
  762. package/ts_build/test/bchaddresstranslator.test.js +76 -0
  763. package/ts_build/test/bchaddresstranslator.test.js.map +1 -0
  764. package/ts_build/test/blockchainexplorer.test.d.ts +2 -0
  765. package/ts_build/test/blockchainexplorer.test.d.ts.map +1 -0
  766. package/ts_build/test/blockchainexplorer.test.js +98 -0
  767. package/ts_build/test/blockchainexplorer.test.js.map +1 -0
  768. package/ts_build/test/chain/bch.test.d.ts +2 -0
  769. package/ts_build/test/chain/bch.test.d.ts.map +1 -0
  770. package/ts_build/test/chain/bch.test.js +135 -0
  771. package/ts_build/test/chain/bch.test.js.map +1 -0
  772. package/ts_build/test/chain/btc.test.d.ts +2 -0
  773. package/ts_build/test/chain/btc.test.d.ts.map +1 -0
  774. package/ts_build/test/chain/btc.test.js +310 -0
  775. package/ts_build/test/chain/btc.test.js.map +1 -0
  776. package/ts_build/test/chain/doge.test.d.ts +2 -0
  777. package/ts_build/test/chain/doge.test.d.ts.map +1 -0
  778. package/ts_build/test/chain/doge.test.js +343 -0
  779. package/ts_build/test/chain/doge.test.js.map +1 -0
  780. package/ts_build/test/chain/eth.test.d.ts +2 -0
  781. package/ts_build/test/chain/eth.test.d.ts.map +1 -0
  782. package/ts_build/test/chain/eth.test.js +51 -0
  783. package/ts_build/test/chain/eth.test.js.map +1 -0
  784. package/ts_build/test/chain/ltc.test.d.ts +2 -0
  785. package/ts_build/test/chain/ltc.test.d.ts.map +1 -0
  786. package/ts_build/test/chain/ltc.test.js +323 -0
  787. package/ts_build/test/chain/ltc.test.js.map +1 -0
  788. package/ts_build/test/chain/matic.test.d.ts +2 -0
  789. package/ts_build/test/chain/matic.test.d.ts.map +1 -0
  790. package/ts_build/test/chain/matic.test.js +51 -0
  791. package/ts_build/test/chain/matic.test.js.map +1 -0
  792. package/ts_build/test/chain/xrp.test.d.ts +2 -0
  793. package/ts_build/test/chain/xrp.test.d.ts.map +1 -0
  794. package/ts_build/test/chain/xrp.test.js +228 -0
  795. package/ts_build/test/chain/xrp.test.js.map +1 -0
  796. package/ts_build/test/expressapp.test.d.ts +2 -0
  797. package/ts_build/test/expressapp.test.d.ts.map +1 -0
  798. package/ts_build/test/expressapp.test.js +523 -0
  799. package/ts_build/test/expressapp.test.js.map +1 -0
  800. package/ts_build/test/integration/bcmonitor.test.d.ts +2 -0
  801. package/ts_build/test/integration/bcmonitor.test.d.ts.map +1 -0
  802. package/ts_build/test/integration/bcmonitor.test.js +375 -0
  803. package/ts_build/test/integration/bcmonitor.test.js.map +1 -0
  804. package/ts_build/test/integration/cashAddrMigration.test.d.ts +2 -0
  805. package/ts_build/test/integration/cashAddrMigration.test.d.ts.map +1 -0
  806. package/ts_build/test/integration/cashAddrMigration.test.js +147 -0
  807. package/ts_build/test/integration/cashAddrMigration.test.js.map +1 -0
  808. package/ts_build/test/integration/data/tss/2of3/index.d.ts +4 -0
  809. package/ts_build/test/integration/data/tss/2of3/index.d.ts.map +1 -0
  810. package/ts_build/test/integration/data/tss/2of3/index.js +20 -0
  811. package/ts_build/test/integration/data/tss/2of3/index.js.map +1 -0
  812. package/ts_build/test/integration/data/tss/2of3/party0.key.d.ts +6 -0
  813. package/ts_build/test/integration/data/tss/2of3/party0.key.d.ts.map +1 -0
  814. package/ts_build/test/integration/data/tss/2of3/party0.key.js +9 -0
  815. package/ts_build/test/integration/data/tss/2of3/party0.key.js.map +1 -0
  816. package/ts_build/test/integration/data/tss/2of3/party1.key.d.ts +6 -0
  817. package/ts_build/test/integration/data/tss/2of3/party1.key.d.ts.map +1 -0
  818. package/ts_build/test/integration/data/tss/2of3/party1.key.js +9 -0
  819. package/ts_build/test/integration/data/tss/2of3/party1.key.js.map +1 -0
  820. package/ts_build/test/integration/data/tss/2of3/party2.key.d.ts +6 -0
  821. package/ts_build/test/integration/data/tss/2of3/party2.key.d.ts.map +1 -0
  822. package/ts_build/test/integration/data/tss/2of3/party2.key.js +9 -0
  823. package/ts_build/test/integration/data/tss/2of3/party2.key.js.map +1 -0
  824. package/ts_build/test/integration/emailnotifications.test.d.ts +2 -0
  825. package/ts_build/test/integration/emailnotifications.test.d.ts.map +1 -0
  826. package/ts_build/test/integration/emailnotifications.test.js +805 -0
  827. package/ts_build/test/integration/emailnotifications.test.js.map +1 -0
  828. package/ts_build/test/integration/externalservices/banxa.test.d.ts +2 -0
  829. package/ts_build/test/integration/externalservices/banxa.test.d.ts.map +1 -0
  830. package/ts_build/test/integration/externalservices/banxa.test.js +382 -0
  831. package/ts_build/test/integration/externalservices/banxa.test.js.map +1 -0
  832. package/ts_build/test/integration/externalservices/changelly.test.d.ts +2 -0
  833. package/ts_build/test/integration/externalservices/changelly.test.d.ts.map +1 -0
  834. package/ts_build/test/integration/externalservices/changelly.test.js +509 -0
  835. package/ts_build/test/integration/externalservices/changelly.test.js.map +1 -0
  836. package/ts_build/test/integration/externalservices/coinGecko.test.d.ts +2 -0
  837. package/ts_build/test/integration/externalservices/coinGecko.test.d.ts.map +1 -0
  838. package/ts_build/test/integration/externalservices/coinGecko.test.js +295 -0
  839. package/ts_build/test/integration/externalservices/coinGecko.test.js.map +1 -0
  840. package/ts_build/test/integration/externalservices/moonpay.test.d.ts +2 -0
  841. package/ts_build/test/integration/externalservices/moonpay.test.d.ts.map +1 -0
  842. package/ts_build/test/integration/externalservices/moonpay.test.js +567 -0
  843. package/ts_build/test/integration/externalservices/moonpay.test.js.map +1 -0
  844. package/ts_build/test/integration/externalservices/oneInch.test.d.ts +2 -0
  845. package/ts_build/test/integration/externalservices/oneInch.test.d.ts.map +1 -0
  846. package/ts_build/test/integration/externalservices/oneInch.test.js +182 -0
  847. package/ts_build/test/integration/externalservices/oneInch.test.js.map +1 -0
  848. package/ts_build/test/integration/externalservices/ramp.test.d.ts +2 -0
  849. package/ts_build/test/integration/externalservices/ramp.test.d.ts.map +1 -0
  850. package/ts_build/test/integration/externalservices/ramp.test.js +459 -0
  851. package/ts_build/test/integration/externalservices/ramp.test.js.map +1 -0
  852. package/ts_build/test/integration/externalservices/sardine.test.d.ts +2 -0
  853. package/ts_build/test/integration/externalservices/sardine.test.d.ts.map +1 -0
  854. package/ts_build/test/integration/externalservices/sardine.test.js +364 -0
  855. package/ts_build/test/integration/externalservices/sardine.test.js.map +1 -0
  856. package/ts_build/test/integration/externalservices/simplex.test.d.ts +2 -0
  857. package/ts_build/test/integration/externalservices/simplex.test.d.ts.map +1 -0
  858. package/ts_build/test/integration/externalservices/simplex.test.js +383 -0
  859. package/ts_build/test/integration/externalservices/simplex.test.js.map +1 -0
  860. package/ts_build/test/integration/externalservices/thorswap.test.d.ts +2 -0
  861. package/ts_build/test/integration/externalservices/thorswap.test.d.ts.map +1 -0
  862. package/ts_build/test/integration/externalservices/thorswap.test.js +316 -0
  863. package/ts_build/test/integration/externalservices/thorswap.test.js.map +1 -0
  864. package/ts_build/test/integration/externalservices/transak.test.d.ts +2 -0
  865. package/ts_build/test/integration/externalservices/transak.test.d.ts.map +1 -0
  866. package/ts_build/test/integration/externalservices/transak.test.js +409 -0
  867. package/ts_build/test/integration/externalservices/transak.test.js.map +1 -0
  868. package/ts_build/test/integration/externalservices/wyre.test.d.ts +2 -0
  869. package/ts_build/test/integration/externalservices/wyre.test.d.ts.map +1 -0
  870. package/ts_build/test/integration/externalservices/wyre.test.js +281 -0
  871. package/ts_build/test/integration/externalservices/wyre.test.js.map +1 -0
  872. package/ts_build/test/integration/fiatrateservice.test.d.ts +2 -0
  873. package/ts_build/test/integration/fiatrateservice.test.d.ts.map +1 -0
  874. package/ts_build/test/integration/fiatrateservice.test.js +838 -0
  875. package/ts_build/test/integration/fiatrateservice.test.js.map +1 -0
  876. package/ts_build/test/integration/helpers.d.ts +57 -0
  877. package/ts_build/test/integration/helpers.d.ts.map +1 -0
  878. package/ts_build/test/integration/helpers.js +633 -0
  879. package/ts_build/test/integration/helpers.js.map +1 -0
  880. package/ts_build/test/integration/history.test.d.ts +2 -0
  881. package/ts_build/test/integration/history.test.d.ts.map +1 -0
  882. package/ts_build/test/integration/history.test.js +1064 -0
  883. package/ts_build/test/integration/history.test.js.map +1 -0
  884. package/ts_build/test/integration/hugetx.d.ts +46 -0
  885. package/ts_build/test/integration/hugetx.d.ts.map +1 -0
  886. package/ts_build/test/integration/hugetx.js +6459 -0
  887. package/ts_build/test/integration/hugetx.js.map +1 -0
  888. package/ts_build/test/integration/pushNotifications.test.d.ts +2 -0
  889. package/ts_build/test/integration/pushNotifications.test.d.ts.map +1 -0
  890. package/ts_build/test/integration/pushNotifications.test.js +1379 -0
  891. package/ts_build/test/integration/pushNotifications.test.js.map +1 -0
  892. package/ts_build/test/integration/server.test.d.ts +2 -0
  893. package/ts_build/test/integration/server.test.d.ts.map +1 -0
  894. package/ts_build/test/integration/server.test.js +9980 -0
  895. package/ts_build/test/integration/server.test.js.map +1 -0
  896. package/ts_build/test/integration/tss.test.d.ts +2 -0
  897. package/ts_build/test/integration/tss.test.d.ts.map +1 -0
  898. package/ts_build/test/integration/tss.test.js +360 -0
  899. package/ts_build/test/integration/tss.test.js.map +1 -0
  900. package/ts_build/test/lock.test.d.ts +2 -0
  901. package/ts_build/test/lock.test.d.ts.map +1 -0
  902. package/ts_build/test/lock.test.js +226 -0
  903. package/ts_build/test/lock.test.js.map +1 -0
  904. package/ts_build/test/model/address.test.d.ts +2 -0
  905. package/ts_build/test/model/address.test.d.ts.map +1 -0
  906. package/ts_build/test/model/address.test.js +209 -0
  907. package/ts_build/test/model/address.test.js.map +1 -0
  908. package/ts_build/test/model/addressmanager.test.d.ts +2 -0
  909. package/ts_build/test/model/addressmanager.test.d.ts.map +1 -0
  910. package/ts_build/test/model/addressmanager.test.js +178 -0
  911. package/ts_build/test/model/addressmanager.test.js.map +1 -0
  912. package/ts_build/test/model/advertisement.test.d.ts +2 -0
  913. package/ts_build/test/model/advertisement.test.d.ts.map +1 -0
  914. package/ts_build/test/model/advertisement.test.js +61 -0
  915. package/ts_build/test/model/advertisement.test.js.map +1 -0
  916. package/ts_build/test/model/copayer.test.d.ts +2 -0
  917. package/ts_build/test/model/copayer.test.d.ts.map +1 -0
  918. package/ts_build/test/model/copayer.test.js +161 -0
  919. package/ts_build/test/model/copayer.test.js.map +1 -0
  920. package/ts_build/test/model/txproposal.test.d.ts +2 -0
  921. package/ts_build/test/model/txproposal.test.d.ts.map +1 -0
  922. package/ts_build/test/model/txproposal.test.js +198 -0
  923. package/ts_build/test/model/txproposal.test.js.map +1 -0
  924. package/ts_build/test/model/wallet.test.d.ts +2 -0
  925. package/ts_build/test/model/wallet.test.d.ts.map +1 -0
  926. package/ts_build/test/model/wallet.test.js +215 -0
  927. package/ts_build/test/model/wallet.test.js.map +1 -0
  928. package/ts_build/test/storage.test.d.ts +2 -0
  929. package/ts_build/test/storage.test.d.ts.map +1 -0
  930. package/ts_build/test/storage.test.js +433 -0
  931. package/ts_build/test/storage.test.js.map +1 -0
  932. package/ts_build/test/test-config.d.ts +8 -0
  933. package/ts_build/test/test-config.d.ts.map +1 -0
  934. package/ts_build/test/test-config.js +14 -0
  935. package/ts_build/test/test-config.js.map +1 -0
  936. package/ts_build/test/testdata.d.ts +91 -0
  937. package/ts_build/test/testdata.d.ts.map +1 -0
  938. package/ts_build/test/testdata.js +304 -0
  939. package/ts_build/test/testdata.js.map +1 -0
  940. package/ts_build/test/utils.test.d.ts +2 -0
  941. package/ts_build/test/utils.test.d.ts.map +1 -0
  942. package/ts_build/test/utils.test.js +450 -0
  943. package/ts_build/test/utils.test.js.map +1 -0
  944. package/ts_build/test/v8.test.d.ts +2 -0
  945. package/ts_build/test/v8.test.d.ts.map +1 -0
  946. package/ts_build/test/v8.test.js +341 -0
  947. package/ts_build/test/v8.test.js.map +1 -0
  948. package/tsconfig.json +43 -0
  949. package/tsconfig.prod.json +6 -0
@@ -0,0 +1,4115 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.UPGRADES = exports.WalletService = void 0;
40
+ exports.checkRequired = checkRequired;
41
+ const crypto_wallet_core_1 = require("@bitpay-labs/crypto-wallet-core");
42
+ const async = __importStar(require("async"));
43
+ const email_validator_1 = __importDefault(require("email-validator"));
44
+ const _ = __importStar(require("lodash"));
45
+ const moralis_1 = __importDefault(require("moralis"));
46
+ const preconditions_1 = require("preconditions");
47
+ const request_1 = __importDefault(require("request"));
48
+ require("source-map-support/register");
49
+ const uuid_1 = __importDefault(require("uuid"));
50
+ const package_json_1 = require("../../package.json");
51
+ const config_1 = __importDefault(require("../config"));
52
+ const deprecated_serverMessages_1 = require("../deprecated-serverMessages");
53
+ const banxa_1 = require("../externalservices/banxa");
54
+ const changelly_1 = require("../externalservices/changelly");
55
+ const coingecko_1 = require("../externalservices/coingecko");
56
+ const moonpay_1 = require("../externalservices/moonpay");
57
+ const oneInch_1 = require("../externalservices/oneInch");
58
+ const ramp_1 = require("../externalservices/ramp");
59
+ const sardine_1 = require("../externalservices/sardine");
60
+ const simplex_1 = require("../externalservices/simplex");
61
+ const thorswap_1 = require("../externalservices/thorswap");
62
+ const transak_1 = require("../externalservices/transak");
63
+ const wyre_1 = require("../externalservices/wyre");
64
+ const serverMessages_1 = require("../serverMessages");
65
+ const bchaddresstranslator_1 = require("./bchaddresstranslator");
66
+ const blockchainexplorer_1 = require("./blockchainexplorer");
67
+ const index_1 = require("./chain/index");
68
+ const common_1 = require("./common");
69
+ const clienterror_1 = require("./errors/clienterror");
70
+ const errordefinitions_1 = require("./errors/errordefinitions");
71
+ const fiatrateservice_1 = require("./fiatrateservice");
72
+ const lock_1 = require("./lock");
73
+ const logger_1 = __importDefault(require("./logger"));
74
+ const messagebroker_1 = require("./messagebroker");
75
+ const model_1 = require("./model");
76
+ const storage_1 = require("./storage");
77
+ let request = request_1.default;
78
+ const $ = (0, preconditions_1.singleton)();
79
+ const Bitcore_ = {
80
+ btc: crypto_wallet_core_1.BitcoreLib,
81
+ bch: crypto_wallet_core_1.BitcoreLibCash,
82
+ eth: crypto_wallet_core_1.BitcoreLib,
83
+ matic: crypto_wallet_core_1.BitcoreLib,
84
+ arb: crypto_wallet_core_1.BitcoreLib,
85
+ base: crypto_wallet_core_1.BitcoreLib,
86
+ op: crypto_wallet_core_1.BitcoreLib,
87
+ xrp: crypto_wallet_core_1.BitcoreLib,
88
+ doge: crypto_wallet_core_1.BitcoreLibDoge,
89
+ ltc: crypto_wallet_core_1.BitcoreLibLtc,
90
+ sol: crypto_wallet_core_1.BitcoreLib,
91
+ };
92
+ const { Utils, Constants, Defaults, Services, } = common_1.Common;
93
+ let initialized = false;
94
+ let doNotCheckV8 = false;
95
+ let isMoralisInitialized = false;
96
+ let lock;
97
+ let storage;
98
+ let blockchainExplorer;
99
+ let blockchainExplorerOpts;
100
+ let messageBroker;
101
+ let fiatRateService;
102
+ let serviceVersion;
103
+ function boolToNum(x) {
104
+ return x ? 1 : 0;
105
+ }
106
+ class WalletService {
107
+ lock;
108
+ storage;
109
+ blockchainExplorer;
110
+ blockchainExplorerOpts;
111
+ messageBroker;
112
+ fiatRateService;
113
+ notifyTicker;
114
+ userAgent;
115
+ walletId;
116
+ copayerId;
117
+ appName;
118
+ appVersion;
119
+ parsedClientVersion;
120
+ clientVersion;
121
+ copayerIsSupportStaff;
122
+ copayerIsMarketingStaff;
123
+ request;
124
+ externalServices;
125
+ constructor() {
126
+ if (!initialized) {
127
+ throw new Error('Server not initialized');
128
+ }
129
+ this.lock = lock;
130
+ this.storage = storage;
131
+ this.blockchainExplorer = blockchainExplorer;
132
+ this.blockchainExplorerOpts = blockchainExplorerOpts;
133
+ this.messageBroker = messageBroker;
134
+ this.fiatRateService = fiatRateService;
135
+ this.notifyTicker = 0;
136
+ this.request = request;
137
+ this.externalServices = {
138
+ banxa: new banxa_1.BanxaService(),
139
+ changelly: new changelly_1.ChangellyService(),
140
+ moonpay: new moonpay_1.MoonpayService(),
141
+ oneInch: new oneInch_1.OneInchService(this.storage),
142
+ ramp: new ramp_1.RampService(),
143
+ sardine: new sardine_1.SardineService(),
144
+ simplex: new simplex_1.SimplexService(),
145
+ thorswap: new thorswap_1.ThorswapService(),
146
+ transak: new transak_1.TransakService(),
147
+ wyre: new wyre_1.WyreService(),
148
+ coinGecko: new coingecko_1.CoinGeckoService(this.storage),
149
+ };
150
+ }
151
+ static getServiceVersion() {
152
+ if (!serviceVersion) {
153
+ serviceVersion = 'bws-' + package_json_1.version;
154
+ }
155
+ return serviceVersion;
156
+ }
157
+ static initialize(opts, cb) {
158
+ $.shouldBeFunction(cb, '');
159
+ opts = opts || {};
160
+ blockchainExplorer = opts.blockchainExplorer;
161
+ blockchainExplorerOpts = opts.blockchainExplorerOpts;
162
+ doNotCheckV8 = opts.doNotCheckV8;
163
+ if (opts.request) {
164
+ request = opts.request;
165
+ }
166
+ const initStorage = cb => {
167
+ if (opts.storage) {
168
+ storage = opts.storage;
169
+ return cb();
170
+ }
171
+ else {
172
+ const newStorage = new storage_1.Storage();
173
+ newStorage.connect(opts.storageOpts, err => {
174
+ if (err) {
175
+ return cb(err);
176
+ }
177
+ storage = newStorage;
178
+ return cb();
179
+ });
180
+ }
181
+ };
182
+ const initMessageBroker = cb => {
183
+ messageBroker = opts.messageBroker || new messagebroker_1.MessageBroker(opts.messageBrokerOpts);
184
+ if (messageBroker) {
185
+ messageBroker.onMessage(WalletService.handleIncomingNotifications);
186
+ }
187
+ return cb();
188
+ };
189
+ const initFiatRateService = cb => {
190
+ if (opts.fiatRateService) {
191
+ fiatRateService = opts.fiatRateService;
192
+ return cb();
193
+ }
194
+ else {
195
+ const newFiatRateService = new fiatrateservice_1.FiatRateService();
196
+ const opts2 = opts.fiatRateServiceOpts || {};
197
+ opts2.storage = storage;
198
+ newFiatRateService.init(opts2, err => {
199
+ if (err) {
200
+ return cb(err);
201
+ }
202
+ fiatRateService = newFiatRateService;
203
+ return cb();
204
+ });
205
+ }
206
+ };
207
+ const initMoralis = async (cb) => {
208
+ if (!config_1.default.moralis || !config_1.default.moralis.apiKey) {
209
+ logger_1.default.warn('Moralis missing credentials');
210
+ return cb();
211
+ }
212
+ if (!isMoralisInitialized) {
213
+ try {
214
+ logger_1.default.info('Initializing Moralis...');
215
+ const API_KEY = config_1.default.moralis.apiKey;
216
+ await moralis_1.default.start({
217
+ apiKey: API_KEY,
218
+ });
219
+ logger_1.default.info('Moralis initialized successfully!');
220
+ isMoralisInitialized = true;
221
+ return cb();
222
+ }
223
+ catch (err) {
224
+ logger_1.default.error('Error initializing Moralis: ', err);
225
+ isMoralisInitialized = false;
226
+ return cb();
227
+ }
228
+ }
229
+ else {
230
+ return cb();
231
+ }
232
+ };
233
+ async.series([
234
+ next => {
235
+ initStorage(next);
236
+ },
237
+ next => {
238
+ initMessageBroker(next);
239
+ },
240
+ next => {
241
+ initFiatRateService(next);
242
+ },
243
+ next => {
244
+ initMoralis(next);
245
+ }
246
+ ], err => {
247
+ lock = opts.lock || new lock_1.Lock(storage);
248
+ if (err) {
249
+ logger_1.default.error('Could not initialize: %o', err);
250
+ throw err;
251
+ }
252
+ initialized = true;
253
+ return cb();
254
+ });
255
+ }
256
+ static handleIncomingNotifications(notification, cb) {
257
+ cb = cb || function () { };
258
+ return cb();
259
+ }
260
+ static shutDown(cb) {
261
+ if (!initialized) {
262
+ return cb();
263
+ }
264
+ storage.disconnect(err => {
265
+ if (err) {
266
+ return cb(err);
267
+ }
268
+ initialized = false;
269
+ return cb();
270
+ });
271
+ }
272
+ static getInstance(opts) {
273
+ opts = opts || {};
274
+ const upgradeMessage = WalletService.upgradeNeeded(exports.UPGRADES.bwc_$lt_1_2, opts);
275
+ if (upgradeMessage) {
276
+ throw errordefinitions_1.Errors.UPGRADE_NEEDED.withMessageMaybe(upgradeMessage);
277
+ }
278
+ const server = new WalletService();
279
+ server._setClientVersion(opts.clientVersion);
280
+ server._setAppVersion(opts.userAgent);
281
+ server.userAgent = opts.userAgent;
282
+ return server;
283
+ }
284
+ static getInstanceWithAuth(opts, cb) {
285
+ const withSignature = cb => {
286
+ if (!checkRequired(opts, ['copayerId', 'message', 'signature'], cb)) {
287
+ return;
288
+ }
289
+ let server;
290
+ try {
291
+ server = WalletService.getInstance(opts);
292
+ }
293
+ catch (ex) {
294
+ return cb(ex);
295
+ }
296
+ server.storage.fetchCopayerLookup(opts.copayerId, (err, copayer) => {
297
+ if (err) {
298
+ return cb(err);
299
+ }
300
+ if (!copayer) {
301
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED.withMessage('Copayer not found'));
302
+ }
303
+ const isValid = !!server._getSigningKey(opts.message, opts.signature, copayer.requestPubKeys);
304
+ if (!isValid) {
305
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED.withMessage('Invalid signature'));
306
+ }
307
+ server.walletId = copayer.walletId;
308
+ if (copayer.isSupportStaff) {
309
+ server.walletId = opts.walletId || copayer.walletId;
310
+ server.copayerIsSupportStaff = true;
311
+ }
312
+ if (copayer.isMarketingStaff) {
313
+ server.copayerIsMarketingStaff = true;
314
+ }
315
+ server.copayerId = opts.copayerId;
316
+ return cb(null, server);
317
+ });
318
+ };
319
+ const withSession = cb => {
320
+ if (!checkRequired(opts, ['copayerId', 'session'], cb)) {
321
+ return;
322
+ }
323
+ let server;
324
+ try {
325
+ server = WalletService.getInstance(opts);
326
+ }
327
+ catch (ex) {
328
+ return cb(ex);
329
+ }
330
+ server.storage.getSession(opts.copayerId, (err, s) => {
331
+ if (err) {
332
+ return cb(err);
333
+ }
334
+ const isValid = s && s.id === opts.session && s.isValid();
335
+ if (!isValid) {
336
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED.withMessage('Session expired'));
337
+ }
338
+ server.storage.fetchCopayerLookup(opts.copayerId, (err, copayer) => {
339
+ if (err) {
340
+ return cb(err);
341
+ }
342
+ if (!copayer) {
343
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED.withMessage('Copayer not found'));
344
+ }
345
+ server.copayerId = opts.copayerId;
346
+ server.walletId = copayer.walletId;
347
+ return cb(null, server);
348
+ });
349
+ });
350
+ };
351
+ const authFn = opts.session ? withSession : withSignature;
352
+ return authFn(cb);
353
+ }
354
+ static getStorage() {
355
+ if (!initialized) {
356
+ throw new Error('Storage requested before server was initialized');
357
+ }
358
+ return storage;
359
+ }
360
+ _runLocked(cb, task, waitTime) {
361
+ $.checkState(this.walletId, 'Failed state: this.walletId undefined at <_runLocked()>');
362
+ this.lock.runLocked(this.walletId, { waitTime }, cb, task);
363
+ }
364
+ _cleanLogArgs(args) {
365
+ if (!args || args.length === 0) {
366
+ return [];
367
+ }
368
+ if (!Array.isArray(args)) {
369
+ args = [args];
370
+ }
371
+ for (let i = 0; i < args.length; i++) {
372
+ args[i] = args[i]?.response ? JSON.parse(JSON.stringify(args[i])) : args[i];
373
+ }
374
+ return args;
375
+ }
376
+ logi(message, ...args) {
377
+ args = this._cleanLogArgs(args);
378
+ if (typeof message === 'string' && args.length > 0 && !message.endsWith('%o')) {
379
+ for (let i = 0; i < args.length; i++) {
380
+ message += ' %o';
381
+ }
382
+ }
383
+ if (!this || !this.walletId) {
384
+ return logger_1.default.warn(message, ...args);
385
+ }
386
+ message = '<' + this.walletId + '>' + message;
387
+ return logger_1.default.info(message, ...args);
388
+ }
389
+ logw(message, ...args) {
390
+ args = this._cleanLogArgs(args);
391
+ if (typeof message === 'string' && args.length > 0 && !message.endsWith('%o')) {
392
+ for (let i = 0; i < args.length; i++) {
393
+ message += ' %o';
394
+ args[i] = args[i]?.stack || args[i]?.message || args[i];
395
+ }
396
+ }
397
+ if (!this || !this.walletId) {
398
+ return logger_1.default.warn(message, ...args);
399
+ }
400
+ message = '<' + this.walletId + '>' + message;
401
+ return logger_1.default.warn(message, ...args);
402
+ }
403
+ logd(message, ...args) {
404
+ args = this._cleanLogArgs(args);
405
+ if (typeof message === 'string' && args.length > 0 && !message.endsWith('%o')) {
406
+ for (let i = 0; i < args.length; i++) {
407
+ message += ' %o';
408
+ }
409
+ }
410
+ if (!this || !this.walletId) {
411
+ return logger_1.default.verbose(message, ...args);
412
+ }
413
+ message = '<' + this.walletId + '>' + message;
414
+ return logger_1.default.verbose(message, ...args);
415
+ }
416
+ login(opts, cb) {
417
+ let session;
418
+ async.series([
419
+ next => {
420
+ this.storage.getSession(this.copayerId, (err, s) => {
421
+ if (err) {
422
+ return next(err);
423
+ }
424
+ session = s;
425
+ next();
426
+ });
427
+ },
428
+ next => {
429
+ if (!session || !session.isValid()) {
430
+ session = model_1.Session.create({
431
+ copayerId: this.copayerId,
432
+ walletId: this.walletId
433
+ });
434
+ }
435
+ else {
436
+ session.touch();
437
+ }
438
+ next();
439
+ },
440
+ next => {
441
+ this.storage.storeSession(session, next);
442
+ }
443
+ ], err => {
444
+ if (err) {
445
+ return cb(err);
446
+ }
447
+ if (!session) {
448
+ return cb(new Error('Could not get current session for this copayer'));
449
+ }
450
+ return cb(null, session.id);
451
+ });
452
+ }
453
+ logout(_opts, _cb) {
454
+ }
455
+ async createWallet(opts, cb) {
456
+ let pubKey;
457
+ opts.coin = opts.coin || Defaults.COIN;
458
+ if (!opts.chain) {
459
+ opts.chain = opts.coin;
460
+ }
461
+ const upgradeMessage = this._upgradeNeeded([exports.UPGRADES.BCH_bwc_$lt_8_3_multisig, exports.UPGRADES.SOL_bwc_$lt_10_10_12], opts);
462
+ if (upgradeMessage) {
463
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED.withMessageMaybe(upgradeMessage));
464
+ }
465
+ if (!checkRequired(opts, ['name', 'm', 'n', 'pubKey'], cb)) {
466
+ return;
467
+ }
468
+ if (!opts.name) {
469
+ return cb(new clienterror_1.ClientError('Invalid wallet name'));
470
+ }
471
+ if (!model_1.Wallet.verifyCopayerLimits(opts.m, opts.n)) {
472
+ return cb(new clienterror_1.ClientError('Invalid combination of required copayers / total copayers'));
473
+ }
474
+ if (!Utils.checkValueInCollection(opts.chain, Constants.CHAINS)) {
475
+ return cb(new clienterror_1.ClientError('Invalid chain'));
476
+ }
477
+ opts.network = Utils.getNetworkName(opts.chain, opts.network) || 'livenet';
478
+ if (!Utils.checkValueInCollection(opts.network, Constants.NETWORKS[opts.chain])) {
479
+ return cb(new clienterror_1.ClientError('Invalid network'));
480
+ }
481
+ if (opts.network === 'regtest' && !config_1.default.allowRegtest) {
482
+ return cb(new clienterror_1.ClientError('Regtest is not allowed for this environment'));
483
+ }
484
+ try {
485
+ pubKey = new crypto_wallet_core_1.BitcoreLib.PublicKey.fromString(opts.pubKey);
486
+ }
487
+ catch {
488
+ return cb(new clienterror_1.ClientError('Invalid public key'));
489
+ }
490
+ if (opts.n > 1) {
491
+ const multisig = index_1.ChainService.supportsMultisig(opts.chain);
492
+ const thresholdsig = index_1.ChainService.supportsThresholdsig(opts.chain);
493
+ if (!multisig && !thresholdsig) {
494
+ return cb(new clienterror_1.ClientError('Multisig wallets are not supported for this chain'));
495
+ }
496
+ if (!multisig && !opts.tssKeyId) {
497
+ return cb(new clienterror_1.ClientError('TSS key session id is required for this chain'));
498
+ }
499
+ }
500
+ if (opts.tssKeyId) {
501
+ opts.tssVersion = opts.tssVersion || Defaults.TSS_KEYGEN_SCHEME_VERSION;
502
+ if (!(opts.tssVersion > 0 && opts.tssVersion <= Constants.TSS_KEYGEN_SCHEME_VERSION_MAX)) {
503
+ return cb(new clienterror_1.ClientError('Invalid TSS version'));
504
+ }
505
+ const keySession = await storage.fetchTssKeyGenSession({ id: opts.tssKeyId });
506
+ if (!keySession || !keySession.sharedPublicKey) {
507
+ return cb(new clienterror_1.ClientError('Invalid TSS key session id'));
508
+ }
509
+ opts.m = 1;
510
+ opts.n = 1;
511
+ }
512
+ const derivationStrategy = Constants.DERIVATION_STRATEGIES.BIP44;
513
+ let addressType = opts.n === 1 ? Constants.SCRIPT_TYPES.P2PKH : Constants.SCRIPT_TYPES.P2SH;
514
+ if (opts.useNativeSegwit && Utils.checkValueInCollection(opts.chain, Constants.NATIVE_SEGWIT_CHAINS)) {
515
+ switch (Number(opts.segwitVersion)) {
516
+ case 0:
517
+ default:
518
+ addressType = opts.n === 1 ? Constants.SCRIPT_TYPES.P2WPKH : Constants.SCRIPT_TYPES.P2WSH;
519
+ break;
520
+ case 1:
521
+ if (!Utils.checkValueInCollection(opts.chain, Constants.TAPROOT_CHAINS)) {
522
+ return cb(new clienterror_1.ClientError('Invalid chain for P2TR'));
523
+ }
524
+ addressType = Constants.SCRIPT_TYPES.P2TR;
525
+ break;
526
+ }
527
+ }
528
+ if (index_1.ChainService.isSingleAddress(opts.chain)) {
529
+ opts.singleAddress = true;
530
+ }
531
+ let newWallet;
532
+ async.series([
533
+ acb => {
534
+ if (!opts.id) {
535
+ return acb();
536
+ }
537
+ this.storage.fetchWallet(opts.id, (err, wallet) => {
538
+ if (wallet) {
539
+ return acb(errordefinitions_1.Errors.WALLET_ALREADY_EXISTS);
540
+ }
541
+ return acb(err);
542
+ });
543
+ },
544
+ acb => {
545
+ const wallet = model_1.Wallet.create({
546
+ id: opts.id,
547
+ name: opts.name,
548
+ m: opts.m,
549
+ n: opts.n,
550
+ coin: opts.coin,
551
+ chain: opts.chain,
552
+ network: opts.network,
553
+ pubKey: pubKey.toString(),
554
+ singleAddress: !!opts.singleAddress,
555
+ derivationStrategy,
556
+ addressType,
557
+ nativeCashAddr: opts.nativeCashAddr,
558
+ usePurpose48: opts.n > 1 && !opts.tssVersion && !!opts.usePurpose48,
559
+ hardwareSourcePublicKey: opts.hardwareSourcePublicKey,
560
+ clientDerivedPublicKey: opts.clientDerivedPublicKey,
561
+ tssVersion: opts.tssVersion,
562
+ tssKeyId: opts.tssKeyId
563
+ });
564
+ this.storage.storeWallet(wallet, err => {
565
+ this.logd('Wallet created', wallet.id, opts.network);
566
+ newWallet = wallet;
567
+ return acb(err);
568
+ });
569
+ }
570
+ ], err => {
571
+ return cb(err, newWallet ? newWallet.id : null);
572
+ });
573
+ }
574
+ getWallet(opts, cb) {
575
+ this.storage.fetchWallet(this.walletId, (err, wallet) => {
576
+ if (err)
577
+ return cb(err);
578
+ if (!wallet)
579
+ return cb(errordefinitions_1.Errors.WALLET_NOT_FOUND);
580
+ if (this._upgradeNeeded(exports.UPGRADES.SOL_bwc_$lt_10_10_12, wallet))
581
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED);
582
+ if (wallet.coin != 'bch' || wallet.nativeCashAddr)
583
+ return cb(null, wallet);
584
+ if (opts.doNotMigrate)
585
+ return cb(null, wallet);
586
+ if (!wallet.chain)
587
+ wallet.chain = Utils.getChain(wallet.coin);
588
+ logger_1.default.info(`Migrating wallet ${wallet.id} to cashAddr`);
589
+ this.storage.migrateToCashAddr(this.walletId, e => {
590
+ if (e)
591
+ return cb(e);
592
+ wallet.nativeCashAddr = true;
593
+ return this.storage.storeWallet(wallet, e => {
594
+ if (e)
595
+ return cb(e);
596
+ return cb(e, wallet);
597
+ });
598
+ });
599
+ });
600
+ }
601
+ getWalletFromIdentifier(opts, cb) {
602
+ if (!opts.identifier)
603
+ return cb();
604
+ const end = (err, ret) => {
605
+ if (opts.walletCheck && !err && ret) {
606
+ return this.syncWallet(ret, cb);
607
+ }
608
+ else {
609
+ return cb(err, ret);
610
+ }
611
+ };
612
+ let walletId;
613
+ async.parallel([
614
+ done => {
615
+ this.storage.fetchWallet(opts.identifier, (err, wallet) => {
616
+ if (wallet)
617
+ walletId = wallet.id;
618
+ return done(err);
619
+ });
620
+ },
621
+ done => {
622
+ this.storage.fetchAddressByChain(Defaults.CHAIN, opts.identifier, (err, address) => {
623
+ if (address)
624
+ walletId = address.walletId;
625
+ return done(err);
626
+ });
627
+ },
628
+ done => {
629
+ this.storage.fetchTxByHash(opts.identifier, (err, tx) => {
630
+ if (tx)
631
+ walletId = tx.walletId;
632
+ return done(err);
633
+ });
634
+ }
635
+ ], err => {
636
+ if (err)
637
+ return cb(err);
638
+ if (walletId) {
639
+ return this.storage.fetchWallet(walletId, end);
640
+ }
641
+ return cb();
642
+ });
643
+ }
644
+ getStatus(opts, cb) {
645
+ opts = opts || {};
646
+ const status = {};
647
+ async.parallel([
648
+ next => {
649
+ this.getWallet({}, (err, wallet) => {
650
+ if (err)
651
+ return next(err);
652
+ if (this._upgradeNeeded(exports.UPGRADES.SOL_bwc_$lt_10_10_12, wallet)) {
653
+ return next(errordefinitions_1.Errors.UPGRADE_NEEDED);
654
+ }
655
+ const walletExtendedKeys = ['publicKeyRing', 'pubKey', 'addressManager'];
656
+ const copayerExtendedKeys = ['xPubKey', 'requestPubKey', 'signature', 'addressManager', 'customData'];
657
+ wallet.copayers = (wallet.copayers || []).map(copayer => {
658
+ if (copayer.id == this.copayerId)
659
+ return copayer;
660
+ return _.omit(copayer, 'customData');
661
+ });
662
+ if (!opts.includeExtendedInfo) {
663
+ wallet = _.omit(wallet, walletExtendedKeys);
664
+ wallet.copayers = (wallet.copayers || []).map(copayer => {
665
+ return _.omit(copayer, copayerExtendedKeys);
666
+ });
667
+ }
668
+ status.wallet = wallet;
669
+ if (opts.includeServerMessages) {
670
+ status.serverMessages = (0, serverMessages_1.serverMessages)(wallet, this.appName, this.appVersion);
671
+ }
672
+ else {
673
+ status.serverMessage = (0, deprecated_serverMessages_1.serverMessages)(wallet, this.appName, this.appVersion);
674
+ }
675
+ next();
676
+ });
677
+ },
678
+ next => {
679
+ opts.wallet = status.wallet;
680
+ this.getBalance(opts, (err, balance) => {
681
+ if (opts.includeExtendedInfo) {
682
+ if (err && err.code != 'WALLET_NEED_SCAN') {
683
+ return next(err);
684
+ }
685
+ }
686
+ else if (err) {
687
+ return next(err);
688
+ }
689
+ status.balance = balance;
690
+ next();
691
+ });
692
+ },
693
+ next => {
694
+ this.getPendingTxs(opts, (err, pendingTxps) => {
695
+ if (err)
696
+ return next(err);
697
+ status.pendingTxps = pendingTxps;
698
+ next();
699
+ });
700
+ },
701
+ next => {
702
+ this.getPreferences({}, (err, preferences) => {
703
+ if (err)
704
+ return next(err);
705
+ status.preferences = preferences;
706
+ next();
707
+ });
708
+ }
709
+ ], err => {
710
+ if (err)
711
+ return cb(err);
712
+ return cb(null, status);
713
+ });
714
+ }
715
+ _verifySignature(text, signature, pubkey) {
716
+ return Utils.verifyMessage(text, signature, pubkey);
717
+ }
718
+ _verifyRequestPubKey(requestPubKey, signature, xPubKey) {
719
+ const pub = new crypto_wallet_core_1.BitcoreLib.HDPublicKey(xPubKey).deriveChild(Constants.PATHS.REQUEST_KEY_AUTH).publicKey;
720
+ return Utils.verifyMessage(requestPubKey, signature, pub.toString());
721
+ }
722
+ _getSigningKey(text, signature, pubKeys) {
723
+ return pubKeys.find(item => {
724
+ return this._verifySignature(text, signature, item.key);
725
+ });
726
+ }
727
+ _notify(type, data, opts, cb) {
728
+ if (typeof opts === 'function') {
729
+ cb = opts;
730
+ opts = {};
731
+ }
732
+ opts = opts || {};
733
+ cb = cb || function () { };
734
+ const walletId = this.walletId || data.walletId;
735
+ const copayerId = this.copayerId || data.copayerId;
736
+ $.checkState(walletId, 'Failed state: walletId undefined at <_notify()>');
737
+ const notification = model_1.Notification.create({
738
+ type,
739
+ data,
740
+ ticker: this.notifyTicker++,
741
+ creatorId: opts.isGlobal ? null : copayerId,
742
+ walletId
743
+ });
744
+ this.storage.storeNotification(walletId, notification, () => {
745
+ this.messageBroker.send(notification);
746
+ return cb();
747
+ });
748
+ }
749
+ _notifyTxProposalAction(type, txp, extraArgs, cb) {
750
+ if (typeof extraArgs === 'function') {
751
+ cb = extraArgs;
752
+ extraArgs = {};
753
+ }
754
+ const data = Object.assign({
755
+ txProposalId: txp.id,
756
+ creatorId: txp.creatorId,
757
+ amount: txp.getTotalAmount(),
758
+ message: txp.message,
759
+ tokenAddress: txp.tokenAddress,
760
+ multisigContractAddress: txp.multisigContractAddress
761
+ }, extraArgs);
762
+ this._notify(type, data, {}, cb);
763
+ }
764
+ _addCopayerToWallet(wallet, opts, cb) {
765
+ const copayer = model_1.Copayer.create({
766
+ coin: wallet.coin,
767
+ chain: wallet.chain,
768
+ name: opts.name,
769
+ copayerIndex: wallet.copayers.length,
770
+ xPubKey: opts.xPubKey,
771
+ hardwareSourcePublicKey: opts.hardwareSourcePublicKey,
772
+ clientDerivedPublicKey: opts.clientDerivedPublicKey,
773
+ requestPubKey: opts.requestPubKey,
774
+ signature: opts.copayerSignature,
775
+ customData: opts.customData,
776
+ derivationStrategy: wallet.derivationStrategy
777
+ });
778
+ this.storage.fetchCopayerLookup(copayer.id, (err, res) => {
779
+ if (err)
780
+ return cb(err);
781
+ if (res)
782
+ return cb(errordefinitions_1.Errors.COPAYER_REGISTERED);
783
+ if (opts.dryRun)
784
+ return cb(null, {
785
+ copayerId: null,
786
+ wallet
787
+ });
788
+ wallet.addCopayer(copayer);
789
+ this.storage.storeWalletAndUpdateCopayersLookup(wallet, err => {
790
+ if (err)
791
+ return cb(err);
792
+ async.series([
793
+ next => {
794
+ this._notify('NewCopayer', {
795
+ walletId: opts.walletId,
796
+ copayerId: copayer.id,
797
+ copayerName: copayer.name
798
+ }, {}, next);
799
+ },
800
+ next => {
801
+ if (wallet.isComplete() && wallet.isShared()) {
802
+ this._notify('WalletComplete', {
803
+ walletId: opts.walletId
804
+ }, {
805
+ isGlobal: true
806
+ }, next);
807
+ }
808
+ else {
809
+ next();
810
+ }
811
+ }
812
+ ], () => {
813
+ return cb(null, {
814
+ copayerId: copayer.id,
815
+ wallet
816
+ });
817
+ });
818
+ });
819
+ });
820
+ }
821
+ _addKeyToCopayer(wallet, copayer, opts, cb) {
822
+ wallet.addCopayerRequestKey(copayer.id, opts.requestPubKey, opts.signature, opts.restrictions, opts.name);
823
+ this.storage.storeWalletAndUpdateCopayersLookup(wallet, err => {
824
+ if (err)
825
+ return cb(err);
826
+ return cb(null, {
827
+ copayerId: copayer.id,
828
+ wallet
829
+ });
830
+ });
831
+ }
832
+ addAccess(opts, cb) {
833
+ if (!checkRequired(opts, ['copayerId', 'requestPubKey', 'signature'], cb))
834
+ return;
835
+ this.storage.fetchCopayerLookup(opts.copayerId, (err, copayer) => {
836
+ if (err)
837
+ return cb(err);
838
+ if (!copayer)
839
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED);
840
+ this.storage.fetchWallet(copayer.walletId, (err, wallet) => {
841
+ if (err)
842
+ return cb(err);
843
+ if (!wallet)
844
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED);
845
+ const xPubKey = wallet.copayers.find(c => c.id === opts.copayerId).xPubKey;
846
+ if (!this._verifyRequestPubKey(opts.requestPubKey, opts.signature, xPubKey)) {
847
+ return cb(errordefinitions_1.Errors.NOT_AUTHORIZED);
848
+ }
849
+ if (copayer.requestPubKeys.length > Defaults.MAX_KEYS)
850
+ return cb(errordefinitions_1.Errors.TOO_MANY_KEYS);
851
+ this._addKeyToCopayer(wallet, copayer, opts, cb);
852
+ });
853
+ });
854
+ }
855
+ _setClientVersion(version) {
856
+ delete this.parsedClientVersion;
857
+ this.clientVersion = version;
858
+ }
859
+ _setAppVersion(userAgent) {
860
+ const parsed = Utils.parseAppVersion(userAgent);
861
+ if (!parsed) {
862
+ this.appName = this.appVersion = null;
863
+ }
864
+ else {
865
+ this.appName = parsed.app;
866
+ this.appVersion = parsed;
867
+ }
868
+ }
869
+ _parseClientVersion() {
870
+ if (this.parsedClientVersion == null) {
871
+ this.parsedClientVersion = Utils.parseVersion(this.clientVersion);
872
+ }
873
+ return this.parsedClientVersion;
874
+ }
875
+ _clientSupportsPayProRefund() {
876
+ const version = this._parseClientVersion();
877
+ if (!version)
878
+ return false;
879
+ if (version.agent != 'bwc')
880
+ return true;
881
+ if (version.major < 1 || (version.major == 1 && version.minor < 2))
882
+ return false;
883
+ return true;
884
+ }
885
+ static _getCopayerHash(name, xPubKey, requestPubKey) {
886
+ return [name, xPubKey, requestPubKey].join('|');
887
+ }
888
+ joinWallet(opts, cb) {
889
+ if (!checkRequired(opts, ['walletId', 'name', 'requestPubKey', 'copayerSignature'], cb))
890
+ return;
891
+ if (!opts.name)
892
+ return cb(new clienterror_1.ClientError('Invalid copayer name'));
893
+ opts.coin = opts.coin || Defaults.COIN;
894
+ if (!opts.chain) {
895
+ opts.chain = opts.coin;
896
+ }
897
+ if (!Utils.checkValueInCollection(opts.chain, Constants.CHAINS))
898
+ return cb(new clienterror_1.ClientError('Invalid coin'));
899
+ let xPubKey;
900
+ if (!opts.hardwareSourcePublicKey && !opts.clientDerivedPublicKey) {
901
+ if (!checkRequired(opts, ['xPubKey'], cb))
902
+ return;
903
+ try {
904
+ xPubKey = Bitcore_[opts.chain].HDPublicKey(opts.xPubKey);
905
+ }
906
+ catch {
907
+ return cb(new clienterror_1.ClientError('Invalid extended public key'));
908
+ }
909
+ if (xPubKey.network == null) {
910
+ return cb(new clienterror_1.ClientError('Invalid extended public key'));
911
+ }
912
+ }
913
+ this.walletId = opts.walletId;
914
+ this._runLocked(cb, cb => {
915
+ this.storage.fetchWallet(opts.walletId, async (err, wallet) => {
916
+ if (err)
917
+ return cb(err);
918
+ if (!wallet)
919
+ return cb(errordefinitions_1.Errors.WALLET_NOT_FOUND);
920
+ if ((opts.hardwareSourcePublicKey || opts.clientDerivedPublicKey) && !opts.tssKeyId) {
921
+ this._addCopayerToWallet(wallet, opts, cb);
922
+ return;
923
+ }
924
+ if (this._upgradeNeeded(exports.UPGRADES.BCH_bwc_$lt_8_3_multisig, { chain: opts.chain, n: wallet.n })) {
925
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED.withMessage('BWC clients < 8.3 are no longer supported for multisig BCH wallets.'));
926
+ }
927
+ if (this._upgradeNeeded([exports.UPGRADES.bwc_$lt_8_4_multisig_purpose48, exports.UPGRADES.bwc_$lt_8_17_multisig_p2wsh], wallet)) {
928
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED.withMessage('Please upgrade your client to join this multisig wallet'));
929
+ }
930
+ if (this._upgradeNeeded(exports.UPGRADES.SOL_bwc_$lt_10_10_12, wallet)) {
931
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED);
932
+ }
933
+ if (opts.chain != wallet.chain) {
934
+ return cb(new clienterror_1.ClientError('The wallet you are trying to join was created for a different chain'));
935
+ }
936
+ if (!Utils.compareNetworks(wallet.network, xPubKey.network.name, wallet.chain)) {
937
+ return cb(new clienterror_1.ClientError('The wallet you are trying to join was created for a different network'));
938
+ }
939
+ if (wallet.derivationStrategy == Constants.DERIVATION_STRATEGIES.BIP45) {
940
+ return cb(new clienterror_1.ClientError('The wallet you are trying to join was created with an older version of the client app.'));
941
+ }
942
+ const hash = WalletService._getCopayerHash(opts.name, opts.xPubKey, opts.requestPubKey);
943
+ if (!this._verifySignature(hash, opts.copayerSignature, wallet.pubKey)) {
944
+ return cb(new clienterror_1.ClientError());
945
+ }
946
+ if (wallet.copayers?.find(c => c.xPubKey === opts.xPubKey))
947
+ return cb(errordefinitions_1.Errors.COPAYER_IN_WALLET);
948
+ if (wallet.tssKeyId) {
949
+ const keySession = await storage.fetchTssKeyGenSession({ id: wallet.tssKeyId });
950
+ const copayerId = model_1.Copayer.xPubToCopayerId(opts.chain, opts.xPubKey);
951
+ if (!keySession.participants.includes(copayerId)) {
952
+ return cb(errordefinitions_1.Errors.TSS_NON_PARTICIPANT);
953
+ }
954
+ return this._addCopayerToWallet(wallet, opts, cb);
955
+ }
956
+ if (wallet.copayers.length == wallet.n)
957
+ return cb(errordefinitions_1.Errors.WALLET_FULL);
958
+ this._addCopayerToWallet(wallet, opts, cb);
959
+ });
960
+ });
961
+ }
962
+ savePreferences(opts, cb) {
963
+ opts = opts || {};
964
+ const preferences = [
965
+ {
966
+ name: 'email',
967
+ isValid(value) {
968
+ return email_validator_1.default.validate(value);
969
+ }
970
+ },
971
+ {
972
+ name: 'language',
973
+ isValid(value) {
974
+ return typeof value === 'string' && value.length == 2;
975
+ }
976
+ },
977
+ {
978
+ name: 'unit',
979
+ isValid(value) {
980
+ return typeof value === 'string' && ['btc', 'bit'].includes(value.toLowerCase());
981
+ }
982
+ },
983
+ {
984
+ name: 'tokenAddresses',
985
+ isValid(value) {
986
+ return Array.isArray(value) && value.every(x => crypto_wallet_core_1.Validation.validateAddress('eth', 'mainnet', x));
987
+ }
988
+ },
989
+ {
990
+ name: 'multisigEthInfo',
991
+ isValid(value) {
992
+ return (Array.isArray(value) &&
993
+ value.every(x => crypto_wallet_core_1.Validation.validateAddress('eth', 'mainnet', x.multisigContractAddress)));
994
+ }
995
+ },
996
+ {
997
+ name: 'maticTokenAddresses',
998
+ isValid(value) {
999
+ return Array.isArray(value) && value.every(x => crypto_wallet_core_1.Validation.validateAddress('matic', 'mainnet', x));
1000
+ }
1001
+ },
1002
+ {
1003
+ name: 'multisigMaticInfo',
1004
+ isValid(value) {
1005
+ return (Array.isArray(value) &&
1006
+ value.every(x => crypto_wallet_core_1.Validation.validateAddress('matic', 'mainnet', x.multisigContractAddress)));
1007
+ }
1008
+ },
1009
+ {
1010
+ name: 'opTokenAddresses',
1011
+ isValid(value) {
1012
+ return Array.isArray(value) && value.every(x => crypto_wallet_core_1.Validation.validateAddress('op', 'mainnet', x));
1013
+ }
1014
+ },
1015
+ {
1016
+ name: 'baseTokenAddresses',
1017
+ isValid(value) {
1018
+ return Array.isArray(value) && value.every(x => crypto_wallet_core_1.Validation.validateAddress('base', 'mainnet', x));
1019
+ }
1020
+ },
1021
+ {
1022
+ name: 'arbTokenAddresses',
1023
+ isValid(value) {
1024
+ return Array.isArray(value) && value.every(x => crypto_wallet_core_1.Validation.validateAddress('arb', 'mainnet', x));
1025
+ }
1026
+ },
1027
+ {
1028
+ name: 'solTokenAddresses',
1029
+ isValid(value) {
1030
+ return Array.isArray(value) && value.every(x => crypto_wallet_core_1.Validation.validateAddress('sol', 'mainnet', x));
1031
+ }
1032
+ },
1033
+ ];
1034
+ opts = _.pick(opts, preferences.map(p => p.name));
1035
+ try {
1036
+ for (const preference of preferences) {
1037
+ const value = opts[preference.name];
1038
+ if (!value)
1039
+ continue;
1040
+ if (!preference.isValid(value)) {
1041
+ throw new Error('Invalid ' + preference.name);
1042
+ }
1043
+ }
1044
+ }
1045
+ catch (ex) {
1046
+ return cb(new clienterror_1.ClientError(ex));
1047
+ }
1048
+ this.getWallet({}, (err, wallet) => {
1049
+ if (err)
1050
+ return cb(err);
1051
+ if (!Constants.EVM_CHAINS[wallet.chain.toUpperCase()]) {
1052
+ opts.tokenAddresses = null;
1053
+ opts.multisigEthInfo = null;
1054
+ }
1055
+ if (wallet.coin != 'matic') {
1056
+ opts.maticTokenAddresses = null;
1057
+ opts.multisigMaticInfo = null;
1058
+ }
1059
+ this._runLocked(cb, cb => {
1060
+ this.storage.fetchPreferences(this.walletId, this.copayerId, (err, oldPref) => {
1061
+ if (err)
1062
+ return cb(err);
1063
+ const newPref = model_1.Preferences.create({
1064
+ walletId: this.walletId,
1065
+ copayerId: this.copayerId
1066
+ });
1067
+ const preferences = model_1.Preferences.fromObj(_.defaults(newPref, opts, oldPref));
1068
+ if (opts.tokenAddresses) {
1069
+ oldPref = oldPref || {};
1070
+ oldPref.tokenAddresses = oldPref.tokenAddresses || [];
1071
+ preferences.tokenAddresses = _.uniq(oldPref.tokenAddresses.concat(opts.tokenAddresses));
1072
+ }
1073
+ if (opts.multisigEthInfo) {
1074
+ oldPref = oldPref || {};
1075
+ oldPref.multisigEthInfo = oldPref.multisigEthInfo || [];
1076
+ preferences.multisigEthInfo = _.uniq(oldPref.multisigEthInfo.concat(opts.multisigEthInfo).reduce((x, y) => {
1077
+ let exists = false;
1078
+ for (let e of x) {
1079
+ if (e.multisigContractAddress === y.multisigContractAddress) {
1080
+ e.tokenAddresses = e.tokenAddresses || [];
1081
+ y.tokenAddresses = _.uniq(e.tokenAddresses.concat(y.tokenAddresses));
1082
+ e = Object.assign(e, y);
1083
+ exists = true;
1084
+ }
1085
+ }
1086
+ return exists ? x : [...x, y];
1087
+ }, []));
1088
+ }
1089
+ if (opts.maticTokenAddresses) {
1090
+ oldPref = oldPref || {};
1091
+ oldPref.maticTokenAddresses = oldPref.maticTokenAddresses || [];
1092
+ preferences.maticTokenAddresses = _.uniq(oldPref.maticTokenAddresses.concat(opts.maticTokenAddresses));
1093
+ }
1094
+ if (opts.opTokenAddresses) {
1095
+ oldPref = oldPref || {};
1096
+ oldPref.opTokenAddresses = oldPref.opTokenAddresses || [];
1097
+ preferences.opTokenAddresses = _.uniq(oldPref.opTokenAddresses.concat(opts.opTokenAddresses));
1098
+ }
1099
+ if (opts.baseTokenAddresses) {
1100
+ oldPref = oldPref || {};
1101
+ oldPref.baseTokenAddresses = oldPref.baseTokenAddresses || [];
1102
+ preferences.baseTokenAddresses = _.uniq(oldPref.baseTokenAddresses.concat(opts.baseTokenAddresses));
1103
+ }
1104
+ if (opts.arbTokenAddresses) {
1105
+ oldPref = oldPref || {};
1106
+ oldPref.arbTokenAddresses = oldPref.arbTokenAddresses || [];
1107
+ preferences.arbTokenAddresses = _.uniq(oldPref.arbTokenAddresses.concat(opts.arbTokenAddresses));
1108
+ }
1109
+ if (opts.solTokenAddresses) {
1110
+ oldPref = oldPref || {};
1111
+ oldPref.solTokenAddresses = oldPref.solTokenAddresses || [];
1112
+ preferences.solTokenAddresses = _.uniq(oldPref.solTokenAddresses.concat(opts.solTokenAddresses));
1113
+ }
1114
+ if (opts.multisigMaticInfo) {
1115
+ oldPref = oldPref || {};
1116
+ oldPref.multisigMaticInfo = oldPref.multisigMaticInfo || [];
1117
+ preferences.multisigMaticInfo = _.uniq(oldPref.multisigMaticInfo.concat(opts.multisigMaticInfo).reduce((x, y) => {
1118
+ let exists = false;
1119
+ for (let e of x) {
1120
+ if (e.multisigContractAddress === y.multisigContractAddress) {
1121
+ e.maticTokenAddresses = e.maticTokenAddresses || [];
1122
+ y.maticTokenAddresses = _.uniq(e.maticTokenAddresses.concat(y.maticTokenAddresses));
1123
+ e = Object.assign(e, y);
1124
+ exists = true;
1125
+ }
1126
+ }
1127
+ return exists ? x : [...x, y];
1128
+ }, []));
1129
+ }
1130
+ this.storage.storePreferences(preferences, err => {
1131
+ return cb(err);
1132
+ });
1133
+ });
1134
+ });
1135
+ });
1136
+ }
1137
+ getPreferences(opts, cb) {
1138
+ this.storage.fetchPreferences(this.walletId, this.copayerId, (err, preferences) => {
1139
+ if (err)
1140
+ return cb(err);
1141
+ return cb(null, preferences || {});
1142
+ });
1143
+ }
1144
+ _canCreateAddress(ignoreMaxGap, cb) {
1145
+ if (ignoreMaxGap)
1146
+ return cb(null, true);
1147
+ this.storage.fetchAddresses(this.walletId, (err, addresses) => {
1148
+ if (err)
1149
+ return cb(err);
1150
+ const latestAddresses = addresses.filter(x => !x.isChange).slice(-Defaults.MAX_MAIN_ADDRESS_GAP);
1151
+ if (latestAddresses.length < Defaults.MAX_MAIN_ADDRESS_GAP ||
1152
+ latestAddresses.some(a => a.hasActivity))
1153
+ return cb(null, true);
1154
+ const bc = this._getBlockchainExplorer(latestAddresses[0].coin, latestAddresses[0].network);
1155
+ if (!bc)
1156
+ return cb(new Error('Could not get blockchain explorer instance'));
1157
+ let activityFound = false;
1158
+ let i = latestAddresses.length;
1159
+ async.whilst(() => {
1160
+ return i > 0 && !activityFound;
1161
+ }, next => {
1162
+ bc.getAddressActivity(latestAddresses[--i].address, (err, res) => {
1163
+ if (err)
1164
+ return next(err);
1165
+ activityFound = !!res;
1166
+ return next();
1167
+ });
1168
+ }, err => {
1169
+ if (err)
1170
+ return cb(err);
1171
+ if (!activityFound)
1172
+ return cb(null, false);
1173
+ const address = latestAddresses[i];
1174
+ address.hasActivity = true;
1175
+ this.storage.storeAddress(address, err => {
1176
+ return cb(err, true);
1177
+ });
1178
+ });
1179
+ });
1180
+ }
1181
+ _store(wallet, address, cb, checkSync = false, forceSync = false) {
1182
+ const stoAddress = _.clone(address);
1183
+ index_1.ChainService.addressToStorageTransform(wallet.chain, wallet.network, stoAddress);
1184
+ this.storage.storeAddressAndWallet(wallet, stoAddress, (err, isDuplicate) => {
1185
+ if (err)
1186
+ return cb(err);
1187
+ this.syncWallet(wallet, err2 => {
1188
+ if (err2) {
1189
+ this.logw('Error syncing v8 addresses:', err2);
1190
+ }
1191
+ return cb(null, isDuplicate);
1192
+ }, !checkSync, null, forceSync);
1193
+ });
1194
+ }
1195
+ createAddress(opts, cb) {
1196
+ opts = opts || {};
1197
+ const createNewAddress = (wallet, cb) => {
1198
+ let address;
1199
+ try {
1200
+ address = wallet.createAddress(!!opts.isChange);
1201
+ }
1202
+ catch (e) {
1203
+ this.logw('Error creating address:', e);
1204
+ return cb('Bad xPub');
1205
+ }
1206
+ this._store(wallet, address, (err, duplicate) => {
1207
+ if (err)
1208
+ return cb(err);
1209
+ if (duplicate)
1210
+ return cb(null, address);
1211
+ if (wallet.chain == 'bch' && opts.noCashAddr) {
1212
+ address = _.cloneDeep(address);
1213
+ address.address = bchaddresstranslator_1.BCHAddressTranslator.translate(address.address, 'copay');
1214
+ }
1215
+ this._notify('NewAddress', {
1216
+ address: address.address
1217
+ }, () => {
1218
+ return cb(null, address);
1219
+ });
1220
+ }, true);
1221
+ };
1222
+ const getFirstAddress = (wallet, cb) => {
1223
+ this.storage.fetchAddresses(this.walletId, (err, addresses) => {
1224
+ if (err)
1225
+ return cb(err);
1226
+ if (addresses?.length) {
1227
+ const x = addresses[0];
1228
+ index_1.ChainService.addressFromStorageTransform(wallet.chain, wallet.network, x);
1229
+ return cb(null, x);
1230
+ }
1231
+ return createNewAddress(wallet, cb);
1232
+ });
1233
+ };
1234
+ this.getWallet({ doNotMigrate: opts.doNotMigrate }, (err, wallet) => {
1235
+ if (err)
1236
+ return cb(err);
1237
+ if (index_1.ChainService.isSingleAddress(wallet.chain)) {
1238
+ opts.ignoreMaxGap = true;
1239
+ opts.singleAddress = true;
1240
+ }
1241
+ this._canCreateAddress(opts.ignoreMaxGap || opts.singleAddress || wallet.singleAddress, (err, canCreate) => {
1242
+ if (err)
1243
+ return cb(err);
1244
+ if (!canCreate)
1245
+ return cb(errordefinitions_1.Errors.MAIN_ADDRESS_GAP_REACHED);
1246
+ this._runLocked(cb, cb => {
1247
+ this.getWallet({ doNotMigrate: opts.doNotMigrate }, (err, wallet) => {
1248
+ if (err)
1249
+ return cb(err);
1250
+ if (!wallet.isComplete())
1251
+ return cb(errordefinitions_1.Errors.WALLET_NOT_COMPLETE);
1252
+ if (wallet.scanStatus == 'error')
1253
+ return cb(errordefinitions_1.Errors.WALLET_NEED_SCAN);
1254
+ const createFn = opts.singleAddress || wallet.singleAddress ? getFirstAddress : createNewAddress;
1255
+ return createFn(wallet, (err, address) => {
1256
+ if (err) {
1257
+ return cb(err);
1258
+ }
1259
+ return cb(err, address);
1260
+ });
1261
+ });
1262
+ }, 10 * 1000);
1263
+ });
1264
+ });
1265
+ }
1266
+ getAddresses(opts, cb) {
1267
+ opts = opts || {};
1268
+ this.storage.fetchAddresses(this.walletId, (err, addresses) => {
1269
+ if (err)
1270
+ return cb(err);
1271
+ if (opts.noChange) {
1272
+ addresses = addresses.filter(a => !a.isChange);
1273
+ }
1274
+ if (opts.addresses) {
1275
+ addresses = addresses.filter(a => opts.addresses.includes(a.address));
1276
+ }
1277
+ if (opts.reverse)
1278
+ addresses.reverse();
1279
+ if (opts.skip > 0)
1280
+ addresses = addresses.slice(opts.skip);
1281
+ if (opts.limit > 0)
1282
+ addresses = addresses.slice(0, opts.limit);
1283
+ this.getWallet({}, (err, wallet) => {
1284
+ if (err)
1285
+ return cb(err);
1286
+ for (const x of addresses) {
1287
+ index_1.ChainService.addressFromStorageTransform(wallet.chain, wallet.network, x);
1288
+ }
1289
+ return cb(null, addresses);
1290
+ });
1291
+ });
1292
+ }
1293
+ verifyMessageSignature(opts, cb) {
1294
+ if (!checkRequired(opts, ['message', 'signature'], cb))
1295
+ return;
1296
+ this.getWallet({}, (err, wallet) => {
1297
+ if (err)
1298
+ return cb(err);
1299
+ const copayer = wallet.getCopayer(this.copayerId);
1300
+ const isValid = !!this._getSigningKey(opts.message, opts.signature, copayer.requestPubKeys);
1301
+ return cb(null, isValid);
1302
+ });
1303
+ }
1304
+ _getBlockchainExplorer(chain, network) {
1305
+ let opts = {};
1306
+ let provider;
1307
+ chain = chain.toLowerCase();
1308
+ if (this.blockchainExplorer)
1309
+ return this.blockchainExplorer;
1310
+ if (this.blockchainExplorerOpts) {
1311
+ if (this.blockchainExplorerOpts[chain] && this.blockchainExplorerOpts[chain][network]) {
1312
+ opts = this.blockchainExplorerOpts[chain][network];
1313
+ provider = opts.provider;
1314
+ }
1315
+ else if (this.blockchainExplorerOpts[network]) {
1316
+ opts = this.blockchainExplorerOpts[network];
1317
+ }
1318
+ }
1319
+ opts.provider = provider;
1320
+ opts.chain = chain;
1321
+ opts.network = Utils.getNetworkName(chain, network);
1322
+ opts.userAgent = WalletService.getServiceVersion();
1323
+ let bc;
1324
+ try {
1325
+ bc = (0, blockchainexplorer_1.BlockChainExplorer)(opts);
1326
+ }
1327
+ catch (ex) {
1328
+ this.logw('Could not instantiate blockchain explorer:', ex);
1329
+ }
1330
+ return bc;
1331
+ }
1332
+ getUtxosForCurrentWallet(opts, cb) {
1333
+ opts = opts || {};
1334
+ const utxoKey = utxo => utxo.txid + '|' + utxo.vout;
1335
+ let allAddresses, allUtxos, utxoIndex, bc, wallet, blockchainHeight;
1336
+ async.series([
1337
+ next => {
1338
+ this.getWallet({}, (err, w) => {
1339
+ if (err)
1340
+ return next(err);
1341
+ wallet = w;
1342
+ if (wallet.scanStatus == 'error')
1343
+ return cb(errordefinitions_1.Errors.WALLET_NEED_SCAN);
1344
+ bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
1345
+ if (!bc)
1346
+ return cb(new Error('Could not get blockchain explorer instance'));
1347
+ return next();
1348
+ });
1349
+ },
1350
+ next => {
1351
+ if (Array.isArray(opts.addresses)) {
1352
+ allAddresses = opts.addresses;
1353
+ return next();
1354
+ }
1355
+ this.storage.fetchAddresses(this.walletId, (err, addresses) => {
1356
+ for (const x of addresses) {
1357
+ index_1.ChainService.addressFromStorageTransform(wallet.chain, wallet.network, x);
1358
+ }
1359
+ allAddresses = addresses;
1360
+ if (allAddresses.length == 0)
1361
+ return cb(null, []);
1362
+ return next();
1363
+ });
1364
+ },
1365
+ next => {
1366
+ return next();
1367
+ },
1368
+ next => {
1369
+ if (!wallet.isComplete())
1370
+ return next();
1371
+ this._getBlockchainHeight(wallet.chain, wallet.network, (err, height, _hash) => {
1372
+ if (err)
1373
+ return next(err);
1374
+ blockchainHeight = height;
1375
+ next();
1376
+ });
1377
+ },
1378
+ next => {
1379
+ if (!wallet.isComplete())
1380
+ return next();
1381
+ const dustThreshold = Bitcore_[wallet.chain].Transaction.DUST_AMOUNT;
1382
+ const isEscrowPayment = wallet.isZceCompatible() && opts.instantAcceptanceEscrow ? true : false;
1383
+ const replaceTxByFee = opts.replaceTxByFee ? true : false;
1384
+ bc.getUtxos(wallet, blockchainHeight, (err, utxos) => {
1385
+ if (err)
1386
+ return next(err);
1387
+ if (utxos.length == 0)
1388
+ return cb(null, []);
1389
+ let unusableAddresses = [];
1390
+ if (isEscrowPayment) {
1391
+ const unusableUtxos = utxos.filter(utxo => utxo.spent || utxo.address.startsWith('p'));
1392
+ unusableAddresses = unusableUtxos.map(utxo => utxo.address);
1393
+ }
1394
+ allUtxos = utxos.filter(x => x.satoshis >= dustThreshold && !unusableAddresses.includes(x.address));
1395
+ return next();
1396
+ }, { includeSpent: isEscrowPayment || replaceTxByFee });
1397
+ },
1398
+ next => {
1399
+ if (!wallet.isComplete() || !wallet.isZceCompatible())
1400
+ return next();
1401
+ const bchRollingBlockCheckpointNumber = 10;
1402
+ const bchReorgSafeBlockHeight = blockchainHeight - bchRollingBlockCheckpointNumber - 1;
1403
+ let lockedAddresses = [];
1404
+ bc.getTransactions(wallet, bchReorgSafeBlockHeight, (err, txs) => {
1405
+ if (err)
1406
+ return next(err);
1407
+ const unconfirmedZceTxs = txs.filter(tx => tx.category === 'move' && tx.address.startsWith('p'));
1408
+ async.each(unconfirmedZceTxs, (tx, next) => {
1409
+ this.getCoinsForTx({ txId: tx.txid }, (err, coins) => {
1410
+ if (err)
1411
+ return next(err);
1412
+ const inputAddresses = coins.inputs.map(input => input.address);
1413
+ lockedAddresses = [...lockedAddresses, ...inputAddresses];
1414
+ return next();
1415
+ });
1416
+ }, err => {
1417
+ if (err)
1418
+ return next(err);
1419
+ allUtxos = allUtxos.map(utxo => {
1420
+ if (lockedAddresses.includes(utxo.address)) {
1421
+ utxo.locked = true;
1422
+ }
1423
+ return utxo;
1424
+ });
1425
+ return next();
1426
+ });
1427
+ });
1428
+ },
1429
+ next => {
1430
+ utxoIndex = _.keyBy(allUtxos, utxoKey);
1431
+ this.getPendingTxs({}, (err, txps) => {
1432
+ if (err)
1433
+ return next(err);
1434
+ const lockedInputs = txps.flatMap(t => t.inputs).map(utxoKey);
1435
+ for (const input of lockedInputs) {
1436
+ if (utxoIndex[input]) {
1437
+ utxoIndex[input].locked = true;
1438
+ }
1439
+ }
1440
+ logger_1.default.debug(`Got ${lockedInputs.length} locked utxos`);
1441
+ return next();
1442
+ });
1443
+ },
1444
+ next => {
1445
+ const now = Math.floor(Date.now() / 1000);
1446
+ this.storage.fetchBroadcastedTxs(this.walletId, {
1447
+ minTs: now - 24 * 3600,
1448
+ limit: 100
1449
+ }, (err, txs) => {
1450
+ if (err)
1451
+ return next(err);
1452
+ const spentInputs = txs.flatMap(t => t.inputs).map(utxoKey);
1453
+ const txIdArray = opts.inputs?.map(i => i.txid) || [];
1454
+ for (const input of spentInputs) {
1455
+ if (utxoIndex[input]) {
1456
+ utxoIndex[input].spent = true;
1457
+ }
1458
+ }
1459
+ allUtxos = allUtxos.filter(utxo => {
1460
+ return !((!opts.replaceTxByFee && utxo.spent) ||
1461
+ (utxo.spent && opts.replaceTxByFee && !txIdArray.includes(utxo.txid)));
1462
+ });
1463
+ logger_1.default.debug(`Got ${allUtxos.length} usable UTXOs`);
1464
+ return next();
1465
+ });
1466
+ },
1467
+ next => {
1468
+ const addressToPath = _.keyBy(allAddresses, 'address');
1469
+ for (const utxo of allUtxos) {
1470
+ if (!addressToPath[utxo.address]) {
1471
+ if (!opts.addresses)
1472
+ this.logw('Ignored UTXO!: ' + utxo.address);
1473
+ continue;
1474
+ }
1475
+ utxo.path = addressToPath[utxo.address].path;
1476
+ utxo.publicKeys = addressToPath[utxo.address].publicKeys;
1477
+ }
1478
+ return next();
1479
+ }
1480
+ ], (err) => {
1481
+ if (err && err.statusCode == 404) {
1482
+ return this.registerWalletV8(wallet, cb);
1483
+ }
1484
+ return cb(err, allUtxos);
1485
+ });
1486
+ }
1487
+ getUtxos(opts, cb) {
1488
+ opts = opts || {};
1489
+ if (opts.coin) {
1490
+ return cb(new clienterror_1.ClientError('coins option no longer supported'));
1491
+ }
1492
+ if (opts.addresses) {
1493
+ if (opts.addresses.length > 1)
1494
+ return cb(new clienterror_1.ClientError('Addresses option only support 1 address'));
1495
+ this.getWallet({}, (err, wallet) => {
1496
+ if (err)
1497
+ return cb(err);
1498
+ console.log('wallet:', wallet.chain, wallet.network);
1499
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
1500
+ if (!bc) {
1501
+ return cb(new Error('Could not get blockchain explorer instance'));
1502
+ }
1503
+ const address = opts.addresses[0];
1504
+ const A = Bitcore_[wallet.chain].Address;
1505
+ let addrObj = {};
1506
+ try {
1507
+ addrObj = new A(address);
1508
+ }
1509
+ catch {
1510
+ return cb(null, []);
1511
+ }
1512
+ if (!Utils.compareNetworks(addrObj.network.name.toLowerCase(), wallet.network.toLowerCase(), wallet.chain)) {
1513
+ return cb(null, []);
1514
+ }
1515
+ this._getBlockchainHeight(wallet.chain, wallet.network, (err, height, _hash) => {
1516
+ if (err)
1517
+ return cb(err);
1518
+ bc.getAddressUtxos(address, height, (err, utxos) => {
1519
+ if (err)
1520
+ return cb(err);
1521
+ return cb(null, utxos);
1522
+ });
1523
+ });
1524
+ });
1525
+ }
1526
+ else {
1527
+ this.getUtxosForCurrentWallet({}, cb);
1528
+ }
1529
+ }
1530
+ getCoinsForTx(opts, cb) {
1531
+ this.getWallet({}, (err, wallet) => {
1532
+ if (!index_1.ChainService.isUTXOChain(wallet.chain)) {
1533
+ return cb(null, {
1534
+ inputs: [],
1535
+ outputs: []
1536
+ });
1537
+ }
1538
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
1539
+ if (!bc) {
1540
+ return cb(new Error('Could not get blockchain explorer instance'));
1541
+ }
1542
+ bc.getCoinsForTx(opts.txId, (err, coins) => {
1543
+ if (err)
1544
+ return cb(err);
1545
+ return cb(null, coins);
1546
+ });
1547
+ });
1548
+ }
1549
+ getBalance(opts, cb) {
1550
+ opts = opts || {};
1551
+ if (opts.coin) {
1552
+ return cb(new clienterror_1.ClientError('coin is not longer supported in getBalance'));
1553
+ }
1554
+ let wallet = opts.wallet;
1555
+ const setWallet = cb1 => {
1556
+ if (wallet)
1557
+ return cb1();
1558
+ this.getWallet({}, (err, ret) => {
1559
+ if (err)
1560
+ return cb(err);
1561
+ wallet = ret;
1562
+ return cb1(null, wallet);
1563
+ });
1564
+ };
1565
+ setWallet(() => {
1566
+ if (!wallet.isComplete()) {
1567
+ const emptyBalance = {
1568
+ totalAmount: 0,
1569
+ lockedAmount: 0,
1570
+ totalConfirmedAmount: 0,
1571
+ lockedConfirmedAmount: 0,
1572
+ availableAmount: 0,
1573
+ availableConfirmedAmount: 0
1574
+ };
1575
+ return cb(null, emptyBalance);
1576
+ }
1577
+ this.syncWallet(wallet, err => {
1578
+ if (err)
1579
+ return cb(err);
1580
+ return index_1.ChainService.getWalletBalance(this, wallet, opts, cb);
1581
+ });
1582
+ });
1583
+ }
1584
+ getSendMaxInfo(opts, cb) {
1585
+ opts = opts || {};
1586
+ this.getWallet({}, (err, wallet) => {
1587
+ if (err)
1588
+ return cb(err);
1589
+ const feeArgs = boolToNum(!!opts.feeLevel) + boolToNum(_.isNumber(opts.feePerKb));
1590
+ if (feeArgs > 1)
1591
+ return cb(new clienterror_1.ClientError('Only one of feeLevel/feePerKb can be specified'));
1592
+ if (feeArgs == 0) {
1593
+ opts.feeLevel = 'normal';
1594
+ }
1595
+ const feeLevels = Defaults.FEE_LEVELS[wallet.chain];
1596
+ if (opts.feeLevel) {
1597
+ if (!feeLevels.some(lvl => lvl.name === opts.feeLevel))
1598
+ return cb(new clienterror_1.ClientError('Invalid fee level. Valid values are ' + feeLevels.map(lvl => lvl.name).join(', ')));
1599
+ }
1600
+ if (Utils.isNumber(opts.feePerKb)) {
1601
+ if (opts.feePerKb < Defaults.MIN_FEE_PER_KB || opts.feePerKb > Defaults.MAX_FEE_PER_KB[wallet.chain])
1602
+ return cb(new clienterror_1.ClientError('Invalid fee per KB'));
1603
+ }
1604
+ return index_1.ChainService.getWalletSendMaxInfo(this, wallet, opts, cb);
1605
+ });
1606
+ }
1607
+ _sampleFeeLevels(chain, network, points, cb) {
1608
+ const bc = this._getBlockchainExplorer(chain, network);
1609
+ if (!bc)
1610
+ return cb(new Error('Could not get blockchain explorer instance'));
1611
+ bc.estimateFee(points, (err, result) => {
1612
+ if (err) {
1613
+ this.logw('Error estimating fee:', err);
1614
+ return cb(err);
1615
+ }
1616
+ const failed = [];
1617
+ const levels = _.fromPairs(points.map(p => {
1618
+ const feePerKb = Utils.isObject(result) && result[p] && Utils.isNumber(result[p]) ? +result[p] : -1;
1619
+ if (feePerKb < 0)
1620
+ failed.push(p);
1621
+ return index_1.ChainService.convertFeePerKb(chain, p, feePerKb);
1622
+ }));
1623
+ if (failed.length) {
1624
+ const logger = network == 'livenet' ? this.logw : this.logi;
1625
+ logger.call(this, 'Could not compute fee estimation in ' + network + ': ' + failed.join(', ') + ' blocks.');
1626
+ }
1627
+ return cb(null, levels, failed.length);
1628
+ });
1629
+ }
1630
+ estimateFee(opts) {
1631
+ opts = opts || {};
1632
+ return new Promise((resolve, reject) => {
1633
+ const bc = this._getBlockchainExplorer(opts.chain, opts.network);
1634
+ if (!bc)
1635
+ return reject(new Error('Could not get blockchain explorer instance'));
1636
+ bc.estimateFeeV2(opts, (err, result) => {
1637
+ if (err) {
1638
+ this.logw('Error estimating fee:', err);
1639
+ return reject(err);
1640
+ }
1641
+ return resolve(result);
1642
+ });
1643
+ });
1644
+ }
1645
+ estimatePriorityFee(opts) {
1646
+ opts = opts || {};
1647
+ return new Promise((resolve, reject) => {
1648
+ const bc = this._getBlockchainExplorer(opts.chain, opts.network);
1649
+ if (!bc)
1650
+ return reject(new Error('Could not get blockchain explorer instance'));
1651
+ bc.estimatePriorityFee(opts, (err, result) => {
1652
+ if (err) {
1653
+ this.logw('Error estimating priority fee:', err);
1654
+ return reject(err);
1655
+ }
1656
+ return resolve(result);
1657
+ });
1658
+ });
1659
+ }
1660
+ getFeeLevels(opts, cb) {
1661
+ opts = opts || {};
1662
+ opts.chain = opts.chain || Defaults.CHAIN;
1663
+ if (!Utils.checkValueInCollection(opts.chain, Constants.CHAINS))
1664
+ return cb(new clienterror_1.ClientError('Invalid chain'));
1665
+ opts.network = Utils.getNetworkName(opts.chain, opts.network) || 'livenet';
1666
+ if (!Utils.checkValueInCollection(opts.network, Constants.NETWORKS[opts.chain]))
1667
+ return cb(new clienterror_1.ClientError('Invalid network'));
1668
+ const cacheKey = 'feeLevel:' + opts.chain + ':' + opts.network;
1669
+ this.storage.checkAndUseGlobalCache(cacheKey, Defaults.FEE_LEVEL_CACHE_DURATION, (err, values, oldvalues) => {
1670
+ if (err)
1671
+ return cb(err);
1672
+ if (values)
1673
+ return cb(null, values, true);
1674
+ const feeLevels = Defaults.FEE_LEVELS[opts.chain];
1675
+ const samplePoints = () => {
1676
+ const definedPoints = _.uniq(feeLevels.map(lvl => lvl.nbBlocks));
1677
+ return _.uniq(_.flatten(definedPoints.map((p) => {
1678
+ return _.range(p, p + Defaults.FEE_LEVELS_FALLBACK + 1);
1679
+ })));
1680
+ };
1681
+ const getFeeLevel = (feeSamples, level, n, fallback) => {
1682
+ let result;
1683
+ if (feeSamples[n] >= 0) {
1684
+ result = {
1685
+ nbBlocks: n,
1686
+ feePerKb: feeSamples[n]
1687
+ };
1688
+ }
1689
+ else {
1690
+ if (fallback > 0) {
1691
+ result = getFeeLevel(feeSamples, level, n + 1, fallback - 1);
1692
+ }
1693
+ else {
1694
+ result = {
1695
+ feePerKb: level.defaultValue,
1696
+ nbBlocks: null
1697
+ };
1698
+ }
1699
+ }
1700
+ return result;
1701
+ };
1702
+ this._sampleFeeLevels(opts.chain, opts.network, samplePoints(), (err, feeSamples, failed) => {
1703
+ if (err) {
1704
+ if (oldvalues) {
1705
+ this.logw('## There was an error estimating fees. Using old cached values. Error:', err);
1706
+ return cb(null, oldvalues, true);
1707
+ }
1708
+ }
1709
+ const values = feeLevels.map(level => {
1710
+ const result = {
1711
+ level: level.name
1712
+ };
1713
+ if (err) {
1714
+ result.feePerKb = level.defaultValue;
1715
+ result.nbBlocks = null;
1716
+ }
1717
+ else {
1718
+ const feeLevel = getFeeLevel(feeSamples, level, level.nbBlocks, Defaults.FEE_LEVELS_FALLBACK);
1719
+ result.feePerKb = +(feeLevel.feePerKb * (level.multiplier || 1)).toFixed(0);
1720
+ result.nbBlocks = feeLevel.nbBlocks;
1721
+ }
1722
+ return result;
1723
+ });
1724
+ for (let i = 1; i < values.length; i++) {
1725
+ values[i].feePerKb = Math.min(values[i].feePerKb, values[i - 1].feePerKb);
1726
+ }
1727
+ if (failed > 0) {
1728
+ this.logw('Not caching default values. Failed: ' + failed);
1729
+ return cb(null, values);
1730
+ }
1731
+ this.storage.storeGlobalCache(cacheKey, values, err => {
1732
+ if (err) {
1733
+ this.logw('Could not store fee level cache:', err);
1734
+ }
1735
+ return cb(null, values);
1736
+ });
1737
+ });
1738
+ });
1739
+ }
1740
+ _canCreateTx(cb) {
1741
+ this.storage.fetchLastTxs(this.walletId, this.copayerId, 5 + Defaults.BACKOFF_OFFSET, (err, txs) => {
1742
+ if (err)
1743
+ return cb(err);
1744
+ if (!txs.length)
1745
+ return cb(null, true);
1746
+ const lastRejections = _.takeWhile(txs, {
1747
+ status: 'rejected'
1748
+ });
1749
+ const exceededRejections = lastRejections.length - Defaults.BACKOFF_OFFSET;
1750
+ if (exceededRejections <= 0)
1751
+ return cb(null, true);
1752
+ const lastTxTs = txs[0].createdOn;
1753
+ const now = Math.floor(Date.now() / 1000);
1754
+ const timeSinceLastRejection = now - lastTxTs;
1755
+ const backoffTime = Defaults.BACKOFF_TIME;
1756
+ if (timeSinceLastRejection <= backoffTime)
1757
+ this.logd('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime);
1758
+ return cb(null, timeSinceLastRejection > backoffTime);
1759
+ });
1760
+ }
1761
+ _validateOutputs(opts, wallet) {
1762
+ if (_.isEmpty(opts.outputs))
1763
+ return new clienterror_1.ClientError('No outputs were specified');
1764
+ for (let i = 0; i < opts.outputs.length; i++) {
1765
+ const output = opts.outputs[i];
1766
+ output.valid = false;
1767
+ if (index_1.ChainService.isUTXOChain(wallet.chain) && output.script) {
1768
+ const error = index_1.ChainService.checkScriptOutput(wallet.chain, output);
1769
+ if (error)
1770
+ return error;
1771
+ output.valid = true;
1772
+ }
1773
+ else {
1774
+ try {
1775
+ index_1.ChainService.validateAddress(wallet, output.toAddress, opts);
1776
+ }
1777
+ catch (addrErr) {
1778
+ return addrErr;
1779
+ }
1780
+ if (!checkRequired(output, ['toAddress', 'amount'])) {
1781
+ return new clienterror_1.ClientError('Argument missing in output #' + (i + 1) + '.');
1782
+ }
1783
+ if (!index_1.ChainService.checkValidTxAmount(wallet.chain, output)) {
1784
+ return new clienterror_1.ClientError('Invalid amount');
1785
+ }
1786
+ const error = index_1.ChainService.checkDust(wallet.chain, output, opts);
1787
+ if (error)
1788
+ return error;
1789
+ output.valid = true;
1790
+ }
1791
+ }
1792
+ return null;
1793
+ }
1794
+ _validateAndSanitizeTxOpts(wallet, opts, cb) {
1795
+ async.series([
1796
+ next => {
1797
+ const feeArgs = boolToNum(!!opts.feeLevel) + boolToNum(Utils.isNumber(opts.feePerKb)) + boolToNum(Utils.isNumber(opts.fee));
1798
+ if (feeArgs > 1)
1799
+ return next(new clienterror_1.ClientError('Only one of feeLevel/feePerKb/fee can be specified'));
1800
+ if (feeArgs == 0) {
1801
+ opts.feeLevel = 'normal';
1802
+ }
1803
+ const feeLevels = Defaults.FEE_LEVELS[wallet.chain];
1804
+ if (opts.feeLevel) {
1805
+ if (!feeLevels.some(lvl => lvl.name === opts.feeLevel))
1806
+ return next(new clienterror_1.ClientError('Invalid fee level. Valid values are ' + feeLevels.map(lvl => lvl.name).join(', ')));
1807
+ }
1808
+ const error = index_1.ChainService.checkUtxos(wallet.chain, opts);
1809
+ if (error) {
1810
+ return next(new clienterror_1.ClientError('fee can only be set when inputs are specified'));
1811
+ }
1812
+ next();
1813
+ },
1814
+ next => {
1815
+ if (wallet.singleAddress && opts.changeAddress)
1816
+ return next(new clienterror_1.ClientError('Cannot specify change address on single-address wallet'));
1817
+ next();
1818
+ },
1819
+ next => {
1820
+ if (!opts.sendMax)
1821
+ return next();
1822
+ if (!Array.isArray(opts.outputs) || opts.outputs.length > 1) {
1823
+ return next(new clienterror_1.ClientError('Only one output allowed when sendMax is specified'));
1824
+ }
1825
+ if (Utils.isNumber(opts.outputs[0].amount))
1826
+ return next(new clienterror_1.ClientError('Amount is not allowed when sendMax is specified'));
1827
+ if (Utils.isNumber(opts.fee))
1828
+ return next(new clienterror_1.ClientError('Fee is not allowed when sendMax is specified (use feeLevel/feePerKb instead)'));
1829
+ this.getSendMaxInfo({
1830
+ feePerKb: opts.feePerKb,
1831
+ excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos,
1832
+ returnInputs: true,
1833
+ numSignatures: opts.numSignatures
1834
+ }, (err, info) => {
1835
+ if (err)
1836
+ return next(err);
1837
+ opts.outputs[0].amount = info.amount;
1838
+ opts.inputs = info.inputs;
1839
+ return next();
1840
+ });
1841
+ },
1842
+ next => {
1843
+ const validationError = this._validateOutputs(opts, wallet);
1844
+ if (validationError) {
1845
+ return next(validationError);
1846
+ }
1847
+ next();
1848
+ },
1849
+ next => {
1850
+ if (wallet.chain != 'bch')
1851
+ return next();
1852
+ if (!opts.noCashAddr)
1853
+ return next();
1854
+ opts.origAddrOutputs = opts.outputs.map(x => {
1855
+ const ret = {
1856
+ toAddress: x.toAddress,
1857
+ amount: x.amount
1858
+ };
1859
+ if (x.message)
1860
+ ret.message = x.message;
1861
+ if (x.script)
1862
+ ret.script = x.script;
1863
+ return ret;
1864
+ });
1865
+ opts.returnOrigAddrOutputs = false;
1866
+ for (const x of opts.outputs) {
1867
+ if (!x.toAddress)
1868
+ continue;
1869
+ let newAddr;
1870
+ try {
1871
+ newAddr = Bitcore_['bch'].Address(x.toAddress).toLegacyAddress();
1872
+ }
1873
+ catch (e) {
1874
+ return next(e);
1875
+ }
1876
+ if (x.txAddress != newAddr) {
1877
+ x.toAddress = newAddr;
1878
+ opts.returnOrigAddrOutputs = true;
1879
+ }
1880
+ }
1881
+ next();
1882
+ }
1883
+ ], cb);
1884
+ }
1885
+ _getFeePerKb(wallet, opts, cb) {
1886
+ if (Utils.isNumber(opts.feePerKb))
1887
+ return cb(null, opts.feePerKb);
1888
+ this.getFeeLevels({
1889
+ chain: wallet.chain,
1890
+ network: wallet.network
1891
+ }, (err, levels) => {
1892
+ if (err)
1893
+ return cb(err);
1894
+ const level = levels.find(l => l.level === opts.feeLevel);
1895
+ if (!level) {
1896
+ const msg = `Could not compute fee for "${opts.feeLevel}" level`;
1897
+ this.logw(msg);
1898
+ return cb(new clienterror_1.ClientError(msg));
1899
+ }
1900
+ return cb(null, level.feePerKb);
1901
+ });
1902
+ }
1903
+ _getTransactionCount(wallet, address, cb) {
1904
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
1905
+ if (!bc)
1906
+ return cb(new Error('Could not get blockchain explorer instance'));
1907
+ bc.getTransactionCount(address, (err, nonce) => {
1908
+ if (err) {
1909
+ this.logw('Error estimating nonce:', err);
1910
+ return cb(err);
1911
+ }
1912
+ return cb(null, nonce);
1913
+ });
1914
+ }
1915
+ getNonce(opts) {
1916
+ const bc = this._getBlockchainExplorer(opts.chain || opts.coin || Defaults.EVM_CHAIN, opts.network);
1917
+ return new Promise((resolve, reject) => {
1918
+ if (!bc)
1919
+ return reject(new Error('Could not get blockchain explorer instance'));
1920
+ bc.getTransactionCount(opts.address, (err, nonce) => {
1921
+ if (err) {
1922
+ this.logw('Error estimating nonce:', err);
1923
+ return reject(err);
1924
+ }
1925
+ return resolve(nonce);
1926
+ });
1927
+ });
1928
+ }
1929
+ estimateGas(opts) {
1930
+ const bc = this._getBlockchainExplorer(opts.chain || opts.coin || Defaults.EVM_CHAIN, opts.network);
1931
+ return new Promise((resolve, reject) => {
1932
+ if (!bc)
1933
+ return reject(new Error('Could not get blockchain explorer instance'));
1934
+ bc.estimateGas(opts, (err, gasLimit) => {
1935
+ if (err) {
1936
+ this.logw('Error estimating gas limit:', err);
1937
+ return reject(err);
1938
+ }
1939
+ return resolve(gasLimit);
1940
+ });
1941
+ });
1942
+ }
1943
+ getMultisigContractInstantiationInfo(opts) {
1944
+ const bc = this._getBlockchainExplorer(opts.chain || Defaults.EVM_CHAIN, opts.network);
1945
+ return new Promise((resolve, reject) => {
1946
+ if (!bc)
1947
+ return reject(new Error('Could not get blockchain explorer instance'));
1948
+ bc.getMultisigContractInstantiationInfo(opts, (err, contractInstantiationInfo) => {
1949
+ if (err) {
1950
+ this.logw('Error getting contract instantiation info:', err);
1951
+ return reject(err);
1952
+ }
1953
+ return resolve(contractInstantiationInfo);
1954
+ });
1955
+ });
1956
+ }
1957
+ getMultisigContractInfo(opts) {
1958
+ const bc = this._getBlockchainExplorer(opts.chain || Defaults.EVM_CHAIN, opts.network);
1959
+ return new Promise((resolve, reject) => {
1960
+ if (!bc)
1961
+ return reject(new Error('Could not get blockchain explorer instance'));
1962
+ bc.getMultisigContractInfo(opts, (err, contractInfo) => {
1963
+ if (err) {
1964
+ this.logw('Error getting contract instantiation info:', err);
1965
+ return reject(err);
1966
+ }
1967
+ return resolve(contractInfo);
1968
+ });
1969
+ });
1970
+ }
1971
+ getTokenContractInfo(opts) {
1972
+ const bc = this._getBlockchainExplorer(opts.chain || Defaults.EVM_CHAIN, opts.network);
1973
+ return new Promise((resolve, reject) => {
1974
+ if (!bc)
1975
+ return reject(new Error('Could not get blockchain explorer instance'));
1976
+ bc.getTokenContractInfo(opts, (err, contractInfo) => {
1977
+ if (err) {
1978
+ this.logw('Error getting contract info:', err);
1979
+ return reject(err);
1980
+ }
1981
+ return resolve(contractInfo);
1982
+ });
1983
+ });
1984
+ }
1985
+ getMultisigTxpsInfo(opts) {
1986
+ const bc = this._getBlockchainExplorer(opts.chain || Defaults.EVM_CHAIN, opts.network);
1987
+ return new Promise((resolve, reject) => {
1988
+ if (!bc)
1989
+ return reject(new Error('Could not get blockchain explorer instance'));
1990
+ bc.getMultisigTxpsInfo(opts, (err, multisigTxpsInfo) => {
1991
+ if (err) {
1992
+ this.logw('Error getting contract txps hash:', err);
1993
+ return reject(err);
1994
+ }
1995
+ return resolve(multisigTxpsInfo);
1996
+ });
1997
+ });
1998
+ }
1999
+ createTx(opts, cb) {
2000
+ opts = opts ? _.clone(opts) : {};
2001
+ const checkTxpAlreadyExists = (txProposalId, cb) => {
2002
+ if (!txProposalId)
2003
+ return cb();
2004
+ this.storage.fetchTx(this.walletId, txProposalId, cb);
2005
+ };
2006
+ this._runLocked(cb, cb => {
2007
+ let changeAddress, feePerKb, gasPrice, gasLimit, fee, maxGasFee, priorityGasFee;
2008
+ this.getWallet({}, (err, wallet) => {
2009
+ if (err)
2010
+ return cb(err);
2011
+ if (!wallet.isComplete())
2012
+ return cb(errordefinitions_1.Errors.WALLET_NOT_COMPLETE);
2013
+ if (wallet.scanStatus == 'error')
2014
+ return cb(errordefinitions_1.Errors.WALLET_NEED_SCAN);
2015
+ if (config_1.default.suspendedChains && config_1.default.suspendedChains.includes(wallet.chain)) {
2016
+ const Err = errordefinitions_1.Errors.NETWORK_SUSPENDED;
2017
+ Err.message = Err.message.replace('$network', wallet.chain.toUpperCase());
2018
+ return cb(Err);
2019
+ }
2020
+ checkTxpAlreadyExists(opts.txProposalId, (err, txp) => {
2021
+ if (err)
2022
+ return cb(err);
2023
+ if (txp)
2024
+ return cb(null, txp);
2025
+ async.series([
2026
+ next => {
2027
+ if (index_1.ChainService.isUTXOChain(wallet.chain))
2028
+ return next();
2029
+ this.getAddresses({ reverse: true, limit: 1, noChange: true }, (err, mainAddr) => {
2030
+ if (err)
2031
+ return next(err);
2032
+ opts.from = mainAddr[0].address;
2033
+ next();
2034
+ });
2035
+ },
2036
+ next => {
2037
+ this._validateAndSanitizeTxOpts(wallet, opts, next);
2038
+ },
2039
+ next => {
2040
+ this._canCreateTx((err, canCreate) => {
2041
+ if (err)
2042
+ return next(err);
2043
+ if (!canCreate)
2044
+ return next(errordefinitions_1.Errors.TX_CANNOT_CREATE);
2045
+ next();
2046
+ });
2047
+ },
2048
+ async (next) => {
2049
+ if (opts.sendMax)
2050
+ return next();
2051
+ try {
2052
+ changeAddress = await index_1.ChainService.getChangeAddress(this, wallet, opts);
2053
+ }
2054
+ catch (error) {
2055
+ return next(error);
2056
+ }
2057
+ return next();
2058
+ },
2059
+ async (next) => {
2060
+ logger_1.default.info('Calculating fee for new tx: %o', {
2061
+ from: opts.from, fee: opts.fee, input: opts.inputs?.length, gasLimit: opts.gasLimit, gasLimitBuffer: opts.gasLimitBuffer
2062
+ });
2063
+ if (!isNaN(opts.fee) && (opts.inputs || []).length > 0)
2064
+ return next();
2065
+ try {
2066
+ ({ feePerKb, gasPrice, maxGasFee, priorityGasFee, gasLimit, fee } = await index_1.ChainService.getFee(this, wallet, opts));
2067
+ logger_1.default.info('ChainService.getFee return value %o', {
2068
+ from: opts.from, feePerKb, gasPrice, maxGasFee, priorityGasFee, gasLimit, fee
2069
+ });
2070
+ }
2071
+ catch (error) {
2072
+ return next(error);
2073
+ }
2074
+ next();
2075
+ },
2076
+ async (next) => {
2077
+ if (!opts.nonce && !Constants.SVM_CHAINS[wallet.chain.toUpperCase()]) {
2078
+ try {
2079
+ opts.nonce = await index_1.ChainService.getTransactionCount(this, wallet, opts.from);
2080
+ }
2081
+ catch (error) {
2082
+ return next(error);
2083
+ }
2084
+ }
2085
+ return next();
2086
+ },
2087
+ async (next) => {
2088
+ if (Constants.SVM_CHAINS[wallet.chain.toUpperCase()] && !opts.nonceAddress) {
2089
+ this._getBlockchainHeight(wallet.chain, wallet.network, (err, height, hash) => {
2090
+ if (err)
2091
+ return next(err);
2092
+ opts.blockHeight = height;
2093
+ opts.blockHash = hash;
2094
+ opts.refreshOnPublish = true;
2095
+ return next();
2096
+ });
2097
+ }
2098
+ else {
2099
+ return next();
2100
+ }
2101
+ },
2102
+ async (next) => {
2103
+ opts.signingMethod = opts.signingMethod || 'ecdsa';
2104
+ opts.coin = opts.coin || wallet.coin;
2105
+ if (!['ecdsa', 'schnorr'].includes(opts.signingMethod)) {
2106
+ return next(errordefinitions_1.Errors.WRONG_SIGNING_METHOD);
2107
+ }
2108
+ if (opts.coin != 'bch' && opts.signingMethod == 'schnorr')
2109
+ return next(errordefinitions_1.Errors.WRONG_SIGNING_METHOD);
2110
+ return next();
2111
+ },
2112
+ next => {
2113
+ try {
2114
+ let txOptsFee = fee;
2115
+ if (!txOptsFee) {
2116
+ const useInputFee = opts.inputs && isNaN(opts.feePerKb);
2117
+ const isNotUtxoCoin = !index_1.ChainService.isUTXOChain(wallet.chain);
2118
+ const shouldUseOptsFee = useInputFee || isNotUtxoCoin;
2119
+ if (shouldUseOptsFee) {
2120
+ txOptsFee = opts.fee;
2121
+ }
2122
+ }
2123
+ const txOpts = {
2124
+ id: opts.txProposalId,
2125
+ walletId: this.walletId,
2126
+ creatorId: this.copayerId,
2127
+ coin: opts.coin,
2128
+ chain: opts.chain?.toLowerCase() || Utils.getChain(opts.coin),
2129
+ network: wallet.network,
2130
+ outputs: opts.outputs,
2131
+ message: opts.message,
2132
+ from: opts.from,
2133
+ changeAddress,
2134
+ feeLevel: opts.feeLevel,
2135
+ feePerKb,
2136
+ payProUrl: opts.payProUrl,
2137
+ walletM: wallet.m,
2138
+ walletN: wallet.n,
2139
+ excludeUnconfirmedUtxos: !!opts.excludeUnconfirmedUtxos,
2140
+ instantAcceptanceEscrow: opts.instantAcceptanceEscrow,
2141
+ addressType: wallet.addressType,
2142
+ customData: opts.customData,
2143
+ inputs: opts.inputs,
2144
+ version: opts.txpVersion,
2145
+ fee: txOptsFee,
2146
+ noShuffleOutputs: opts.noShuffleOutputs,
2147
+ gasPrice,
2148
+ maxGasFee,
2149
+ priorityGasFee,
2150
+ txType: opts.txType,
2151
+ nonce: opts.nonce,
2152
+ gasLimit,
2153
+ data: opts.data,
2154
+ tokenAddress: opts.tokenAddress,
2155
+ multisigContractAddress: opts.multisigContractAddress,
2156
+ multiSendContractAddress: opts.multiSendContractAddress,
2157
+ destinationTag: opts.destinationTag,
2158
+ invoiceID: opts.invoiceID,
2159
+ signingMethod: opts.signingMethod,
2160
+ isTokenSwap: opts.isTokenSwap,
2161
+ enableRBF: opts.enableRBF,
2162
+ replaceTxByFee: opts.replaceTxByFee,
2163
+ multiTx: opts.multiTx,
2164
+ blockHash: opts.blockHash,
2165
+ blockHeight: opts.blockHeight,
2166
+ nonceAddress: opts.nonceAddress,
2167
+ category: opts.category,
2168
+ fromKeyPair: opts.fromKeyPair,
2169
+ priorityFee: opts.priorityFee,
2170
+ computeUnits: opts.computeUnits,
2171
+ memo: opts.memo,
2172
+ fromAta: opts.fromAta,
2173
+ decimals: opts.decimals,
2174
+ refreshOnPublish: opts.refreshOnPublish
2175
+ };
2176
+ txp = model_1.TxProposal.create(txOpts);
2177
+ next();
2178
+ }
2179
+ catch (e) {
2180
+ logger_1.default.error('Error creating TX: %o', e.stack || e.message || e);
2181
+ return next(e);
2182
+ }
2183
+ },
2184
+ async (next) => {
2185
+ if (opts.chain != 'xrp')
2186
+ return next();
2187
+ this.getBalance({ chain: opts.chain, wallet }, async (err, bal) => {
2188
+ if (err)
2189
+ return next(err);
2190
+ index_1.ChainService.getReserve(this, wallet, (err, reserve) => {
2191
+ if (err)
2192
+ return next(err);
2193
+ if (reserve > bal.totalConfirmedAmount - txp.getTotalAmount() - txp.fee)
2194
+ return next(errordefinitions_1.Errors.BALANCE_BELOW_RESERVE);
2195
+ return next();
2196
+ });
2197
+ });
2198
+ },
2199
+ next => {
2200
+ return index_1.ChainService.selectTxInputs(this, txp, wallet, opts, next);
2201
+ },
2202
+ async (next) => {
2203
+ if (!wallet.isZceCompatible() || !opts.instantAcceptanceEscrow)
2204
+ return next();
2205
+ try {
2206
+ opts.inputs = txp.inputs;
2207
+ const escrowAddress = await index_1.ChainService.getChangeAddress(this, wallet, opts);
2208
+ txp.escrowAddress = escrowAddress;
2209
+ }
2210
+ catch (error) {
2211
+ return next(error);
2212
+ }
2213
+ if (opts.dryRun)
2214
+ return next();
2215
+ this._store(wallet, txp.escrowAddress, next, true);
2216
+ },
2217
+ next => {
2218
+ if (!txp.multiSendContractAddress || !txp.tokenAddress) {
2219
+ return next();
2220
+ }
2221
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
2222
+ if (!bc)
2223
+ return cb(new Error('Could not get blockchain explorer instance'));
2224
+ bc.getTokenAllowance({
2225
+ tokenAddress: txp.tokenAddress,
2226
+ ownerAddress: txp.from,
2227
+ spenderAddress: txp.multiSendContractAddress
2228
+ }, (err, allowance) => {
2229
+ if (err) {
2230
+ return next(err);
2231
+ }
2232
+ if (BigInt(allowance) < BigInt(txp.getTotalAmount())) {
2233
+ return next(new Error(`Insufficient token allowance. Allowed: ${BigInt(allowance)}, Want: ${BigInt(txp.getTotalAmount())}`));
2234
+ }
2235
+ return next();
2236
+ });
2237
+ },
2238
+ next => {
2239
+ if (!changeAddress || wallet.singleAddress || opts.dryRun || opts.changeAddress)
2240
+ return next();
2241
+ this._store(wallet, txp.changeAddress, next, true);
2242
+ },
2243
+ next => {
2244
+ if (opts.dryRun)
2245
+ return next();
2246
+ if (txp.coin == 'bch' && txp.changeAddress) {
2247
+ const format = opts.noCashAddr ? 'copay' : 'cashaddr';
2248
+ txp.changeAddress.address = bchaddresstranslator_1.BCHAddressTranslator.translate(txp.changeAddress.address, format);
2249
+ }
2250
+ this.storage.storeTx(wallet.id, txp, next);
2251
+ }
2252
+ ], err => {
2253
+ if (err)
2254
+ return cb(err);
2255
+ if (txp.coin == 'bch') {
2256
+ if (opts.returnOrigAddrOutputs) {
2257
+ logger_1.default.info('Returning Orig BCH address outputs for compat');
2258
+ txp.outputs = opts.origAddrOutputs;
2259
+ }
2260
+ }
2261
+ return cb(null, txp);
2262
+ });
2263
+ });
2264
+ });
2265
+ }, 10 * 1000);
2266
+ }
2267
+ publishTx(opts, cb) {
2268
+ if (!checkRequired(opts, ['txProposalId', 'proposalSignature'], cb))
2269
+ return;
2270
+ this._runLocked(cb, cb => {
2271
+ this.getWallet({}, (err, wallet) => {
2272
+ if (err)
2273
+ return cb(err);
2274
+ if (config_1.default.suspendedChains && config_1.default.suspendedChains.includes(wallet.chain)) {
2275
+ const Err = errordefinitions_1.Errors.NETWORK_SUSPENDED;
2276
+ Err.message = Err.message.replace('$network', wallet.chain.toUpperCase());
2277
+ return cb(Err);
2278
+ }
2279
+ this.storage.fetchTx(this.walletId, opts.txProposalId, (err, txp) => {
2280
+ if (err)
2281
+ return cb(err);
2282
+ if (!txp)
2283
+ return cb(errordefinitions_1.Errors.TX_NOT_FOUND);
2284
+ if (!txp.isTemporary() && !txp.isRepublishEnabled())
2285
+ return cb(null, txp);
2286
+ const copayer = wallet.getCopayer(this.copayerId);
2287
+ let raw;
2288
+ try {
2289
+ raw = txp.getRawTx();
2290
+ }
2291
+ catch (ex) {
2292
+ return cb(ex);
2293
+ }
2294
+ let signingKey = this._getSigningKey(raw, opts.proposalSignature, copayer.requestPubKeys);
2295
+ if (!signingKey) {
2296
+ if (txp.isRepublishEnabled() && txp.prePublishRaw) {
2297
+ raw = txp.prePublishRaw;
2298
+ signingKey = this._getSigningKey(raw, opts.proposalSignature, copayer.requestPubKeys);
2299
+ }
2300
+ }
2301
+ if (!signingKey) {
2302
+ return cb(new clienterror_1.ClientError('Invalid proposal signature'));
2303
+ }
2304
+ if (!txp.proposalSignature) {
2305
+ txp.proposalSignature = opts.proposalSignature;
2306
+ if (signingKey.selfSigned) {
2307
+ txp.proposalSignaturePubKey = signingKey.key;
2308
+ txp.proposalSignaturePubKeySig = signingKey.signature;
2309
+ }
2310
+ }
2311
+ index_1.ChainService.checkTxUTXOs(this, txp, opts, err => {
2312
+ if (err)
2313
+ return cb(err);
2314
+ txp.status = 'pending';
2315
+ index_1.ChainService.refreshTxData(this, txp, opts, (err, txp) => {
2316
+ if (err)
2317
+ return cb(err);
2318
+ if (txp.isRepublishEnabled() && !txp.prePublishRaw) {
2319
+ txp.prePublishRaw = raw;
2320
+ }
2321
+ this.storage.storeTx(this.walletId, txp, err => {
2322
+ if (err)
2323
+ return cb(err);
2324
+ const action = txp.isRepublishEnabled() && txp.prePublishRaw ? 'UpdatedTxProposal' : 'NewTxProposal';
2325
+ this._notifyTxProposalAction(action, txp, () => {
2326
+ if (txp.coin == 'bch' && txp.changeAddress) {
2327
+ const format = opts.noCashAddr ? 'copay' : 'cashaddr';
2328
+ txp.changeAddress.address = bchaddresstranslator_1.BCHAddressTranslator.translate(txp.changeAddress.address, format);
2329
+ }
2330
+ return cb(null, txp);
2331
+ });
2332
+ });
2333
+ });
2334
+ });
2335
+ });
2336
+ });
2337
+ });
2338
+ }
2339
+ getTx(opts, cb) {
2340
+ this.storage.fetchTx(this.walletId, opts.txProposalId, (err, txp) => {
2341
+ if (err)
2342
+ return cb(err);
2343
+ if (!txp)
2344
+ return cb(errordefinitions_1.Errors.TX_NOT_FOUND);
2345
+ if (!txp.txid)
2346
+ return cb(null, txp);
2347
+ this.storage.fetchTxNote(this.walletId, txp.txid, (err, note) => {
2348
+ if (err) {
2349
+ this.logw(`Error fetching tx note for ${txp.txid}:`, err);
2350
+ }
2351
+ txp.note = note;
2352
+ return cb(null, txp);
2353
+ });
2354
+ });
2355
+ }
2356
+ getTxByHash(opts, cb) {
2357
+ this.storage.fetchTxByHash(opts.txid, (err, txp) => {
2358
+ if (err)
2359
+ return cb(err);
2360
+ if (!txp)
2361
+ return cb(errordefinitions_1.Errors.TX_NOT_FOUND);
2362
+ if (!txp.txid)
2363
+ return cb(null, txp);
2364
+ this.storage.fetchTxNote(this.walletId, txp.txid, (err, note) => {
2365
+ if (err) {
2366
+ this.logw(`Error fetching tx note for ${txp.txid}:`, err);
2367
+ }
2368
+ txp.note = note;
2369
+ return cb(null, txp);
2370
+ });
2371
+ });
2372
+ }
2373
+ editTxNote(opts, cb) {
2374
+ if (!checkRequired(opts, 'txid', cb))
2375
+ return;
2376
+ this._runLocked(cb, cb => {
2377
+ this.storage.fetchTxNote(this.walletId, opts.txid, (err, note) => {
2378
+ if (err)
2379
+ return cb(err);
2380
+ if (!note) {
2381
+ note = model_1.TxNote.create({
2382
+ walletId: this.walletId,
2383
+ txid: opts.txid,
2384
+ copayerId: this.copayerId,
2385
+ body: opts.body
2386
+ });
2387
+ }
2388
+ else {
2389
+ note.edit(opts.body, this.copayerId);
2390
+ }
2391
+ this.storage.storeTxNote(note, err => {
2392
+ if (err)
2393
+ return cb(err);
2394
+ this.storage.fetchTxNote(this.walletId, opts.txid, cb);
2395
+ });
2396
+ });
2397
+ });
2398
+ }
2399
+ getTxNote(opts, cb) {
2400
+ if (!checkRequired(opts, 'txid', cb))
2401
+ return;
2402
+ this.storage.fetchTxNote(this.walletId, opts.txid, cb);
2403
+ }
2404
+ getTxNotes(opts, cb) {
2405
+ opts = opts || {};
2406
+ this.storage.fetchTxNotes(this.walletId, opts, cb);
2407
+ }
2408
+ removeWallet(opts, cb) {
2409
+ this._runLocked(cb, cb => {
2410
+ this.storage.removeWallet(this.walletId, cb);
2411
+ });
2412
+ }
2413
+ getRemainingDeleteLockTime(txp) {
2414
+ const now = Math.floor(Date.now() / 1000);
2415
+ const lockTimeRemaining = txp.createdOn + Defaults.DELETE_LOCKTIME - now;
2416
+ if (lockTimeRemaining < 0)
2417
+ return 0;
2418
+ if (txp.creatorId !== this.copayerId)
2419
+ return lockTimeRemaining;
2420
+ const approvers = txp.getApprovers();
2421
+ if (approvers.length > 1 || (approvers.length == 1 && approvers[0] !== this.copayerId))
2422
+ return lockTimeRemaining;
2423
+ return 0;
2424
+ }
2425
+ removePendingTx(opts, cb) {
2426
+ if (!checkRequired(opts, ['txProposalId'], cb))
2427
+ return;
2428
+ this._runLocked(cb, cb => {
2429
+ this.getTx({
2430
+ txProposalId: opts.txProposalId
2431
+ }, (err, txp) => {
2432
+ if (err)
2433
+ return cb(err);
2434
+ if (!txp.isPending())
2435
+ return cb(errordefinitions_1.Errors.TX_NOT_PENDING);
2436
+ const deleteLockTime = this.getRemainingDeleteLockTime(txp);
2437
+ if (deleteLockTime > 0)
2438
+ return cb(errordefinitions_1.Errors.TX_CANNOT_REMOVE);
2439
+ this.storage.removeTx(this.walletId, txp.id, () => {
2440
+ this._notifyTxProposalAction('TxProposalRemoved', txp, cb);
2441
+ });
2442
+ });
2443
+ });
2444
+ }
2445
+ _broadcastRawTx(chain, network, raw, cb) {
2446
+ const bc = this._getBlockchainExplorer(chain, network);
2447
+ if (!bc)
2448
+ return cb(new Error('Could not get blockchain explorer instance'));
2449
+ bc.broadcast(raw, (err, txid) => {
2450
+ if (err) {
2451
+ this.logw('Error broadcasting tx: %o %o %o %o', chain, network, raw, err);
2452
+ return cb(err);
2453
+ }
2454
+ return cb(null, txid);
2455
+ });
2456
+ }
2457
+ broadcastRawTx(opts, cb) {
2458
+ if (!checkRequired(opts, ['network', 'rawTx'], cb))
2459
+ return;
2460
+ opts.chain = opts.chain || opts.coin || Defaults.COIN;
2461
+ if (!Utils.checkValueInCollection(opts.chain, Constants.CHAINS))
2462
+ return cb(new clienterror_1.ClientError('Invalid chain'));
2463
+ opts.network = Utils.getNetworkName(opts.chain, opts.network) || 'livenet';
2464
+ if (!Utils.checkValueInCollection(opts.network, Constants.NETWORKS[opts.chain]))
2465
+ return cb(new clienterror_1.ClientError('Invalid network'));
2466
+ this._broadcastRawTx(opts.chain, opts.network, opts.rawTx, cb);
2467
+ }
2468
+ _checkTxInBlockchain(txp, cb) {
2469
+ if (!txp.txid)
2470
+ return cb();
2471
+ const bc = this._getBlockchainExplorer(txp.chain, txp.network);
2472
+ if (!bc)
2473
+ return cb(new Error('Could not get blockchain explorer instance'));
2474
+ bc.getTransaction(txp.txid, (err, tx) => {
2475
+ if (err)
2476
+ return cb(err);
2477
+ return cb(null, !!tx);
2478
+ });
2479
+ }
2480
+ signTx(opts, cb) {
2481
+ if (!checkRequired(opts, ['txProposalId', 'signatures'], cb))
2482
+ return;
2483
+ opts.maxTxpVersion = opts.maxTxpVersion || 3;
2484
+ this.getWallet({}, (err, wallet) => {
2485
+ if (err)
2486
+ return cb(err);
2487
+ if (config_1.default.suspendedChains && config_1.default.suspendedChains.includes(wallet.chain)) {
2488
+ const Err = errordefinitions_1.Errors.NETWORK_SUSPENDED;
2489
+ Err.message = Err.message.replace('$network', wallet.chain.toUpperCase());
2490
+ return cb(Err);
2491
+ }
2492
+ this.getTx({
2493
+ txProposalId: opts.txProposalId
2494
+ }, async (err, txp) => {
2495
+ if (err)
2496
+ return cb(err);
2497
+ if (this._upgradeNeeded(exports.UPGRADES.version_$gt_maxTxpVersion, { maxTxpVersion: opts.maxTxpVersion, version: txp.version })) {
2498
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED.withMessage('Your client does not support signing this transaction. Please upgrade'));
2499
+ }
2500
+ const action = txp.actions.find(a => a.copayerId === this.copayerId);
2501
+ if (action)
2502
+ return cb(errordefinitions_1.Errors.COPAYER_VOTED);
2503
+ if (!txp.isPending())
2504
+ return cb(errordefinitions_1.Errors.TX_NOT_PENDING);
2505
+ if (this._upgradeNeeded(exports.UPGRADES.BCH_schnorr, { signingMethod: txp.signingMethod, supportBchSchnorr: opts.supportBchSchnorr })) {
2506
+ return cb(errordefinitions_1.Errors.UPGRADE_NEEDED);
2507
+ }
2508
+ if ([...Object.keys(Constants.EVM_CHAINS), 'XRP'].includes(wallet.chain.toUpperCase())) {
2509
+ try {
2510
+ const txps = await this.getPendingTxsPromise({});
2511
+ for (const t of txps) {
2512
+ if (t.id !== txp.id && t.nonce <= txp.nonce && t.status !== 'rejected') {
2513
+ return cb(errordefinitions_1.Errors.TX_NONCE_CONFLICT);
2514
+ }
2515
+ }
2516
+ }
2517
+ catch (err) {
2518
+ return cb(err);
2519
+ }
2520
+ }
2521
+ const copayer = wallet.getCopayer(this.copayerId);
2522
+ try {
2523
+ const xPubKey = wallet.tssKeyId ? wallet.clientDerivedPublicKey : copayer.xPubKey;
2524
+ if (!txp.sign(this.copayerId, opts.signatures, xPubKey)) {
2525
+ this.logw('Error signing transaction (BAD_SIGNATURES)');
2526
+ this.logw('Client version:', this.clientVersion);
2527
+ this.logw('Arguments:', JSON.stringify(opts));
2528
+ this.logw('Transaction proposal:', JSON.stringify(txp));
2529
+ const raw = index_1.ChainService.getBitcoreTx(txp).uncheckedSerialize();
2530
+ this.logw('Raw tx:', raw);
2531
+ return cb(errordefinitions_1.Errors.BAD_SIGNATURES);
2532
+ }
2533
+ }
2534
+ catch (ex) {
2535
+ this.logw('Error signing transaction proposal:', ex);
2536
+ return cb(ex);
2537
+ }
2538
+ this.storage.storeTx(this.walletId, txp, err => {
2539
+ if (err)
2540
+ return cb(err);
2541
+ async.series([
2542
+ next => {
2543
+ this._notifyTxProposalAction('TxProposalAcceptedBy', txp, {
2544
+ copayerId: this.copayerId
2545
+ }, next);
2546
+ },
2547
+ next => {
2548
+ if (txp.isAccepted()) {
2549
+ this._notifyTxProposalAction('TxProposalFinallyAccepted', txp, next);
2550
+ }
2551
+ else {
2552
+ next();
2553
+ }
2554
+ }
2555
+ ], () => {
2556
+ return cb(null, txp);
2557
+ });
2558
+ });
2559
+ });
2560
+ });
2561
+ }
2562
+ _processBroadcast(txp, opts, cb) {
2563
+ $.checkState(txp.txid, 'Failed state: txp.txid undefined at <_processBroadcast()>');
2564
+ opts = opts || {};
2565
+ txp.setBroadcasted();
2566
+ this.storage.storeTx(this.walletId, txp, err => {
2567
+ if (err)
2568
+ return cb(err);
2569
+ const extraArgs = {
2570
+ txid: txp?.txids?.length ? txp.txids : txp.txid
2571
+ };
2572
+ if (opts.byThirdParty) {
2573
+ this._notifyTxProposalAction('NewOutgoingTxByThirdParty', txp, extraArgs);
2574
+ }
2575
+ else {
2576
+ this._notifyTxProposalAction('NewOutgoingTx', txp, extraArgs);
2577
+ }
2578
+ return cb(null, txp);
2579
+ });
2580
+ }
2581
+ broadcastTx(opts, cb) {
2582
+ if (!checkRequired(opts, ['txProposalId'], cb))
2583
+ return;
2584
+ this.getWallet({}, (err, wallet) => {
2585
+ if (err)
2586
+ return cb(err);
2587
+ if (config_1.default.suspendedChains && config_1.default.suspendedChains.includes(wallet.chain)) {
2588
+ const Err = errordefinitions_1.Errors.NETWORK_SUSPENDED;
2589
+ Err.message = Err.message.replace('$network', wallet.chain.toUpperCase());
2590
+ return cb(Err);
2591
+ }
2592
+ this.getTx({ txProposalId: opts.txProposalId }, (err, txp) => {
2593
+ if (err)
2594
+ return cb(err);
2595
+ if (txp.status == 'broadcasted')
2596
+ return cb(errordefinitions_1.Errors.TX_ALREADY_BROADCASTED);
2597
+ if (txp.status != 'accepted')
2598
+ return cb(errordefinitions_1.Errors.TX_NOT_ACCEPTED);
2599
+ const sub = model_1.TxConfirmationSub.create({
2600
+ copayerId: txp.creatorId,
2601
+ txid: txp.txid,
2602
+ walletId: txp.walletId,
2603
+ amount: txp.amount,
2604
+ isActive: true,
2605
+ isCreator: true
2606
+ });
2607
+ this.storage.storeTxConfirmationSub(sub, err => {
2608
+ if (err)
2609
+ logger_1.default.error('Could not store Tx confirmation subscription: %o', err);
2610
+ let raw;
2611
+ try {
2612
+ raw = txp.getRawTx();
2613
+ }
2614
+ catch (ex) {
2615
+ return cb(ex);
2616
+ }
2617
+ this._broadcastRawTx(wallet.chain, wallet.network, raw, (err, txid) => {
2618
+ if (err || txid != txp.txid) {
2619
+ const broadcastErr = err?.response ? this._cleanLogArgs(err)[0] : err?.stack || err?.message || err;
2620
+ this.logw('Broadcast failed: %o %o %o %o %o', wallet.id, wallet.chain, wallet.network, raw, broadcastErr);
2621
+ this._checkTxInBlockchain(txp, (err, isInBlockchain) => {
2622
+ if (err)
2623
+ return cb(err);
2624
+ if (!isInBlockchain)
2625
+ return cb(broadcastErr || 'broadcast error');
2626
+ this._processBroadcast(txp, {
2627
+ byThirdParty: true
2628
+ }, cb);
2629
+ });
2630
+ }
2631
+ else {
2632
+ this._processBroadcast(txp, {
2633
+ byThirdParty: false
2634
+ }, err => {
2635
+ if (err)
2636
+ return cb(err);
2637
+ return cb(null, txp);
2638
+ });
2639
+ }
2640
+ });
2641
+ });
2642
+ });
2643
+ });
2644
+ }
2645
+ rejectTx(opts, cb) {
2646
+ if (!checkRequired(opts, ['txProposalId'], cb))
2647
+ return;
2648
+ this.getTx({
2649
+ txProposalId: opts.txProposalId
2650
+ }, (err, txp) => {
2651
+ if (err)
2652
+ return cb(err);
2653
+ const action = txp.actions.find(a => a.copayerId === this.copayerId);
2654
+ if (action)
2655
+ return cb(errordefinitions_1.Errors.COPAYER_VOTED);
2656
+ if (txp.status != 'pending')
2657
+ return cb(errordefinitions_1.Errors.TX_NOT_PENDING);
2658
+ txp.reject(this.copayerId, opts.reason);
2659
+ this.storage.storeTx(this.walletId, txp, err => {
2660
+ if (err)
2661
+ return cb(err);
2662
+ async.series([
2663
+ next => {
2664
+ this._notifyTxProposalAction('TxProposalRejectedBy', txp, {
2665
+ copayerId: this.copayerId
2666
+ }, next);
2667
+ },
2668
+ next => {
2669
+ if (txp.status == 'rejected') {
2670
+ const rejectedBy = txp.actions.filter(a => a.type === 'reject').map(a => a.copayerId);
2671
+ this._notifyTxProposalAction('TxProposalFinallyRejected', txp, {
2672
+ rejectedBy
2673
+ }, next);
2674
+ }
2675
+ else {
2676
+ next();
2677
+ }
2678
+ }
2679
+ ], () => {
2680
+ return cb(null, txp);
2681
+ });
2682
+ });
2683
+ });
2684
+ }
2685
+ async getPendingTxs(opts, cb) {
2686
+ if (opts.multisigContractAddress) {
2687
+ try {
2688
+ const multisigTxpsInfo = await this.getMultisigTxpsInfo(opts);
2689
+ const txps = await this.storage.fetchEthPendingTxs(multisigTxpsInfo);
2690
+ return cb(null, txps);
2691
+ }
2692
+ catch (error) {
2693
+ return cb(error);
2694
+ }
2695
+ }
2696
+ else {
2697
+ this.storage.fetchPendingTxs(this.walletId, (err, txps) => {
2698
+ if (err)
2699
+ return cb(err);
2700
+ if (opts.tokenAddress) {
2701
+ txps = txps.filter(txp => opts.tokenAddress?.toLowerCase() === txp.tokenAddress?.toLowerCase());
2702
+ }
2703
+ for (const txp of txps) {
2704
+ txp.deleteLockTime = this.getRemainingDeleteLockTime(txp);
2705
+ }
2706
+ ;
2707
+ async.each(txps, (txp, next) => {
2708
+ if (txp.status != 'accepted')
2709
+ return next();
2710
+ this._checkTxInBlockchain(txp, (err, isInBlockchain) => {
2711
+ if (err || !isInBlockchain)
2712
+ return next(err);
2713
+ this._processBroadcast(txp, {
2714
+ byThirdParty: true
2715
+ }, next);
2716
+ });
2717
+ }, err => {
2718
+ txps = txps.filter(txp => txp.status !== 'broadcasted');
2719
+ if (txps[0] && txps[0].chain == 'bch') {
2720
+ const format = opts.noCashAddr ? 'copay' : 'cashaddr';
2721
+ for (const t of txps) {
2722
+ if (t.changeAddress) {
2723
+ t.changeAddress.address = bchaddresstranslator_1.BCHAddressTranslator.translate(t.changeAddress.address, format);
2724
+ }
2725
+ for (const o of t.outputs) {
2726
+ if (o.toAddress) {
2727
+ o.toAddress = bchaddresstranslator_1.BCHAddressTranslator.translate(o.toAddress, format);
2728
+ }
2729
+ }
2730
+ }
2731
+ }
2732
+ return cb(err, txps);
2733
+ });
2734
+ });
2735
+ }
2736
+ }
2737
+ getPendingTxsPromise(opts) {
2738
+ return new Promise((resolve, reject) => {
2739
+ this.getPendingTxs(opts, (err, txps) => {
2740
+ if (err)
2741
+ return reject(err);
2742
+ return resolve(txps);
2743
+ });
2744
+ });
2745
+ }
2746
+ getTxs(opts, cb) {
2747
+ this.storage.fetchTxs(this.walletId, opts, (err, txps) => {
2748
+ if (err)
2749
+ return cb(err);
2750
+ return cb(null, txps);
2751
+ });
2752
+ }
2753
+ getNotifications(opts, cb) {
2754
+ opts = opts || {};
2755
+ this.getWallet({}, (err, wallet) => {
2756
+ if (err)
2757
+ return cb(err);
2758
+ async.map([`${wallet.chain}:${wallet.network}`, this.walletId], (walletId, next) => {
2759
+ this.storage.fetchNotifications(walletId, opts.notificationId, opts.minTs || 0, next);
2760
+ }, (err, res) => {
2761
+ if (err)
2762
+ return cb(err);
2763
+ const notifications = res
2764
+ .flat()
2765
+ .map((n) => ({ ...n, walletId: this.walletId }))
2766
+ .sort((a, b) => a.id - b.id);
2767
+ return cb(null, notifications);
2768
+ });
2769
+ });
2770
+ }
2771
+ _normalizeTxHistory(walletId, txs, dustThreshold, bcHeight, cb) {
2772
+ if (!txs?.length)
2773
+ return cb(null, txs);
2774
+ const indexedFee = _.keyBy(txs.filter(tx => tx.category === 'fee'), 'txid');
2775
+ const indexedSend = _.keyBy(txs.filter(tx => tx.category === 'send'), 'txid');
2776
+ const seenSend = {};
2777
+ const seenReceive = {};
2778
+ const moves = {};
2779
+ txs = txs.filter(tx => {
2780
+ if (tx.category == 'receive') {
2781
+ if (tx.satoshis < dustThreshold)
2782
+ return false;
2783
+ const output = {
2784
+ address: tx.address,
2785
+ amount: Math.abs(tx.satoshis)
2786
+ };
2787
+ if (seenReceive[tx.txid]) {
2788
+ seenReceive[tx.txid].outputs.push(output);
2789
+ return false;
2790
+ }
2791
+ else {
2792
+ tx.outputs = [output];
2793
+ seenReceive[tx.txid] = tx;
2794
+ return true;
2795
+ }
2796
+ }
2797
+ if (tx.category == 'send') {
2798
+ const output = {
2799
+ address: tx.address,
2800
+ amount: Math.abs(tx.satoshis)
2801
+ };
2802
+ if (seenSend[tx.txid]) {
2803
+ seenSend[tx.txid].outputs.push(output);
2804
+ return false;
2805
+ }
2806
+ else {
2807
+ tx.outputs = [output];
2808
+ seenSend[tx.txid] = tx;
2809
+ return true;
2810
+ }
2811
+ }
2812
+ if (tx.category == 'move' && !indexedSend[tx.txid]) {
2813
+ const output = {
2814
+ address: tx.address,
2815
+ amount: Math.abs(tx.satoshis)
2816
+ };
2817
+ if (moves[tx.txid]) {
2818
+ moves[tx.txid].outputs.push(output);
2819
+ return false;
2820
+ }
2821
+ else {
2822
+ moves[tx.txid] = tx;
2823
+ tx.outputs = [output];
2824
+ return true;
2825
+ }
2826
+ }
2827
+ });
2828
+ for (const txid in moves) {
2829
+ if (moves[txid].outputs.length <= 1) {
2830
+ delete moves[txid];
2831
+ }
2832
+ }
2833
+ const fixMoves = cb2 => {
2834
+ if (!Object.keys(moves).length)
2835
+ return cb2();
2836
+ const moves3 = Object.values(moves).flatMap(m => m.outputs);
2837
+ this.storage.fetchAddressesByWalletId(walletId, moves3.map(m => m.address), (err, addrs) => {
2838
+ if (err)
2839
+ return cb(err);
2840
+ const isChangeAddress = _.countBy(addrs.filter(a => a.isChange), 'address');
2841
+ for (const x of Object.values(moves)) {
2842
+ x.outputs = x.outputs.filter(o => !isChangeAddress[o.address]);
2843
+ }
2844
+ return cb2();
2845
+ });
2846
+ };
2847
+ fixMoves(err => {
2848
+ if (err)
2849
+ return cb(err);
2850
+ const ret = (txs || []).map(tx => {
2851
+ const t = new Date(tx.blockTime).getTime() / 1000;
2852
+ const c = tx.height >= 0 && bcHeight >= tx.height ? bcHeight - tx.height + 1 : 0;
2853
+ function recreateAbiType(effects) {
2854
+ if (effects && effects.length) {
2855
+ const erc20Transfer = effects.find(e => e.type == 'ERC20:transfer' && e.callStack == '');
2856
+ if (erc20Transfer) {
2857
+ return { name: 'transfer' };
2858
+ }
2859
+ }
2860
+ return undefined;
2861
+ }
2862
+ const ret = {
2863
+ id: tx.id,
2864
+ txid: tx.txid,
2865
+ confirmations: c,
2866
+ blockheight: tx.height > 0 ? tx.height : null,
2867
+ fees: tx.fee ?? (indexedFee[tx.txid] ? Math.abs(indexedFee[tx.txid].satoshis) : null),
2868
+ time: t,
2869
+ size: tx.size,
2870
+ amount: 0,
2871
+ action: undefined,
2872
+ addressTo: undefined,
2873
+ outputs: undefined,
2874
+ dust: false,
2875
+ error: tx.error,
2876
+ internal: tx.internal,
2877
+ network: tx.network,
2878
+ chain: tx.chain,
2879
+ data: tx.data,
2880
+ abiType: tx.abiType || recreateAbiType(tx.effects),
2881
+ gasPrice: tx.gasPrice,
2882
+ maxGasFee: tx.maxGasFee,
2883
+ priorityGasFee: tx.priorityGasFee,
2884
+ txType: tx.txType,
2885
+ gasLimit: tx.gasLimit,
2886
+ receipt: tx.receipt ? { ...tx.receipt, logs: undefined } : undefined,
2887
+ nonce: tx.nonce,
2888
+ effects: tx.effects
2889
+ };
2890
+ switch (tx.category) {
2891
+ case 'send':
2892
+ ret.action = 'sent';
2893
+ ret.amount = Math.abs(tx.outputs.reduce((sum, o) => sum += o.amount, 0)) || Math.abs(tx.satoshis);
2894
+ ret.addressTo = tx.outputs ? tx.outputs[0].address : null;
2895
+ ret.outputs = tx.outputs;
2896
+ break;
2897
+ case 'receive':
2898
+ ret.action = 'received';
2899
+ ret.outputs = tx.outputs;
2900
+ ret.amount = Math.abs(tx.outputs.reduce((sum, o) => sum += o.amount, 0)) || Math.abs(tx.satoshis);
2901
+ ret.dust = ret.amount < dustThreshold;
2902
+ break;
2903
+ case 'move':
2904
+ ret.action = 'moved';
2905
+ ret.amount = Math.abs(tx.satoshis);
2906
+ ret.addressTo = tx.outputs && tx.outputs.length ? tx.outputs[0].address : null;
2907
+ ret.outputs = tx.outputs;
2908
+ break;
2909
+ default:
2910
+ ret.action = 'invalid';
2911
+ }
2912
+ return ret;
2913
+ }).filter(x => !x.dust);
2914
+ return cb(null, ret);
2915
+ });
2916
+ }
2917
+ _getBlockchainHeight(chain, network, cb) {
2918
+ const cacheKey = storage_1.Storage.BCHEIGHT_KEY + ':' + chain + ':' + network;
2919
+ const cacheTime = Defaults.BLOCKHEIGHT_CACHE_TIME[chain.toLowerCase()] || Defaults.BLOCKHEIGHT_CACHE_TIME.default;
2920
+ this.storage.checkAndUseGlobalCache(cacheKey, cacheTime, (err, values) => {
2921
+ if (err)
2922
+ return cb(err);
2923
+ if (values)
2924
+ return cb(null, values.current, values.hash, true);
2925
+ values = {};
2926
+ const bc = this._getBlockchainExplorer(chain, network);
2927
+ if (!bc)
2928
+ return cb(new Error('Could not get blockchain explorer instance'));
2929
+ bc.getBlockchainHeight((err, height, hash) => {
2930
+ if (!err && height > 0) {
2931
+ values.current = height;
2932
+ values.hash = hash;
2933
+ }
2934
+ else {
2935
+ return cb(err || 'wrong height');
2936
+ }
2937
+ this.storage.storeGlobalCache(cacheKey, values, err => {
2938
+ if (err) {
2939
+ this.logw('Could not store bc height cache:', err);
2940
+ }
2941
+ return cb(null, values.current, values.hash);
2942
+ });
2943
+ });
2944
+ });
2945
+ }
2946
+ updateWalletV8Keys(wallet) {
2947
+ if (!wallet.beAuthPrivateKey2) {
2948
+ this.logd('Adding wallet beAuthKey');
2949
+ wallet.updateBEKeys();
2950
+ }
2951
+ }
2952
+ registerWalletV8(wallet, cb) {
2953
+ if (wallet.beRegistered) {
2954
+ return cb();
2955
+ }
2956
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
2957
+ this.logd('Registering wallet');
2958
+ bc.register(wallet, err => {
2959
+ if (err) {
2960
+ return cb(err);
2961
+ }
2962
+ wallet.beRegistered = true;
2963
+ return this.storage.storeWallet(wallet, err => cb(err, true));
2964
+ });
2965
+ }
2966
+ checkWalletSync(bc, wallet, simpleRun, cb) {
2967
+ if (!wallet.addressManager && !wallet.addressManager.receiveAddressIndex)
2968
+ return cb(null, true);
2969
+ const totalAddresses = wallet.addressManager.receiveAddressIndex + wallet.addressManager.changeAddressIndex;
2970
+ this.storage.getWalletAddressChecked(wallet.id, (err, checkedTotal) => {
2971
+ if (checkedTotal == totalAddresses) {
2972
+ logger_1.default.debug('addresses checked already');
2973
+ return cb(null, true);
2974
+ }
2975
+ if (simpleRun)
2976
+ return cb();
2977
+ this.storage.walletCheck({ walletId: wallet.id }).then((localCheck) => {
2978
+ bc.getCheckData(wallet, (err, serverCheck) => {
2979
+ if (err) {
2980
+ this.logw('Error at bitcore WalletCheck, ignoring:', err);
2981
+ return cb();
2982
+ }
2983
+ const isOK = serverCheck.sum == localCheck.sum;
2984
+ if (isOK) {
2985
+ logger_1.default.debug('Wallet Sync Check OK');
2986
+ }
2987
+ else {
2988
+ logger_1.default.warn('ERROR: Wallet check failed: %o', { localCheck, serverCheck });
2989
+ return cb(null, isOK);
2990
+ }
2991
+ this.storage.setWalletAddressChecked(wallet.id, totalAddresses, () => {
2992
+ return cb(null, isOK);
2993
+ });
2994
+ });
2995
+ });
2996
+ });
2997
+ }
2998
+ syncWallet(wallet, cb, skipCheck, count, force) {
2999
+ count = count || 0;
3000
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
3001
+ if (!bc) {
3002
+ return cb(new Error('Could not get blockchain explorer instance'));
3003
+ }
3004
+ this.updateWalletV8Keys(wallet);
3005
+ this.registerWalletV8(wallet, (err, justRegistered) => {
3006
+ if (err) {
3007
+ return cb(err);
3008
+ }
3009
+ this.checkWalletSync(bc, wallet, true, (err, isOK) => {
3010
+ if (isOK && !justRegistered && !force)
3011
+ return cb();
3012
+ const fetchAddresses = (force ? this.storage.fetchAddresses : this.storage.fetchUnsyncAddresses).bind(this.storage);
3013
+ fetchAddresses(this.walletId, (err, addresses) => {
3014
+ if (err) {
3015
+ return cb(err);
3016
+ }
3017
+ const syncAddr = (addresses, icb) => {
3018
+ if (!addresses?.length) {
3019
+ return icb();
3020
+ }
3021
+ const addressStr = addresses.map(x => {
3022
+ index_1.ChainService.addressFromStorageTransform(wallet.chain, wallet.network, x);
3023
+ return x.address;
3024
+ });
3025
+ this.logd('Syncing addresses: ', addressStr.length);
3026
+ bc.addAddresses(wallet, addressStr, err => {
3027
+ if (err)
3028
+ return cb(err);
3029
+ this.storage.markSyncedAddresses(addressStr, icb);
3030
+ }, { reprocess: force });
3031
+ };
3032
+ syncAddr(addresses, () => {
3033
+ if (skipCheck || doNotCheckV8)
3034
+ return cb();
3035
+ this.checkWalletSync(bc, wallet, false, (err, isOK) => {
3036
+ if (err)
3037
+ return cb();
3038
+ if (isOK)
3039
+ return cb();
3040
+ if (count++ >= 1) {
3041
+ logger_1.default.warn('## ERROR: TRIED TO SYNC WALLET AND FAILED. GIVING UP');
3042
+ return cb();
3043
+ }
3044
+ logger_1.default.info('Trying to RESYNC wallet... count:' + count);
3045
+ wallet.beRegistered = false;
3046
+ this.storage.deregisterWallet(wallet.id, () => {
3047
+ this.syncWallet(wallet, cb, false, count);
3048
+ });
3049
+ });
3050
+ });
3051
+ });
3052
+ });
3053
+ });
3054
+ }
3055
+ static _getResultTx(wallet, indexedAddresses, tx, opts) {
3056
+ let amountIn, amountOut, amountOutChange;
3057
+ let amount, action, addressTo;
3058
+ let inputs, outputs, foreignCrafted;
3059
+ const sum = (items, isMine, isChange = false) => {
3060
+ return items.filter(i => i.isMine == isMine && i.isChange == isChange).reduce((sum, i) => sum += i.amount, 0);
3061
+ };
3062
+ const classify = items => {
3063
+ return items.map(item => {
3064
+ const address = indexedAddresses[item.address];
3065
+ return {
3066
+ address: item.address,
3067
+ amount: item.amount,
3068
+ isMine: !!address,
3069
+ isChange: address ? address.isChange || wallet.singleAddress : false
3070
+ };
3071
+ });
3072
+ };
3073
+ if (tx.outputs.length || tx.inputs.length) {
3074
+ inputs = classify(tx.inputs);
3075
+ outputs = classify(tx.outputs);
3076
+ amountIn = sum(inputs, true);
3077
+ amountOut = sum(outputs, true, false);
3078
+ amountOutChange = sum(outputs, true, true);
3079
+ if (amountIn == amountOut + amountOutChange + (amountIn > 0 ? tx.fees : 0)) {
3080
+ amount = amountOut;
3081
+ action = 'moved';
3082
+ }
3083
+ else {
3084
+ amount = amountIn - amountOut - amountOutChange - (amountIn > 0 && amountOutChange > 0 ? tx.fees : 0);
3085
+ action = amount > 0 ? 'sent' : 'received';
3086
+ }
3087
+ amount = Math.abs(amount);
3088
+ if (action === 'sent' || action === 'moved') {
3089
+ const firstExternalOutput = outputs.find(o => o.isMine === false);
3090
+ addressTo = firstExternalOutput ? firstExternalOutput.address : null;
3091
+ }
3092
+ if (action == 'sent' && inputs.length !== inputs.filter(i => i.isMine).length) {
3093
+ foreignCrafted = true;
3094
+ }
3095
+ }
3096
+ else {
3097
+ action = 'invalid';
3098
+ amount = 0;
3099
+ }
3100
+ const newTx = {
3101
+ txid: tx.txid,
3102
+ action,
3103
+ amount,
3104
+ fees: tx.fees,
3105
+ time: tx.time,
3106
+ addressTo,
3107
+ confirmations: tx.confirmations,
3108
+ foreignCrafted,
3109
+ outputs: undefined,
3110
+ feePerKb: undefined,
3111
+ inputs: undefined
3112
+ };
3113
+ if (Utils.isNumber(tx.size) && tx.size > 0) {
3114
+ newTx.feePerKb = +((tx.fees * 1000) / tx.size).toFixed();
3115
+ }
3116
+ if (opts.includeExtendedInfo) {
3117
+ newTx.inputs = inputs.map(input => {
3118
+ return _.pick(input, 'address', 'amount', 'isMine');
3119
+ });
3120
+ newTx.outputs = outputs.map(output => {
3121
+ return _.pick(output, 'address', 'amount', 'isMine');
3122
+ });
3123
+ }
3124
+ else {
3125
+ outputs = outputs.filter(o => !o.isChange);
3126
+ if (action == 'received') {
3127
+ outputs = outputs.filter(o => o.isMine);
3128
+ }
3129
+ newTx.outputs = outputs.map(o => ({
3130
+ amount: o.amount,
3131
+ address: o.address
3132
+ }));
3133
+ }
3134
+ return newTx;
3135
+ }
3136
+ static _addProposalInfo(tx, indexedProposals, opts) {
3137
+ opts = opts || {};
3138
+ const proposal = indexedProposals[tx.txid];
3139
+ if (proposal) {
3140
+ tx.createdOn = proposal.createdOn;
3141
+ tx.proposalId = proposal.id;
3142
+ tx.proposalType = proposal.type;
3143
+ tx.creatorName = proposal.creatorName;
3144
+ tx.message = proposal.message;
3145
+ tx.nonce = proposal.nonce;
3146
+ tx.actions = proposal.actions.map(action => {
3147
+ return _.pick(action, ['createdOn', 'type', 'copayerId', 'copayerName', 'comment']);
3148
+ });
3149
+ for (const output of tx.outputs || []) {
3150
+ if (proposal.outputs) {
3151
+ const txpOut = proposal.outputs.find(o => o.toAddress === output.address && o.amount === output.amount);
3152
+ output.message = txpOut ? txpOut.message : null;
3153
+ }
3154
+ }
3155
+ tx.customData = proposal.customData;
3156
+ tx.createdOn = proposal.createdOn;
3157
+ if (opts.includeExtendedInfo) {
3158
+ tx.raw = proposal.raw;
3159
+ }
3160
+ }
3161
+ }
3162
+ static _addNotesInfo(tx, indexedNotes) {
3163
+ const note = indexedNotes[tx.txid];
3164
+ if (note) {
3165
+ tx.note = _.pick(note, ['body', 'editedBy', 'editedByName', 'editedOn']);
3166
+ }
3167
+ }
3168
+ createAdvert(opts, cb) {
3169
+ opts = opts ? _.clone(opts) : {};
3170
+ if (!checkRequired(opts, ['title'], cb)) {
3171
+ return;
3172
+ }
3173
+ const checkIfAdvertExistsAlready = (adId, cb) => {
3174
+ this.storage.fetchAdvert(opts.adId, (err, result) => {
3175
+ if (err)
3176
+ return cb(err);
3177
+ if (result) {
3178
+ return cb(errordefinitions_1.Errors.AD_ALREADY_EXISTS);
3179
+ }
3180
+ if (!result) {
3181
+ const x = new model_1.Advertisement();
3182
+ x.advertisementId = opts.advertisementId || uuid_1.default.v4();
3183
+ x.name = opts.name;
3184
+ x.title = opts.title;
3185
+ x.country = opts.country;
3186
+ x.type = opts.type;
3187
+ x.body = opts.body;
3188
+ x.imgUrl = opts.imgUrl;
3189
+ x.linkText = opts.linkText;
3190
+ x.linkUrl = opts.linkUrl;
3191
+ x.isAdActive = opts.isAdActive;
3192
+ x.dismissible = opts.dismissible;
3193
+ x.signature = opts.signature;
3194
+ x.app = opts.app;
3195
+ x.isTesting = opts.isTesting;
3196
+ return cb(null, x);
3197
+ }
3198
+ });
3199
+ };
3200
+ this._runLocked(cb, cb => {
3201
+ checkIfAdvertExistsAlready(opts.adId, (err, advert) => {
3202
+ if (err)
3203
+ throw err;
3204
+ if (advert) {
3205
+ this.storage.storeAdvert(advert, cb);
3206
+ }
3207
+ });
3208
+ }, 10 * 1000);
3209
+ }
3210
+ getAdvert(opts, cb) {
3211
+ this.storage.fetchAdvert(opts.adId, (err, advert) => {
3212
+ if (err)
3213
+ return cb(err);
3214
+ return cb(null, advert);
3215
+ });
3216
+ }
3217
+ getAdverts(opts, cb) {
3218
+ this.storage.fetchActiveAdverts((err, adverts) => {
3219
+ if (err)
3220
+ return cb(err);
3221
+ return cb(null, adverts);
3222
+ });
3223
+ }
3224
+ getAdvertsByCountry(opts, cb) {
3225
+ this.storage.fetchAdvertsByCountry(opts.country, (err, adverts) => {
3226
+ if (err)
3227
+ return cb(err);
3228
+ return cb(null, adverts);
3229
+ });
3230
+ }
3231
+ getTestingAdverts(opts, cb) {
3232
+ this.storage.fetchTestingAdverts((err, adverts) => {
3233
+ if (err)
3234
+ return cb(err);
3235
+ return cb(null, adverts);
3236
+ });
3237
+ }
3238
+ getAllAdverts(opts, cb) {
3239
+ this._runLocked(cb, cb => {
3240
+ this.getAllAdverts(opts, cb);
3241
+ });
3242
+ }
3243
+ removeAdvert(opts, cb) {
3244
+ opts = opts ? _.clone(opts) : {};
3245
+ if (!checkRequired(opts, ['adId'], cb)) {
3246
+ throw new Error('adId is missing');
3247
+ }
3248
+ const checkIfAdvertExistsAlready = (adId, cb) => {
3249
+ this.storage.fetchAdvert(opts.adId, (err, result) => {
3250
+ if (err)
3251
+ return cb(err);
3252
+ if (!result) {
3253
+ throw new Error('Advertisement does not exist: ' + opts.adId);
3254
+ }
3255
+ if (result) {
3256
+ this.logw('Advert already exists:', opts.adId);
3257
+ return cb(null, adId);
3258
+ }
3259
+ });
3260
+ };
3261
+ this._runLocked(cb, cb => {
3262
+ checkIfAdvertExistsAlready(opts.adId, (err, adId) => {
3263
+ if (err)
3264
+ throw err;
3265
+ this.storage.removeAdvert(adId, cb);
3266
+ });
3267
+ }, 10 * 1000);
3268
+ }
3269
+ activateAdvert(opts, cb) {
3270
+ opts = opts ? _.clone(opts) : {};
3271
+ if (!checkRequired(opts, ['adId'], cb)) {
3272
+ throw new Error('adId is missing');
3273
+ }
3274
+ this.storage.activateAdvert(opts.adId, (err, result) => {
3275
+ if (err)
3276
+ return cb(err);
3277
+ return cb(null, result);
3278
+ });
3279
+ }
3280
+ deactivateAdvert(opts, cb) {
3281
+ opts = opts ? _.clone(opts) : {};
3282
+ if (!checkRequired(opts, ['adId'], cb)) {
3283
+ throw new Error('adId is missing');
3284
+ }
3285
+ this.storage.deactivateAdvert(opts.adId, (err, result) => {
3286
+ if (err)
3287
+ return cb(err);
3288
+ return cb(null, result);
3289
+ });
3290
+ }
3291
+ tagLowFeeTxs(wallet, txs, cb) {
3292
+ const unconfirmed = txs.filter(tx => tx.confirmations === 0);
3293
+ if (!unconfirmed.length)
3294
+ return cb();
3295
+ this.getFeeLevels({
3296
+ chain: wallet.chain,
3297
+ network: wallet.network
3298
+ }, (err, levels) => {
3299
+ if (err) {
3300
+ this.logw('Could not fetch fee levels:', err);
3301
+ }
3302
+ else {
3303
+ const level = levels.find(l => l.level === 'superEconomy');
3304
+ if (!level || !level.nbBlocks) {
3305
+ this.logi('Cannot compute super economy fee level from blockchain');
3306
+ }
3307
+ else {
3308
+ const minFeePerKb = level.feePerKb;
3309
+ for (const tx of unconfirmed) {
3310
+ tx.lowFees = tx.feePerKb < minFeePerKb;
3311
+ }
3312
+ }
3313
+ }
3314
+ return cb();
3315
+ });
3316
+ }
3317
+ getTxHistoryV8(bc, wallet, opts, skip, limit, cb) {
3318
+ let bcHeight, bcHash, lastTxs, cacheStatus, resultTxs = [], fromCache = false;
3319
+ let txsToCache = [], fromBc;
3320
+ let streamData;
3321
+ let streamKey;
3322
+ let walletCacheKey = wallet.id;
3323
+ if (opts.tokenAddress) {
3324
+ wallet.tokenAddress = opts.tokenAddress;
3325
+ walletCacheKey = `${wallet.id}-${opts.tokenAddress}`;
3326
+ }
3327
+ if (opts.multisigContractAddress) {
3328
+ wallet.multisigContractAddress = opts.multisigContractAddress;
3329
+ walletCacheKey = `${wallet.id}-${opts.multisigContractAddress}`;
3330
+ }
3331
+ async.series([
3332
+ next => {
3333
+ this.syncWallet(wallet, next, true);
3334
+ },
3335
+ next => {
3336
+ this._getBlockchainHeight(wallet.chain, wallet.network, (err, height, hash) => {
3337
+ if (err)
3338
+ return next(err);
3339
+ bcHeight = height;
3340
+ bcHash = hash;
3341
+ streamKey = (this.userAgent || '') + '-' + limit + '-' + bcHash;
3342
+ return next();
3343
+ });
3344
+ },
3345
+ next => {
3346
+ this.storage.getTxHistoryCacheStatusV8(walletCacheKey, (err, inCacheStatus) => {
3347
+ if (err)
3348
+ return cb(err);
3349
+ cacheStatus = inCacheStatus;
3350
+ return next();
3351
+ });
3352
+ },
3353
+ next => {
3354
+ if (skip == 0 || !streamKey)
3355
+ return next();
3356
+ logger_1.default.debug('Checking streamKey/skip %o', { streamKey, skip });
3357
+ this.storage.getTxHistoryStreamV8(walletCacheKey, (err, result) => {
3358
+ if (err)
3359
+ return next(err);
3360
+ if (!result)
3361
+ return next();
3362
+ if (result.streamKey != streamKey) {
3363
+ logger_1.default.debug('Deleting old stream cache:' + result.streamKey);
3364
+ return this.storage.clearTxHistoryStreamV8(walletCacheKey, next);
3365
+ }
3366
+ streamData = result.items;
3367
+ logger_1.default.debug(`Using stream cache: ${streamData.length} txs`);
3368
+ return next();
3369
+ });
3370
+ },
3371
+ next => {
3372
+ if (streamData) {
3373
+ lastTxs = streamData;
3374
+ return next();
3375
+ }
3376
+ const startBlock = cacheStatus.updatedHeight || 0;
3377
+ logger_1.default.debug(' ########### GET HISTORY v8 startBlock/bcH] %o', { startBlock, bcHeight });
3378
+ bc.getTransactions(wallet, startBlock, (err, txs) => {
3379
+ if (err)
3380
+ return cb(err);
3381
+ const dustThreshold = index_1.ChainService.getDustAmountValue(wallet.chain);
3382
+ this._normalizeTxHistory(walletCacheKey, txs, dustThreshold, bcHeight, (err, inTxs) => {
3383
+ if (err)
3384
+ return cb(err);
3385
+ if (cacheStatus.tipTxId) {
3386
+ lastTxs = _.takeWhile(inTxs, tx => {
3387
+ return tx.txid != cacheStatus.tipTxId;
3388
+ });
3389
+ logger_1.default.info(`Storing stream cache for ${walletCacheKey}: ${lastTxs.length} txs`);
3390
+ return this.storage.storeTxHistoryStreamV8(walletCacheKey, streamKey, lastTxs, next);
3391
+ }
3392
+ lastTxs = inTxs;
3393
+ return next();
3394
+ });
3395
+ });
3396
+ },
3397
+ next => {
3398
+ if (lastTxs.length >= skip + limit) {
3399
+ resultTxs = lastTxs.slice(skip, skip + limit);
3400
+ fromCache = false;
3401
+ fromBc = true;
3402
+ return next();
3403
+ }
3404
+ if (lastTxs.length >= skip) {
3405
+ resultTxs = lastTxs.slice(skip);
3406
+ skip = 0;
3407
+ limit -= resultTxs.length;
3408
+ fromBc = resultTxs.length > 0;
3409
+ }
3410
+ else {
3411
+ skip -= lastTxs.length;
3412
+ }
3413
+ this.storage.getTxHistoryCacheV8(walletCacheKey, skip, limit, (err, oldTxs) => {
3414
+ if (err) {
3415
+ return next(err);
3416
+ }
3417
+ if (oldTxs.length) {
3418
+ fromCache = true;
3419
+ }
3420
+ for (const x of oldTxs) {
3421
+ if (x.blockheight > 0 && bcHeight >= x.blockheight) {
3422
+ x.confirmations = bcHeight - x.blockheight + 1;
3423
+ }
3424
+ }
3425
+ resultTxs = resultTxs.concat(oldTxs);
3426
+ return next();
3427
+ });
3428
+ },
3429
+ next => {
3430
+ if (streamData) {
3431
+ return next();
3432
+ }
3433
+ let CONFIRMATIONS_TO_START_CACHING = Defaults.CONFIRMATIONS_TO_START_CACHING;
3434
+ if (Constants.CONFIRMATIONS_TO_START_CACHING[wallet.chain] != null) {
3435
+ CONFIRMATIONS_TO_START_CACHING = Constants.CONFIRMATIONS_TO_START_CACHING[wallet.chain];
3436
+ }
3437
+ txsToCache = lastTxs.filter(i => {
3438
+ if (i.confirmations < CONFIRMATIONS_TO_START_CACHING) {
3439
+ return false;
3440
+ }
3441
+ if (!cacheStatus.tipHeight)
3442
+ return true;
3443
+ return i.blockheight > cacheStatus.tipHeight;
3444
+ });
3445
+ logger_1.default.debug(`Found ${lastTxs.length} new txs. Caching ${txsToCache.length}`);
3446
+ if (!txsToCache.length) {
3447
+ return next();
3448
+ }
3449
+ const updateHeight = bcHeight - CONFIRMATIONS_TO_START_CACHING;
3450
+ this.storage.storeTxHistoryCacheV8(walletCacheKey, cacheStatus.tipIndex, txsToCache, updateHeight, next);
3451
+ }
3452
+ ], err => {
3453
+ if (err)
3454
+ return cb(err);
3455
+ return cb(null, {
3456
+ items: resultTxs,
3457
+ fromCache,
3458
+ fromBc,
3459
+ useStream: !!streamData
3460
+ });
3461
+ });
3462
+ }
3463
+ getTxHistory(opts, cb) {
3464
+ opts = opts || {};
3465
+ opts.limit = !Utils.isNumber(opts.limit) ? 50 : Number(opts.limit);
3466
+ if (opts.limit > Defaults.HISTORY_LIMIT)
3467
+ return cb(errordefinitions_1.Errors.HISTORY_LIMIT_EXCEEDED);
3468
+ this.getWallet({}, (err, wallet) => {
3469
+ if (err)
3470
+ return cb(err);
3471
+ if (wallet.scanStatus == 'error')
3472
+ return cb(errordefinitions_1.Errors.WALLET_NEED_SCAN);
3473
+ if (wallet.scanStatus == 'running')
3474
+ return cb(errordefinitions_1.Errors.WALLET_BUSY);
3475
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
3476
+ if (!bc)
3477
+ return cb(new Error('Could not get blockchain explorer instance'));
3478
+ const from = opts.skip || 0;
3479
+ const to = from + opts.limit;
3480
+ async.waterfall([
3481
+ next => {
3482
+ this.getTxHistoryV8(bc, wallet, opts, from, opts.limit, next);
3483
+ },
3484
+ (txs, next) => {
3485
+ if (!txs || !txs.items?.length) {
3486
+ return next();
3487
+ }
3488
+ const minTs = _.minBy(txs.items, 'time').time - 7 * 24 * 3600;
3489
+ const maxTs = _.maxBy(txs.items, 'time').time + 1 * 24 * 3600;
3490
+ async.parallel([
3491
+ done => {
3492
+ this.storage.fetchTxs(this.walletId, {
3493
+ minTs,
3494
+ maxTs
3495
+ }, done);
3496
+ },
3497
+ done => {
3498
+ this.storage.fetchTxNotes(this.walletId, {
3499
+ minTs
3500
+ }, done);
3501
+ }
3502
+ ], (err, res) => {
3503
+ return next(err, {
3504
+ txs,
3505
+ txps: res[0],
3506
+ notes: res[1]
3507
+ });
3508
+ });
3509
+ }
3510
+ ], (err, res) => {
3511
+ if (err)
3512
+ return cb(err);
3513
+ if (!res)
3514
+ return cb(null, []);
3515
+ const indexedProposals = _.keyBy(res.txps, 'txid');
3516
+ const indexedNotes = _.keyBy(res.notes, 'txid');
3517
+ const finalTxs = res.txs.items.map(tx => {
3518
+ WalletService._addProposalInfo(tx, indexedProposals, opts);
3519
+ WalletService._addNotesInfo(tx, indexedNotes);
3520
+ return tx;
3521
+ });
3522
+ this.tagLowFeeTxs(wallet, finalTxs, err => {
3523
+ if (err)
3524
+ this.logw('Failed to tag unconfirmed with low fee:', err);
3525
+ if (res.txs.fromCache) {
3526
+ let p = '';
3527
+ if (res.txs.fromBc) {
3528
+ p = 'Partial';
3529
+ }
3530
+ this.logd(`${p} History from cache ${from}/${to}: ${finalTxs.length} txs`);
3531
+ }
3532
+ else {
3533
+ this.logd(`History from bc ${from}/${to}: ${finalTxs.length} txs`);
3534
+ }
3535
+ return cb(null, finalTxs, !!res.txs.fromCache, !!res.txs.useStream);
3536
+ });
3537
+ });
3538
+ });
3539
+ }
3540
+ scan(opts, cb) {
3541
+ opts = opts || {};
3542
+ opts.startingStep = opts.startingStep || 1000;
3543
+ this.getWallet({}, (err, wallet) => {
3544
+ if (err)
3545
+ return cb(err);
3546
+ if (!wallet.isComplete())
3547
+ return cb(errordefinitions_1.Errors.WALLET_NOT_COMPLETE);
3548
+ if (wallet.derivationStrategy === Constants.DERIVATION_STRATEGIES.BIP44) {
3549
+ opts.includeCopayerBranches = false;
3550
+ }
3551
+ if (opts.includeCopayerBranches) {
3552
+ opts.startingStep = 1;
3553
+ }
3554
+ this.storage.clearWalletCache(this.walletId, () => {
3555
+ if (wallet.singleAddress && index_1.ChainService.isUTXOChain(wallet.chain))
3556
+ return cb();
3557
+ this._runLocked(cb, cb => {
3558
+ wallet.scanStatus = 'running';
3559
+ this.storage.storeWallet(wallet, err => {
3560
+ if (err)
3561
+ return cb(err);
3562
+ const bc = this._getBlockchainExplorer(wallet.chain, wallet.network);
3563
+ if (!bc)
3564
+ return cb(new Error('Could not get blockchain explorer instance'));
3565
+ opts.bc = bc;
3566
+ const scanComplete = error => {
3567
+ this.storage.fetchWallet(wallet.id, (err, wallet) => {
3568
+ if (err)
3569
+ return cb(err);
3570
+ wallet.scanStatus = error ? 'error' : 'success';
3571
+ this.storage.storeWallet(wallet, err => {
3572
+ return cb(error || err);
3573
+ });
3574
+ });
3575
+ };
3576
+ if (!index_1.ChainService.isUTXOChain(wallet.chain)) {
3577
+ return this.syncWallet(wallet, scanComplete);
3578
+ }
3579
+ if (Number.isInteger(opts.startIdx)) {
3580
+ wallet.addressManager.receiveAddressIndex = opts.startIdx;
3581
+ wallet.addressManager.changeAddressIndex = opts.startIdx;
3582
+ }
3583
+ let step = opts.startingStep;
3584
+ async.doWhilst(next => {
3585
+ this._runScan(wallet, step, opts, next);
3586
+ }, () => {
3587
+ step = step / 10;
3588
+ return step >= 1;
3589
+ }, scanComplete);
3590
+ });
3591
+ });
3592
+ });
3593
+ });
3594
+ }
3595
+ _runScan(wallet, step, opts, cb) {
3596
+ const scanBranch = (wallet, derivator, cb) => {
3597
+ let inactiveCounter = 0;
3598
+ const allAddresses = [];
3599
+ let gap = Defaults.SCAN_ADDRESS_GAP;
3600
+ if (step > 1) {
3601
+ gap = Math.min(gap, 3);
3602
+ }
3603
+ async.whilst(() => {
3604
+ return inactiveCounter < gap;
3605
+ }, next => {
3606
+ const address = derivator.derive();
3607
+ opts.bc.getAddressActivity(address.address, (err, activity) => {
3608
+ if (err)
3609
+ return next(err);
3610
+ allAddresses.push(address);
3611
+ inactiveCounter = activity ? 0 : inactiveCounter + 1;
3612
+ return next();
3613
+ });
3614
+ }, err => {
3615
+ derivator.rewind(gap);
3616
+ return cb(err, allAddresses.slice(0, -gap));
3617
+ });
3618
+ };
3619
+ const derivators = [];
3620
+ for (const isChange of [false, true]) {
3621
+ derivators.push({
3622
+ id: wallet.addressManager.getBaseAddressPath(isChange),
3623
+ derive: () => wallet.createAddress(isChange, step),
3624
+ index: () => wallet.addressManager.getCurrentIndex(isChange),
3625
+ rewind: (n) => wallet.addressManager.rewindIndex(isChange, step, n),
3626
+ getSkippedAddress: () => wallet.getSkippedAddress()
3627
+ });
3628
+ if (opts.includeCopayerBranches) {
3629
+ for (const copayer of wallet.copayers) {
3630
+ if (copayer.addressManager) {
3631
+ derivators.push({
3632
+ id: copayer.addressManager.getBaseAddressPath(isChange),
3633
+ derive: () => copayer.createAddress(wallet, isChange),
3634
+ index: () => copayer.addressManager.getCurrentIndex(isChange),
3635
+ rewind: (n) => copayer.addressManager.rewindIndex(isChange, step, n)
3636
+ });
3637
+ }
3638
+ }
3639
+ }
3640
+ }
3641
+ async.eachSeries(derivators, (derivator, next) => {
3642
+ let addresses = [];
3643
+ scanBranch(wallet, derivator, (err, scannedAddresses) => {
3644
+ if (err)
3645
+ return next(err);
3646
+ addresses = addresses.concat(scannedAddresses);
3647
+ if (step > 1) {
3648
+ this.logd('Deriving addresses for scan steps gaps DERIVATOR:' + derivator.id);
3649
+ let addr;
3650
+ while ((addr = derivator.getSkippedAddress())) {
3651
+ addresses.push(addr);
3652
+ }
3653
+ }
3654
+ const reprocess = Number.isInteger(opts.startIdx);
3655
+ this._store(wallet, addresses, next, reprocess, reprocess);
3656
+ });
3657
+ }, cb);
3658
+ }
3659
+ startScan(opts, cb) {
3660
+ const scanFinished = err => {
3661
+ const data = {
3662
+ result: err ? 'error' : 'success',
3663
+ error: undefined
3664
+ };
3665
+ if (err)
3666
+ data.error = err;
3667
+ this._notify('ScanFinished', data, {
3668
+ isGlobal: true
3669
+ });
3670
+ };
3671
+ this.getWallet({}, (err, wallet) => {
3672
+ if (err)
3673
+ return cb(err);
3674
+ if (!wallet.isComplete())
3675
+ return cb(errordefinitions_1.Errors.WALLET_NOT_COMPLETE);
3676
+ if (wallet.singleAddress && index_1.ChainService.isUTXOChain(wallet.chain))
3677
+ return cb();
3678
+ setTimeout(() => {
3679
+ wallet.beRegistered = false;
3680
+ this.storage.deregisterWallet(wallet.id, () => {
3681
+ this.scan(opts, scanFinished);
3682
+ });
3683
+ }, 100);
3684
+ return cb(null, {
3685
+ started: true
3686
+ });
3687
+ });
3688
+ }
3689
+ getFiatRate(opts, cb) {
3690
+ if (!checkRequired(opts, ['code'], cb))
3691
+ return;
3692
+ this.fiatRateService.getRate(opts, (err, rate) => {
3693
+ if (err)
3694
+ return cb(err);
3695
+ return cb(null, rate);
3696
+ });
3697
+ }
3698
+ getFiatRates(opts, cb) {
3699
+ if (isNaN(opts.ts) || Array.isArray(opts.ts))
3700
+ return cb(new clienterror_1.ClientError('Invalid timestamp'));
3701
+ this.fiatRateService.getRates(opts, (err, rates) => {
3702
+ if (err)
3703
+ return cb(err);
3704
+ return cb(null, rates);
3705
+ });
3706
+ }
3707
+ getFiatRatesByCoin(opts, cb) {
3708
+ if (!checkRequired(opts, ['coin'], cb))
3709
+ return;
3710
+ if (isNaN(opts.ts) || Array.isArray(opts.ts))
3711
+ return cb(new clienterror_1.ClientError('Invalid timestamp'));
3712
+ this.fiatRateService.getRatesByCoin(opts, (err, rate) => {
3713
+ if (err)
3714
+ return cb(err);
3715
+ return cb(null, rate);
3716
+ });
3717
+ }
3718
+ getHistoricalRates(opts, cb) {
3719
+ if (!checkRequired(opts, ['code'], cb))
3720
+ return;
3721
+ this.fiatRateService.getHistoricalRates(opts, (err, rates) => {
3722
+ if (err)
3723
+ return cb(err);
3724
+ return cb(null, rates);
3725
+ });
3726
+ }
3727
+ pushNotificationsSubscribe(opts, cb) {
3728
+ if (!checkRequired(opts, ['token'], cb))
3729
+ return;
3730
+ const sub = model_1.PushNotificationSub.create({
3731
+ copayerId: this.copayerId,
3732
+ token: opts.token,
3733
+ packageName: opts.packageName,
3734
+ platform: opts.platform,
3735
+ walletId: opts.walletId
3736
+ });
3737
+ this.storage.storePushNotificationSub(sub, cb);
3738
+ }
3739
+ pushNotificationsBrazeSubscribe(opts, cb) {
3740
+ if (!checkRequired(opts, ['externalUserId'], cb))
3741
+ return;
3742
+ const sub = model_1.PushNotificationSub.create({
3743
+ copayerId: this.copayerId,
3744
+ externalUserId: opts.externalUserId,
3745
+ packageName: opts.packageName,
3746
+ platform: opts.platform,
3747
+ walletId: opts.walletId
3748
+ });
3749
+ this.storage.storePushNotificationBrazeSub(sub, cb);
3750
+ }
3751
+ pushNotificationsUnsubscribe(opts, cb) {
3752
+ if (!checkRequired(opts, ['token'], cb))
3753
+ return;
3754
+ this.storage.removePushNotificationSub(this.copayerId, opts.token, cb);
3755
+ }
3756
+ pushNotificationsBrazeUnsubscribe(opts, cb) {
3757
+ if (!checkRequired(opts, ['externalUserId'], cb))
3758
+ return;
3759
+ this.storage.removePushNotificationBrazeSub(this.copayerId, opts.externalUserId, cb);
3760
+ }
3761
+ txConfirmationSubscribe(opts, cb) {
3762
+ if (!checkRequired(opts, ['txid'], cb))
3763
+ return;
3764
+ const txids = Array.isArray(opts.txid) ? opts.txid : [opts.txid];
3765
+ for (const txid of txids) {
3766
+ const sub = model_1.TxConfirmationSub.create({
3767
+ copayerId: this.copayerId,
3768
+ walletId: this.walletId,
3769
+ txid,
3770
+ amount: opts.amount,
3771
+ isCreator: true
3772
+ });
3773
+ this.storage.storeTxConfirmationSub(sub, cb);
3774
+ }
3775
+ }
3776
+ txConfirmationUnsubscribe(opts, cb) {
3777
+ if (!checkRequired(opts, ['txid'], cb))
3778
+ return;
3779
+ this.storage.removeTxConfirmationSub(this.copayerId, opts.txid, cb);
3780
+ }
3781
+ getServicesData(opts, cb) {
3782
+ const externalServicesConfig = _.cloneDeep(config_1.default.services);
3783
+ const isLoggedIn = !!opts?.bitpayIdLocationCountry;
3784
+ const swapUsaBannedStates = ['HI', 'LA', 'NY'];
3785
+ if ((['US', 'USA'].includes(opts?.bitpayIdLocationCountry?.toUpperCase()) && swapUsaBannedStates.includes(opts?.bitpayIdLocationState?.toUpperCase())) ||
3786
+ (!isLoggedIn && ['US', 'USA'].includes(opts?.currentLocationCountry?.toUpperCase()) && swapUsaBannedStates.includes(opts?.currentLocationState?.toUpperCase()))) {
3787
+ externalServicesConfig.swapCrypto = { ...externalServicesConfig.swapCrypto, ...{ disabled: true, disabledMessage: 'Swaps are currently unavailable in your area.' } };
3788
+ }
3789
+ if (opts?.platform?.os === 'ios' && opts?.currentAppVersion === '14.11.5') {
3790
+ externalServicesConfig.swapCrypto = { ...externalServicesConfig.swapCrypto, ...{ disabled: true, disabledTitle: 'Unavailable', disabledMessage: 'Swaps are currently unavailable in your area.' } };
3791
+ }
3792
+ const buyCryptoUsaBannedStates = ['NY'];
3793
+ if ((['US', 'USA'].includes(opts?.bitpayIdLocationCountry?.toUpperCase()) && buyCryptoUsaBannedStates.includes(opts?.bitpayIdLocationState?.toUpperCase())) ||
3794
+ (!isLoggedIn && ['US', 'USA'].includes(opts?.currentLocationCountry?.toUpperCase()) && buyCryptoUsaBannedStates.includes(opts?.currentLocationState?.toUpperCase()))) {
3795
+ externalServicesConfig.buyCrypto = { ...externalServicesConfig.buyCrypto, ...{ disabled: true, disabledTitle: 'Unavailable', disabledMessage: 'This service is currently unavailable in your area.' } };
3796
+ }
3797
+ const sellCryptoUsaBannedStates = ['NY'];
3798
+ if ((['US', 'USA'].includes(opts?.bitpayIdLocationCountry?.toUpperCase()) && sellCryptoUsaBannedStates.includes(opts?.bitpayIdLocationState?.toUpperCase())) ||
3799
+ (!isLoggedIn && ['US', 'USA'].includes(opts?.currentLocationCountry?.toUpperCase()) && sellCryptoUsaBannedStates.includes(opts?.currentLocationState?.toUpperCase()))) {
3800
+ externalServicesConfig.sellCrypto = { ...externalServicesConfig.sellCrypto, ...{ disabled: true, disabledTitle: 'Unavailable', disabledMessage: 'This service is currently unavailable in your area.' } };
3801
+ }
3802
+ return cb(null, externalServicesConfig);
3803
+ }
3804
+ checkServiceAvailability(req) {
3805
+ if (!checkRequired(req.body, ['service', 'opts'])) {
3806
+ throw new clienterror_1.ClientError('checkServiceAvailability request missing arguments');
3807
+ }
3808
+ let serviceEnabled;
3809
+ switch (req.body.service) {
3810
+ case '1inch':
3811
+ if (req.body.opts?.country?.toUpperCase() === 'US') {
3812
+ serviceEnabled = false;
3813
+ }
3814
+ else {
3815
+ serviceEnabled = true;
3816
+ }
3817
+ break;
3818
+ default:
3819
+ serviceEnabled = true;
3820
+ break;
3821
+ }
3822
+ return serviceEnabled;
3823
+ }
3824
+ getSpenderApprovalWhitelist(cb) {
3825
+ if (Services.ERC20_SPENDER_APPROVAL_WHITELIST) {
3826
+ return cb(null, Services.ERC20_SPENDER_APPROVAL_WHITELIST);
3827
+ }
3828
+ else {
3829
+ return cb(new Error('Could not get ERC20 spender approval whitelist'));
3830
+ }
3831
+ }
3832
+ clearWalletCache(opts) {
3833
+ return new Promise(resolve => {
3834
+ const cacheKey = this.walletId + (opts.tokenAddress ? '-' + opts.tokenAddress : '');
3835
+ this.storage.clearWalletCache(cacheKey, () => {
3836
+ resolve(true);
3837
+ });
3838
+ });
3839
+ }
3840
+ static upgradeNeeded(paths, opts) {
3841
+ paths = Array.isArray(paths) ? paths : [paths];
3842
+ const chain = opts.chain?.toLowerCase();
3843
+ const v = Utils.parseVersion(opts.clientVersion);
3844
+ let result = false;
3845
+ for (const path of paths) {
3846
+ switch (path) {
3847
+ case exports.UPGRADES.SOL_bwc_$lt_10_10_12:
3848
+ result = (chain === 'sol' &&
3849
+ v?.agent === 'bwc' &&
3850
+ (v?.major < 10 ||
3851
+ (v?.major == 10 && v?.minor < 10) ||
3852
+ (v?.major == 10 && v?.minor == 10 && v?.patch < 12)));
3853
+ break;
3854
+ case exports.UPGRADES.BCH_bwc_$lt_8_3_multisig:
3855
+ result = (opts.n > 1 &&
3856
+ chain === 'bch' &&
3857
+ v?.agent === 'bwc' &&
3858
+ (v?.major < 8 ||
3859
+ (v.major == 8 && v?.minor < 3)))
3860
+ ? 'BWC clients < 8.3 are no longer supported for multisig BCH wallets.'
3861
+ : false;
3862
+ break;
3863
+ case exports.UPGRADES.bwc_$lt_8_4_multisig_purpose48:
3864
+ result = (opts.n > 1 &&
3865
+ opts.usePurpose48 &&
3866
+ v?.agent === 'bwc' &&
3867
+ (v?.major < 8 || (v.major == 8 && v?.minor < 4)));
3868
+ break;
3869
+ case exports.UPGRADES.bwc_$lt_8_17_multisig_p2wsh:
3870
+ result = (opts.n > 1 &&
3871
+ opts.addressType?.toLowerCase() === 'p2wsh' &&
3872
+ v?.agent === 'bwc' &&
3873
+ (v?.major < 8 || (v.major == 8 && v?.minor < 17)));
3874
+ break;
3875
+ case exports.UPGRADES.version_$gt_maxTxpVersion:
3876
+ result = parseInt(opts.version) > parseInt(opts.maxTxpVersion);
3877
+ break;
3878
+ case exports.UPGRADES.BCH_schnorr:
3879
+ result = (opts.signingMethod === 'schnorr' && !opts.supportBchSchnorr);
3880
+ break;
3881
+ case exports.UPGRADES.bwc_$lt_1_2:
3882
+ result = (v?.agent === 'bwc' &&
3883
+ (v?.major == 0 || (v?.major == 1 && v?.minor < 2)))
3884
+ ? 'BWC clients < 1.2 are no longer supported.'
3885
+ : false;
3886
+ break;
3887
+ default:
3888
+ throw new Error('Unknown upgrade path');
3889
+ }
3890
+ if (result) {
3891
+ logger_1.default.warn(`Upgrade needed: ${path} | ${opts.clientVersion} | ${opts.userAgent}`);
3892
+ break;
3893
+ }
3894
+ }
3895
+ return result;
3896
+ }
3897
+ _upgradeNeeded(paths, opts) {
3898
+ opts = opts || {};
3899
+ const _opts = {
3900
+ ...opts,
3901
+ clientVersion: this.clientVersion,
3902
+ userAgent: this.userAgent
3903
+ };
3904
+ return WalletService.upgradeNeeded(paths, _opts);
3905
+ }
3906
+ moralisGetWalletTokenBalances(req) {
3907
+ return new Promise(async (resolve, reject) => {
3908
+ try {
3909
+ const response = await moralis_1.default.EvmApi.token.getWalletTokenBalances({
3910
+ address: req.body.address,
3911
+ chain: req.body.chain,
3912
+ toBlock: req.body.toBlock,
3913
+ tokenAddresses: req.body.tokenAddresses,
3914
+ excludeSpam: req.body.excludeSpam,
3915
+ });
3916
+ return resolve(response.raw ?? response);
3917
+ }
3918
+ catch (err) {
3919
+ reject(err);
3920
+ }
3921
+ });
3922
+ }
3923
+ moralisGetTokenAllowance(req) {
3924
+ return new Promise((resolve, reject) => {
3925
+ if (!config_1.default.moralis)
3926
+ return reject(new Error('Moralis missing credentials'));
3927
+ if (!checkRequired(req.body, ['address']) && !checkRequired(req.body, ['ownerAddress'])) {
3928
+ return reject(new clienterror_1.ClientError('moralisGetTokenAllowance request missing arguments'));
3929
+ }
3930
+ const walletAddress = req.body.ownerAddress ?? req.body.address;
3931
+ const headers = {
3932
+ 'Accept': 'application/json',
3933
+ 'Content-Type': 'application/json',
3934
+ 'X-Api-Key': config_1.default.moralis.apiKey,
3935
+ };
3936
+ const qs = [];
3937
+ if (req.body.chain) {
3938
+ const chain = req.body.chain;
3939
+ const formattedChain = typeof chain === 'number' && Number.isInteger(chain)
3940
+ ? `0x${chain.toString(16)}`
3941
+ : chain;
3942
+ qs.push(`chain=${formattedChain}`);
3943
+ }
3944
+ if (req.body.cursor)
3945
+ qs.push('cursor=' + req.body.cursor);
3946
+ if (req.body.limit)
3947
+ qs.push('limit=' + req.body.limit);
3948
+ const URL = `https://deep-index.moralis.io/api/v2.2/wallets/${walletAddress}/approvals${qs.length > 0 ? '?' + qs.join('&') : ''}`;
3949
+ this.request.get(URL, {
3950
+ headers,
3951
+ json: true
3952
+ }, (err, data) => {
3953
+ if (err) {
3954
+ return reject(err.body ?? err);
3955
+ }
3956
+ else {
3957
+ const { spenderAddress, ownerAddress, address } = req.body;
3958
+ if (spenderAddress && ownerAddress) {
3959
+ const spendersList = data?.body?.result;
3960
+ if (Array.isArray(spendersList)) {
3961
+ const spenderData = spendersList.find(s => s.spender?.address?.toLowerCase() === spenderAddress.toLowerCase() &&
3962
+ s.token?.address?.toLowerCase() === address.toLowerCase());
3963
+ data.body = {
3964
+ allowance: spenderData?.value ?? '0'
3965
+ };
3966
+ }
3967
+ }
3968
+ return resolve(data.body ?? data);
3969
+ }
3970
+ });
3971
+ });
3972
+ }
3973
+ moralisGetNativeBalance(req) {
3974
+ return new Promise(async (resolve, reject) => {
3975
+ try {
3976
+ const response = await moralis_1.default.EvmApi.balance.getNativeBalance({
3977
+ address: req.body.address,
3978
+ chain: req.body.chain,
3979
+ toBlock: req.body.toBlock,
3980
+ });
3981
+ return resolve(response.raw ?? response);
3982
+ }
3983
+ catch (err) {
3984
+ reject(err);
3985
+ }
3986
+ });
3987
+ }
3988
+ moralisGetTokenPrice(req) {
3989
+ return new Promise(async (resolve, reject) => {
3990
+ try {
3991
+ const response = await moralis_1.default.EvmApi.token.getTokenPrice({
3992
+ address: req.body.address,
3993
+ chain: req.body.chain,
3994
+ include: req.body.include,
3995
+ exchange: req.body.exchange,
3996
+ toBlock: req.body.toBlock,
3997
+ });
3998
+ return resolve(response.raw ?? response);
3999
+ }
4000
+ catch (err) {
4001
+ reject(err);
4002
+ }
4003
+ });
4004
+ }
4005
+ moralisGetMultipleERC20TokenPrices(req) {
4006
+ return new Promise(async (resolve, reject) => {
4007
+ try {
4008
+ const response = await moralis_1.default.EvmApi.token.getMultipleTokenPrices({
4009
+ chain: req.body.chain,
4010
+ include: req.body.include,
4011
+ }, {
4012
+ tokens: req.body.tokens,
4013
+ });
4014
+ return resolve(response.raw ?? response);
4015
+ }
4016
+ catch (err) {
4017
+ reject(err);
4018
+ }
4019
+ });
4020
+ }
4021
+ moralisGetERC20TokenBalancesWithPricesByWallet(req) {
4022
+ return new Promise((resolve, reject) => {
4023
+ if (!config_1.default.moralis)
4024
+ return reject(new Error('Moralis missing credentials'));
4025
+ if (!checkRequired(req.body, ['address'])) {
4026
+ return reject(new clienterror_1.ClientError('moralisGetERC20TokenBalancesWithPricesByWallet request missing arguments'));
4027
+ }
4028
+ const headers = {
4029
+ 'Accept': 'application/json',
4030
+ 'Content-Type': 'application/json',
4031
+ 'X-Api-Key': config_1.default.moralis.apiKey,
4032
+ };
4033
+ const qs = [];
4034
+ if (req.body.chain)
4035
+ qs.push('chain=' + req.body.chain);
4036
+ if (req.body.toBlock)
4037
+ qs.push('to_block=' + req.body.toBlock);
4038
+ if (req.body.tokenAddresses)
4039
+ qs.push('token_addresses=' + req.body.tokenAddresses);
4040
+ if (req.body.excludeSpam)
4041
+ qs.push('exclude_spam=' + req.body.excludeSpam);
4042
+ if (req.body.cursor)
4043
+ qs.push('cursor=' + req.body.cursor);
4044
+ if (req.body.limit)
4045
+ qs.push('limit=' + req.body.limit);
4046
+ if (req.body.excludeNative)
4047
+ qs.push('exclude_native=' + req.body.excludeNative);
4048
+ const URL = `https://deep-index.moralis.io/api/v2.2/wallets/${req.body.address}/tokens${qs.length > 0 ? '?' + qs.join('&') : ''}`;
4049
+ this.request.get(URL, {
4050
+ headers,
4051
+ json: true
4052
+ }, (err, data) => {
4053
+ if (err) {
4054
+ return reject(err.body ?? err);
4055
+ }
4056
+ else {
4057
+ return resolve(data.body ?? data);
4058
+ }
4059
+ });
4060
+ });
4061
+ }
4062
+ moralisGetSolWalletPortfolio(req) {
4063
+ return new Promise(async (resolve, reject) => {
4064
+ let network;
4065
+ const chain = req.body.network ?? req.body.chain ?? undefined;
4066
+ const formattedChain = typeof chain === 'number' && Number.isInteger(chain)
4067
+ ? `0x${chain.toString(16)}`
4068
+ : chain;
4069
+ switch (formattedChain) {
4070
+ case '0x65':
4071
+ case 'devnet':
4072
+ network = 'devnet';
4073
+ break;
4074
+ case '0x66':
4075
+ case 'testnet':
4076
+ network = 'testnet';
4077
+ break;
4078
+ default:
4079
+ network = 'mainnet';
4080
+ break;
4081
+ }
4082
+ try {
4083
+ const response = await moralis_1.default.SolApi.account.getPortfolio({
4084
+ address: req.body.address,
4085
+ network,
4086
+ });
4087
+ return resolve(response.raw ?? response);
4088
+ }
4089
+ catch (err) {
4090
+ reject(err);
4091
+ }
4092
+ });
4093
+ }
4094
+ }
4095
+ exports.WalletService = WalletService;
4096
+ function checkRequired(obj, args, cb) {
4097
+ const missing = Utils.getMissingFields(obj, args);
4098
+ if (!missing.length) {
4099
+ return true;
4100
+ }
4101
+ if (typeof cb === 'function') {
4102
+ return cb(new clienterror_1.ClientError('Required argument: ' + missing[0] + ' missing.'));
4103
+ }
4104
+ return false;
4105
+ }
4106
+ exports.UPGRADES = {
4107
+ SOL_bwc_$lt_10_10_12: 'SOL:bwc<10.10.12',
4108
+ BCH_bwc_$lt_8_3_multisig: 'BCH:bwc<8.3:multisig',
4109
+ bwc_$lt_8_4_multisig_purpose48: 'bwc<8.4:multisig:purpose48',
4110
+ bwc_$lt_8_17_multisig_p2wsh: 'bwc<8.17:multisig:p2wsh',
4111
+ version_$gt_maxTxpVersion: 'version>maxTxpVersion',
4112
+ BCH_schnorr: 'BCH:schnorr',
4113
+ bwc_$lt_1_2: 'bwc<1.2',
4114
+ };
4115
+ //# sourceMappingURL=server.js.map