@bsv/wallet-toolbox 1.6.22 → 1.6.24

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 (212) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/docs/client.md +300 -167
  3. package/docs/monitor.md +126 -23
  4. package/docs/services.md +86 -37
  5. package/docs/wallet.md +300 -167
  6. package/mobile/out/src/CWIStyleWalletManager.d.ts +1 -0
  7. package/mobile/out/src/CWIStyleWalletManager.d.ts.map +1 -1
  8. package/mobile/out/src/CWIStyleWalletManager.js +4 -2
  9. package/mobile/out/src/CWIStyleWalletManager.js.map +1 -1
  10. package/mobile/out/src/index.mobile.d.ts +1 -1
  11. package/mobile/out/src/index.mobile.js +1 -1
  12. package/mobile/out/src/monitor/Monitor.d.ts +32 -8
  13. package/mobile/out/src/monitor/Monitor.d.ts.map +1 -1
  14. package/mobile/out/src/monitor/Monitor.js +59 -28
  15. package/mobile/out/src/monitor/Monitor.js.map +1 -1
  16. package/mobile/out/src/monitor/tasks/TaskCheckNoSends.js +2 -1
  17. package/mobile/out/src/monitor/tasks/TaskCheckNoSends.js.map +1 -1
  18. package/mobile/out/src/monitor/tasks/TaskClock.js +3 -2
  19. package/mobile/out/src/monitor/tasks/TaskClock.js.map +1 -1
  20. package/mobile/out/src/monitor/tasks/TaskMonitorCallHistory.js +2 -1
  21. package/mobile/out/src/monitor/tasks/TaskMonitorCallHistory.js.map +1 -1
  22. package/mobile/out/src/monitor/tasks/TaskNewHeader.js +2 -1
  23. package/mobile/out/src/monitor/tasks/TaskNewHeader.js.map +1 -1
  24. package/mobile/out/src/monitor/tasks/TaskReorg.d.ts +47 -0
  25. package/mobile/out/src/monitor/tasks/TaskReorg.d.ts.map +1 -0
  26. package/mobile/out/src/monitor/tasks/TaskReorg.js +135 -0
  27. package/mobile/out/src/monitor/tasks/TaskReorg.js.map +1 -0
  28. package/mobile/out/src/monitor/tasks/TaskSendWaiting.js +2 -1
  29. package/mobile/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
  30. package/mobile/out/src/monitor/tasks/TaskUnFail.js +2 -1
  31. package/mobile/out/src/monitor/tasks/TaskUnFail.js.map +1 -1
  32. package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts +1 -1
  33. package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts.map +1 -1
  34. package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts +4 -0
  35. package/mobile/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts.map +1 -1
  36. package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.d.ts.map +1 -1
  37. package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.js +3 -1
  38. package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
  39. package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.d.ts.map +1 -1
  40. package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js +4 -1
  41. package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js.map +1 -1
  42. package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
  43. package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +3 -1
  44. package/mobile/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
  45. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts +5 -0
  46. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts.map +1 -0
  47. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js +68 -0
  48. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js.map +1 -0
  49. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts +2 -1
  50. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts.map +1 -1
  51. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js +59 -15
  52. package/mobile/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js.map +1 -1
  53. package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts +1 -1
  54. package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts.map +1 -1
  55. package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js +4 -61
  56. package/mobile/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js.map +1 -1
  57. package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts +13 -0
  58. package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts.map +1 -0
  59. package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js +27 -0
  60. package/mobile/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -0
  61. package/mobile/out/src/services/chaintracker/chaintracks/index.client.d.ts +2 -28
  62. package/mobile/out/src/services/chaintracker/chaintracks/index.client.d.ts.map +1 -1
  63. package/mobile/out/src/services/chaintracker/chaintracks/index.client.js +2 -50
  64. package/mobile/out/src/services/chaintracker/chaintracks/index.client.js.map +1 -1
  65. package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.d.ts +30 -0
  66. package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.d.ts.map +1 -0
  67. package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.js +68 -0
  68. package/mobile/out/src/services/chaintracker/chaintracks/index.mobile.js.map +1 -0
  69. package/mobile/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js +11 -11
  70. package/mobile/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js.map +1 -1
  71. package/mobile/out/src/storage/methods/createAction.d.ts.map +1 -1
  72. package/mobile/out/src/storage/methods/createAction.js.map +1 -1
  73. package/mobile/package-lock.json +7 -6
  74. package/mobile/package.json +2 -2
  75. package/out/src/CWIStyleWalletManager.d.ts +1 -0
  76. package/out/src/CWIStyleWalletManager.d.ts.map +1 -1
  77. package/out/src/CWIStyleWalletManager.js +4 -2
  78. package/out/src/CWIStyleWalletManager.js.map +1 -1
  79. package/out/src/index.mobile.d.ts +1 -1
  80. package/out/src/index.mobile.js +1 -1
  81. package/out/src/monitor/Monitor.d.ts +32 -8
  82. package/out/src/monitor/Monitor.d.ts.map +1 -1
  83. package/out/src/monitor/Monitor.js +59 -28
  84. package/out/src/monitor/Monitor.js.map +1 -1
  85. package/out/src/monitor/MonitorDaemon.d.ts +2 -0
  86. package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
  87. package/out/src/monitor/MonitorDaemon.js +3 -1
  88. package/out/src/monitor/MonitorDaemon.js.map +1 -1
  89. package/out/src/monitor/__test/MonitorDaemon.man.test.js +30 -39
  90. package/out/src/monitor/__test/MonitorDaemon.man.test.js.map +1 -1
  91. package/out/src/monitor/tasks/TaskCheckNoSends.js +2 -1
  92. package/out/src/monitor/tasks/TaskCheckNoSends.js.map +1 -1
  93. package/out/src/monitor/tasks/TaskClock.js +3 -2
  94. package/out/src/monitor/tasks/TaskClock.js.map +1 -1
  95. package/out/src/monitor/tasks/TaskMonitorCallHistory.js +2 -1
  96. package/out/src/monitor/tasks/TaskMonitorCallHistory.js.map +1 -1
  97. package/out/src/monitor/tasks/TaskNewHeader.js +2 -1
  98. package/out/src/monitor/tasks/TaskNewHeader.js.map +1 -1
  99. package/out/src/monitor/tasks/TaskReorg.d.ts +47 -0
  100. package/out/src/monitor/tasks/TaskReorg.d.ts.map +1 -0
  101. package/out/src/monitor/tasks/TaskReorg.js +135 -0
  102. package/out/src/monitor/tasks/TaskReorg.js.map +1 -0
  103. package/out/src/monitor/tasks/TaskSendWaiting.js +2 -1
  104. package/out/src/monitor/tasks/TaskSendWaiting.js.map +1 -1
  105. package/out/src/monitor/tasks/TaskUnFail.js +2 -1
  106. package/out/src/monitor/tasks/TaskUnFail.js.map +1 -1
  107. package/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts +1 -1
  108. package/out/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.d.ts.map +1 -1
  109. package/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts +4 -0
  110. package/out/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.d.ts.map +1 -1
  111. package/out/src/services/chaintracker/chaintracks/Chaintracks.d.ts.map +1 -1
  112. package/out/src/services/chaintracker/chaintracks/Chaintracks.js +3 -1
  113. package/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
  114. package/out/src/services/chaintracker/chaintracks/ChaintracksService.js +1 -1
  115. package/out/src/services/chaintracker/chaintracks/ChaintracksService.js.map +1 -1
  116. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.d.ts.map +1 -1
  117. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js +4 -1
  118. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.js.map +1 -1
  119. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
  120. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +3 -1
  121. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
  122. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.d.ts.map +1 -1
  123. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js +3 -1
  124. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.js.map +1 -1
  125. package/out/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.js +1 -1
  126. package/out/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.js.map +1 -1
  127. package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts +5 -0
  128. package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.d.ts.map +1 -0
  129. package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js +68 -0
  130. package/out/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.js.map +1 -0
  131. package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.d.ts +2 -1
  132. package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.d.ts.map +1 -1
  133. package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.js +66 -22
  134. package/out/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.js.map +1 -1
  135. package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts +2 -1
  136. package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.d.ts.map +1 -1
  137. package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js +59 -15
  138. package/out/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.js.map +1 -1
  139. package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts +1 -1
  140. package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.d.ts.map +1 -1
  141. package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js +4 -61
  142. package/out/src/services/chaintracker/chaintracks/createIdbChaintracks.js.map +1 -1
  143. package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.d.ts +14 -0
  144. package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.d.ts.map +1 -0
  145. package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.js +27 -0
  146. package/out/src/services/chaintracker/chaintracks/createKnexChaintracks.js.map +1 -0
  147. package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts +13 -0
  148. package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.d.ts.map +1 -0
  149. package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js +27 -0
  150. package/out/src/services/chaintracker/chaintracks/createNoDbChaintracks.js.map +1 -0
  151. package/out/src/services/chaintracker/chaintracks/index.all.d.ts +1 -0
  152. package/out/src/services/chaintracker/chaintracks/index.all.d.ts.map +1 -1
  153. package/out/src/services/chaintracker/chaintracks/index.all.js +1 -0
  154. package/out/src/services/chaintracker/chaintracks/index.all.js.map +1 -1
  155. package/out/src/services/chaintracker/chaintracks/index.client.d.ts +2 -28
  156. package/out/src/services/chaintracker/chaintracks/index.client.d.ts.map +1 -1
  157. package/out/src/services/chaintracker/chaintracks/index.client.js +2 -50
  158. package/out/src/services/chaintracker/chaintracks/index.client.js.map +1 -1
  159. package/out/src/services/chaintracker/chaintracks/index.mobile.d.ts +30 -0
  160. package/out/src/services/chaintracker/chaintracks/index.mobile.d.ts.map +1 -0
  161. package/out/src/services/chaintracker/chaintracks/index.mobile.js +68 -0
  162. package/out/src/services/chaintracker/chaintracks/index.mobile.js.map +1 -0
  163. package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js +11 -11
  164. package/out/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.js.map +1 -1
  165. package/out/src/services/chaintracker/index.mobile.d.ts +4 -0
  166. package/out/src/services/chaintracker/index.mobile.d.ts.map +1 -0
  167. package/out/src/services/chaintracker/index.mobile.js +20 -0
  168. package/out/src/services/chaintracker/index.mobile.js.map +1 -0
  169. package/out/src/storage/methods/createAction.d.ts.map +1 -1
  170. package/out/src/storage/methods/createAction.js.map +1 -1
  171. package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
  172. package/out/src/storage/schema/KnexMigrations.js +12 -0
  173. package/out/src/storage/schema/KnexMigrations.js.map +1 -1
  174. package/out/test/monitor/Monitor.test.js +32 -29
  175. package/out/test/monitor/Monitor.test.js.map +1 -1
  176. package/out/tsconfig.all.tsbuildinfo +1 -1
  177. package/package.json +5 -4
  178. package/src/CWIStyleWalletManager.ts +14 -4
  179. package/src/index.mobile.ts +1 -1
  180. package/src/monitor/Monitor.ts +94 -29
  181. package/src/monitor/MonitorDaemon.ts +9 -1
  182. package/src/monitor/__test/MonitorDaemon.man.test.ts +35 -7
  183. package/src/monitor/tasks/TaskCheckNoSends.ts +1 -1
  184. package/src/monitor/tasks/TaskClock.ts +2 -2
  185. package/src/monitor/tasks/TaskMonitorCallHistory.ts +1 -1
  186. package/src/monitor/tasks/TaskNewHeader.ts +1 -1
  187. package/src/monitor/tasks/TaskReorg.ts +139 -0
  188. package/src/monitor/tasks/TaskSendWaiting.ts +3 -3
  189. package/src/monitor/tasks/TaskUnFail.ts +1 -1
  190. package/src/services/chaintracker/chaintracks/Api/ChaintracksClientApi.ts +6 -1
  191. package/src/services/chaintracker/chaintracks/Api/ChaintracksStorageApi.ts +4 -0
  192. package/src/services/chaintracker/chaintracks/Chaintracks.ts +3 -1
  193. package/src/services/chaintracker/chaintracks/ChaintracksService.ts +2 -2
  194. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageIdb.ts +4 -1
  195. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.ts +4 -12
  196. package/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageNoDb.ts +3 -1
  197. package/src/services/chaintracker/chaintracks/__tests/Chaintracks.test.ts +2 -2
  198. package/src/services/chaintracker/chaintracks/createDefaultIdbChaintracksOptions.ts +92 -0
  199. package/src/services/chaintracker/chaintracks/createDefaultKnexChaintracksOptions.ts +84 -25
  200. package/src/services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions.ts +79 -17
  201. package/src/services/chaintracker/chaintracks/createIdbChaintracks.ts +11 -64
  202. package/src/services/chaintracker/chaintracks/createKnexChaintracks.ts +65 -0
  203. package/src/services/chaintracker/chaintracks/createNoDbChaintracks.ts +60 -0
  204. package/src/services/chaintracker/chaintracks/index.all.ts +1 -0
  205. package/src/services/chaintracker/chaintracks/index.client.ts +2 -35
  206. package/src/services/chaintracker/chaintracks/index.mobile.ts +37 -0
  207. package/src/services/chaintracker/chaintracks/util/validBulkHeaderFilesByFileHash.ts +11 -11
  208. package/src/services/chaintracker/index.mobile.ts +4 -0
  209. package/src/storage/methods/createAction.ts +6 -1
  210. package/src/storage/schema/KnexMigrations.ts +13 -0
  211. package/syncVersions.js +71 -0
  212. package/test/monitor/Monitor.test.ts +21 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/wallet-toolbox",
3
- "version": "1.6.22",
3
+ "version": "1.6.24",
4
4
  "description": "BRC100 conforming wallet, wallet storage and wallet signer components",
5
5
  "main": "./out/src/index.js",
6
6
  "types": "./out/src/index.d.ts",
@@ -22,8 +22,9 @@
22
22
  "test:coverage": "npm run build && jest --testPathIgnorePatterns=man.test.ts --coverage",
23
23
  "lint": "prettier --write 'src/**/*.ts' --write 'test/**/*.ts' --log-level silent",
24
24
  "build": "tsc --build",
25
- "prepublish": "npm run lint && npm run build && npm run doc",
26
- "doc": "ts2md"
25
+ "prepublish": "npm run lint && npm run build && npm run doc && npm run sync-versions",
26
+ "doc": "ts2md",
27
+ "sync-versions": "node syncVersions.js"
27
28
  },
28
29
  "bugs": {
29
30
  "url": "https://github.com/bsv-blockchain/wallet-toolbox/issues"
@@ -32,7 +33,7 @@
32
33
  "dependencies": {
33
34
  "@bsv/auth-express-middleware": "^1.2.3",
34
35
  "@bsv/payment-express-middleware": "^1.2.3",
35
- "@bsv/sdk": "^1.7.3",
36
+ "@bsv/sdk": "^1.7.6",
36
37
  "express": "^4.21.2",
37
38
  "idb": "^8.0.2",
38
39
  "knex": "^3.1.0",
@@ -61,7 +61,9 @@ import {
61
61
  Transaction,
62
62
  PushDrop,
63
63
  CreateActionInput,
64
- SHIPBroadcaster
64
+ SHIPBroadcaster,
65
+ BigNumber,
66
+ Curve
65
67
  } from '@bsv/sdk'
66
68
  import { PrivilegedKeyManager } from './sdk/PrivilegedKeyManager'
67
69
 
@@ -1065,7 +1067,13 @@ export class CWIStyleWalletManager implements WalletInterface {
1065
1067
  * Lists all available profiles, including the default profile.
1066
1068
  * @returns Array of profile info objects, including an 'active' flag.
1067
1069
  */
1068
- listProfiles(): Array<{ id: number[]; name: string; createdAt: number | null; active: boolean }> {
1070
+ listProfiles(): Array<{
1071
+ id: number[]
1072
+ name: string
1073
+ createdAt: number | null
1074
+ active: boolean
1075
+ identityKey: string
1076
+ }> {
1069
1077
  if (!this.authenticated) {
1070
1078
  throw new Error('Not authenticated.')
1071
1079
  }
@@ -1075,14 +1083,16 @@ export class CWIStyleWalletManager implements WalletInterface {
1075
1083
  id: DEFAULT_PROFILE_ID,
1076
1084
  name: 'default',
1077
1085
  createdAt: null, // Default profile doesn't have a creation timestamp in the same way
1078
- active: this.activeProfileId.every(x => x === 0)
1086
+ active: this.activeProfileId.every(x => x === 0),
1087
+ identityKey: new PrivateKey(this.rootPrimaryKey).toPublicKey().toString()
1079
1088
  },
1080
1089
  // Other profiles
1081
1090
  ...this.profiles.map(p => ({
1082
1091
  id: p.id,
1083
1092
  name: p.name,
1084
1093
  createdAt: p.createdAt,
1085
- active: this.activeProfileId.every((x, i) => x === p.id[i])
1094
+ active: this.activeProfileId.every((x, i) => x === p.id[i]),
1095
+ identityKey: new PrivateKey(this.XOR(this.rootPrimaryKey as number[], p.primaryPad)).toPublicKey().toString()
1086
1096
  }))
1087
1097
  ]
1088
1098
  return profileList
@@ -2,7 +2,7 @@ export * as sdk from './sdk/index'
2
2
 
3
3
  export * from './utility/index.client'
4
4
  export * from './storage/index.mobile'
5
- export * from './services/chaintracker/chaintracks/index.client'
5
+ export * from './services/chaintracker/chaintracks/index.mobile'
6
6
 
7
7
  export * from './CWIStyleWalletManager'
8
8
  export * from './monitor/Monitor'
@@ -11,6 +11,7 @@ import { TaskCheckForProofs } from './tasks/TaskCheckForProofs'
11
11
  import { TaskClock } from './tasks/TaskClock'
12
12
  import { TaskNewHeader } from './tasks/TaskNewHeader'
13
13
  import { TaskMonitorCallHistory } from './tasks/TaskMonitorCallHistory'
14
+ import { TaskReorg } from './tasks/TaskReorg'
14
15
 
15
16
  import { TaskSendWaiting } from './tasks/TaskSendWaiting'
16
17
  import { TaskCheckNoSends } from './tasks/TaskCheckNoSends'
@@ -21,7 +22,8 @@ import { WERR_BAD_REQUEST, WERR_INVALID_PARAMETER } from '../sdk/WERR_errors'
21
22
  import { WalletError } from '../sdk/WalletError'
22
23
  import { BlockHeader } from '../sdk/WalletServices.interfaces'
23
24
  import { Services } from '../services/Services'
24
- import { ChaintracksClientApi } from '../services/chaintracker/chaintracks/Api/ChaintracksClientApi'
25
+ import { ChaintracksClientApi, ReorgListener } from '../services/chaintracker/chaintracks/Api/ChaintracksClientApi'
26
+ import { Chaintracks } from '../services/chaintracker/chaintracks/Chaintracks'
25
27
 
26
28
  export type MonitorStorage = WalletStorageManager
27
29
 
@@ -34,6 +36,8 @@ export interface MonitorOptions {
34
36
 
35
37
  chaintracks: ChaintracksClientApi
36
38
 
39
+ chaintracksWithEvents?: Chaintracks
40
+
37
41
  /**
38
42
  * How many msecs to wait after each getMerkleProof service request.
39
43
  */
@@ -59,7 +63,12 @@ export interface MonitorOptions {
59
63
  * and potentially that reorgs update proofs that were already received.
60
64
  */
61
65
  export class Monitor {
62
- static createDefaultWalletMonitorOptions(chain: Chain, storage: MonitorStorage, services?: Services): MonitorOptions {
66
+ static createDefaultWalletMonitorOptions(
67
+ chain: Chain,
68
+ storage: MonitorStorage,
69
+ services?: Services,
70
+ chaintracks?: Chaintracks
71
+ ): MonitorOptions {
63
72
  services ||= new Services(chain)
64
73
  if (!services.options.chaintracks) throw new WERR_INVALID_PARAMETER('services.options.chaintracks', 'valid')
65
74
  const o: MonitorOptions = {
@@ -71,7 +80,8 @@ export class Monitor {
71
80
  abandonedMsecs: 1000 * 60 * 5,
72
81
  unprovenAttemptsLimitTest: 10,
73
82
  unprovenAttemptsLimitMain: 144,
74
- chaintracks: services.options.chaintracks
83
+ chaintracks: services.options.chaintracks,
84
+ chaintracksWithEvents: chaintracks
75
85
  }
76
86
  return o
77
87
  }
@@ -81,6 +91,9 @@ export class Monitor {
81
91
  chain: Chain
82
92
  storage: MonitorStorage
83
93
  chaintracks: ChaintracksClientApi
94
+ chaintracksWithEvents?: Chaintracks
95
+ reorgSubscriptionPromise?: Promise<string>
96
+ headersSubscriptionPromise?: Promise<string>
84
97
  onTransactionBroadcasted?: (broadcastResult: ReviewActionResult) => Promise<void>
85
98
  onTransactionProven?: (txStatus: ProvenTransactionStatus) => Promise<void>
86
99
 
@@ -90,15 +103,31 @@ export class Monitor {
90
103
  this.chain = this.services.chain
91
104
  this.storage = options.storage
92
105
  this.chaintracks = options.chaintracks
106
+ this.chaintracksWithEvents = options.chaintracksWithEvents
93
107
  this.onTransactionProven = options.onTransactionProven
94
108
  this.onTransactionBroadcasted = options.onTransactionBroadcasted
109
+
110
+ if (this.chaintracksWithEvents) {
111
+ const c = this.chaintracksWithEvents
112
+ this.reorgSubscriptionPromise = c.subscribeReorgs(this.processReorg.bind(this))
113
+ this.headersSubscriptionPromise = c.subscribeHeaders(this.processHeader.bind(this))
114
+ }
95
115
  }
96
116
 
97
- oneSecond = 1000
98
- oneMinute = 60 * this.oneSecond
99
- oneHour = 60 * this.oneMinute
100
- oneDay = 24 * this.oneHour
101
- oneWeek = 7 * this.oneDay
117
+ async destroy(): Promise<void> {
118
+ if (this.chaintracksWithEvents) {
119
+ const c = this.chaintracksWithEvents
120
+ if (this.reorgSubscriptionPromise) await c.unsubscribe(await this.reorgSubscriptionPromise)
121
+ if (this.headersSubscriptionPromise) await c.unsubscribe(await this.headersSubscriptionPromise)
122
+ }
123
+ }
124
+
125
+ static readonly oneSecond = 1000
126
+ static readonly oneMinute = 60 * Monitor.oneSecond
127
+ static readonly oneHour = 60 * Monitor.oneMinute
128
+ static readonly oneDay = 24 * Monitor.oneHour
129
+ static readonly oneWeek = 7 * Monitor.oneDay
130
+
102
131
  /**
103
132
  * _tasks are typically run by the scheduler but may also be run by runTask.
104
133
  */
@@ -113,9 +142,9 @@ export class Monitor {
113
142
  purgeSpent: false,
114
143
  purgeCompleted: false,
115
144
  purgeFailed: true,
116
- purgeSpentAge: 2 * this.oneWeek,
117
- purgeCompletedAge: 2 * this.oneWeek,
118
- purgeFailedAge: 5 * this.oneDay
145
+ purgeSpentAge: 2 * Monitor.oneWeek,
146
+ purgeCompletedAge: 2 * Monitor.oneWeek,
147
+ purgeFailedAge: 5 * Monitor.oneDay
119
148
  }
120
149
 
121
150
  addAllTasksToOther(): void {
@@ -129,6 +158,8 @@ export class Monitor {
129
158
  this._otherTasks.push(new TaskCheckNoSends(this))
130
159
  this._otherTasks.push(new TaskUnFail(this))
131
160
 
161
+ this._otherTasks.push(new TaskReorg(this))
162
+
132
163
  this._otherTasks.push(new TaskFailAbandoned(this))
133
164
 
134
165
  this._otherTasks.push(new TaskSyncWhenIdle(this))
@@ -141,13 +172,14 @@ export class Monitor {
141
172
  this._tasks.push(new TaskClock(this))
142
173
  this._tasks.push(new TaskNewHeader(this))
143
174
  this._tasks.push(new TaskMonitorCallHistory(this))
144
- this._tasks.push(new TaskSendWaiting(this, 8 * this.oneSecond, 7 * this.oneSecond)) // Check every 8 seconds but must be 7 seconds old
145
- this._tasks.push(new TaskCheckForProofs(this, 2 * this.oneHour)) // Every two hours if no block found
175
+ this._tasks.push(new TaskSendWaiting(this, 8 * Monitor.oneSecond, 7 * Monitor.oneSecond)) // Check every 8 seconds but must be 7 seconds old
176
+ this._tasks.push(new TaskCheckForProofs(this, 2 * Monitor.oneHour)) // Every two hours if no block found
146
177
  this._tasks.push(new TaskCheckNoSends(this))
147
- this._tasks.push(new TaskFailAbandoned(this, 8 * this.oneMinute))
178
+ this._tasks.push(new TaskFailAbandoned(this, 8 * Monitor.oneMinute))
148
179
  this._tasks.push(new TaskUnFail(this))
149
- //this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * this.oneHour))
180
+ //this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * Monitor.oneHour))
150
181
  this._tasks.push(new TaskReviewStatus(this))
182
+ this._tasks.push(new TaskReorg(this))
151
183
  }
152
184
 
153
185
  /**
@@ -158,13 +190,14 @@ export class Monitor {
158
190
  this._tasks.push(new TaskClock(this))
159
191
  this._tasks.push(new TaskNewHeader(this))
160
192
  this._tasks.push(new TaskMonitorCallHistory(this))
161
- this._tasks.push(new TaskSendWaiting(this, 8 * this.oneSecond, 7 * this.oneSecond)) // Check every 8 seconds but must be 7 seconds old
162
- this._tasks.push(new TaskCheckForProofs(this, 2 * this.oneHour)) // Every two hours if no block found
193
+ this._tasks.push(new TaskSendWaiting(this, 8 * Monitor.oneSecond, 7 * Monitor.oneSecond)) // Check every 8 seconds but must be 7 seconds old
194
+ this._tasks.push(new TaskCheckForProofs(this, 2 * Monitor.oneHour)) // Every two hours if no block found
163
195
  this._tasks.push(new TaskCheckNoSends(this))
164
- this._tasks.push(new TaskFailAbandoned(this, 8 * this.oneMinute))
196
+ this._tasks.push(new TaskFailAbandoned(this, 8 * Monitor.oneMinute))
165
197
  this._tasks.push(new TaskUnFail(this))
166
- //this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * this.oneHour))
198
+ //this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * Monitor.oneHour))
167
199
  this._tasks.push(new TaskReviewStatus(this))
200
+ this._tasks.push(new TaskReorg(this))
168
201
  }
169
202
 
170
203
  addTask(task: WalletMonitorTask): void {
@@ -177,14 +210,6 @@ export class Monitor {
177
210
  this._tasks = this._tasks.filter(t => t.name !== name)
178
211
  }
179
212
 
180
- async setupChaintracksListeners(): Promise<void> {
181
- try {
182
- // TODO: Use a task monitoring the newest block headere to trigger processNewHeader and reorg handling.
183
- } catch (err) {
184
- /* this chaintracks doesn't support event subscriptions */
185
- }
186
- }
187
-
188
213
  async runTask(name: string): Promise<string> {
189
214
  let task = this._tasks.find(t => t.name === name)
190
215
  let log = ''
@@ -248,17 +273,28 @@ export class Monitor {
248
273
  }
249
274
 
250
275
  _runAsyncSetup: boolean = true
276
+ _tasksRunningPromise?: PromiseLike<void>
277
+ resolveCompletion: ((value: void | PromiseLike<void>) => void) | undefined = undefined
251
278
 
252
279
  async startTasks(): Promise<void> {
253
280
  if (this._tasksRunning) throw new WERR_BAD_REQUEST('monitor tasks are already runnining.')
254
281
 
255
282
  this._tasksRunning = true
283
+ this._tasksRunningPromise = new Promise(resolve => {
284
+ this.resolveCompletion = resolve
285
+ })
286
+
256
287
  for (; this._tasksRunning; ) {
257
288
  await this.runOnce()
258
289
 
259
290
  // console.log(`${new Date().toISOString()} tasks run, waiting...`)
260
291
  await wait(this.options.taskRunWaitMsecs)
261
292
  }
293
+
294
+ if (this.resolveCompletion) {
295
+ this.resolveCompletion()
296
+ this.resolveCompletion = undefined
297
+ }
262
298
  }
263
299
 
264
300
  async logEvent(event: string, details?: string): Promise<void> {
@@ -322,6 +358,8 @@ export class Monitor {
322
358
  }
323
359
  }
324
360
 
361
+ deactivatedHeaders: DeactivedHeader[] = []
362
+
325
363
  /**
326
364
  * Process reorg event received from Chaintracks
327
365
  *
@@ -333,7 +371,34 @@ export class Monitor {
333
371
  * Coinbase transactions always become invalid.
334
372
  */
335
373
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
336
- processReorg(depth: number, oldTip: BlockHeader, newTip: BlockHeader): void {
337
- /* */
374
+ processReorg(depth: number, oldTip: BlockHeader, newTip: BlockHeader, deactivatedHeaders?: BlockHeader[]): void {
375
+ if (deactivatedHeaders) {
376
+ for (const header of deactivatedHeaders) {
377
+ this.deactivatedHeaders.push({
378
+ whenMsecs: Date.now(),
379
+ tries: 0,
380
+ header
381
+ })
382
+ }
383
+ }
338
384
  }
385
+
386
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
387
+ processHeader(header: BlockHeader): void {}
388
+ }
389
+
390
+ export interface DeactivedHeader {
391
+ /**
392
+ * To control aging of notification before pursuing updated proof data.
393
+ */
394
+ whenMsecs: number
395
+ /**
396
+ * Number of attempts made to process the header.
397
+ * Supports returning deactivation notification to the queue if proof data is not yet available.
398
+ */
399
+ tries: number
400
+ /**
401
+ * The deactivated block header.
402
+ */
403
+ header: BlockHeader
339
404
  }
@@ -11,6 +11,7 @@ import { Monitor } from './Monitor'
11
11
  import { WERR_INTERNAL, WERR_INVALID_PARAMETER } from '../sdk/WERR_errors'
12
12
  import { wait } from '../utility/utilityHelpers'
13
13
  import { WalletError } from '../sdk/WalletError'
14
+ import { Chaintracks } from '../services/chaintracker/chaintracks/Chaintracks'
14
15
  dotenv.config()
15
16
 
16
17
  const mainDojoConnection = process.env.MAIN_DOJO_CONNECTION || ''
@@ -28,6 +29,7 @@ export interface MonitorDaemonSetup {
28
29
  servicesOptions?: WalletServicesOptions
29
30
  services?: Services
30
31
  monitor?: Monitor
32
+ chaintracks?: Chaintracks
31
33
  }
32
34
 
33
35
  export class MonitorDaemon {
@@ -99,6 +101,7 @@ export class MonitorDaemon {
99
101
  if (a.servicesOptions) {
100
102
  if (a.servicesOptions.chain != a.chain)
101
103
  throw new WERR_INVALID_PARAMETER('serviceOptions.chain', 'same as args.chain')
104
+ a.servicesOptions.chaintracks ||= a.chaintracks
102
105
  a.services = new Services(a.servicesOptions)
103
106
  }
104
107
 
@@ -108,7 +111,12 @@ export class MonitorDaemon {
108
111
 
109
112
  a.storageManager.setServices(a.services)
110
113
 
111
- const monitorOptions = Monitor.createDefaultWalletMonitorOptions(a.chain, a.storageManager, a.services)
114
+ const monitorOptions = Monitor.createDefaultWalletMonitorOptions(
115
+ a.chain,
116
+ a.storageManager,
117
+ a.services,
118
+ a.chaintracks
119
+ )
112
120
  a.monitor = new Monitor(monitorOptions)
113
121
  }
114
122
 
@@ -1,17 +1,45 @@
1
- import * as dotenv from 'dotenv'
2
1
  import { MonitorDaemon } from '../MonitorDaemon'
3
- dotenv.config()
4
-
5
- const cloudMySQLConnection = process.env.TEST_CLOUD_MYSQL_CONNECTION || '{}'
2
+ import { Chain } from '../../sdk/types'
3
+ import { Services } from '../../services/Services'
4
+ import { _tu } from '../../../test/utils/TestUtilsWalletStorage'
5
+ import { createDefaultNoDbChaintracksOptions } from '../../services/chaintracker/chaintracks/createDefaultNoDbChaintracksOptions'
6
+ import { Chaintracks } from '../../services/chaintracker/chaintracks/Chaintracks'
6
7
 
7
8
  describe('MonitorDaemon tests', () => {
8
9
  jest.setTimeout(99999999)
9
10
 
10
- test('0', async () => {
11
+ test('0 mainnet', async () => {
12
+ await test0Body('main')
13
+ })
14
+
15
+ test('0a testnet', async () => {
16
+ await test0Body('test')
17
+ })
18
+
19
+ async function test0Body(chain: Chain) {
20
+ const env = _tu.getEnv(chain)
21
+
22
+ const servicesOptions = Services.createDefaultOptions(chain)
23
+ if (env.taalApiKey) {
24
+ servicesOptions.taalApiKey = env.taalApiKey
25
+ servicesOptions.arcConfig.apiKey = env.taalApiKey
26
+ }
27
+ if (env.whatsonchainApiKey) servicesOptions.whatsOnChainApiKey = env.whatsonchainApiKey
28
+ if (env.bitailsApiKey) servicesOptions.bitailsApiKey = env.bitailsApiKey
29
+
30
+ const u = undefined
31
+ const maxRetained = 32
32
+ const chaintracksOptions = createDefaultNoDbChaintracksOptions(chain, env.whatsonchainApiKey, u, maxRetained)
33
+ const chaintracks = new Chaintracks(chaintracksOptions)
34
+ servicesOptions.chaintracks = chaintracks
35
+
11
36
  const d = new MonitorDaemon({
12
37
  chain: 'test',
13
- mySQLConnection: cloudMySQLConnection
38
+ mySQLConnection: env.cloudMySQLConnection,
39
+ servicesOptions,
40
+ chaintracks
14
41
  })
42
+
15
43
  await d.runDaemon()
16
- })
44
+ }
17
45
  })
@@ -26,7 +26,7 @@ export class TaskCheckNoSends extends WalletMonitorTask {
26
26
 
27
27
  constructor(
28
28
  monitor: Monitor,
29
- public triggerMsecs = monitor.oneDay * 1
29
+ public triggerMsecs = Monitor.oneDay * 1
30
30
  ) {
31
31
  super(monitor, TaskCheckNoSends.taskName)
32
32
  }
@@ -7,7 +7,7 @@ export class TaskClock extends WalletMonitorTask {
7
7
 
8
8
  constructor(
9
9
  monitor: Monitor,
10
- public triggerMsecs = 1 * monitor.oneSecond
10
+ public triggerMsecs = 1 * Monitor.oneSecond
11
11
  ) {
12
12
  super(monitor, TaskClock.taskName)
13
13
  this.nextMinute = this.getNextMinute()
@@ -28,6 +28,6 @@ export class TaskClock extends WalletMonitorTask {
28
28
  }
29
29
 
30
30
  getNextMinute(): number {
31
- return Math.ceil(Date.now() / this.monitor.oneMinute) * this.monitor.oneMinute
31
+ return Math.ceil(Date.now() / Monitor.oneMinute) * Monitor.oneMinute
32
32
  }
33
33
  }
@@ -7,7 +7,7 @@ export class TaskMonitorCallHistory extends WalletMonitorTask {
7
7
 
8
8
  constructor(
9
9
  monitor: Monitor,
10
- public triggerMsecs = monitor.oneMinute * 12
10
+ public triggerMsecs = Monitor.oneMinute * 12
11
11
  ) {
12
12
  super(monitor, TaskMonitorCallHistory.taskName)
13
13
  }
@@ -29,7 +29,7 @@ export class TaskNewHeader extends WalletMonitorTask {
29
29
 
30
30
  constructor(
31
31
  monitor: Monitor,
32
- public triggerMsecs = 1 * monitor.oneMinute
32
+ public triggerMsecs = 1 * Monitor.oneMinute
33
33
  ) {
34
34
  super(monitor, TaskNewHeader.taskName)
35
35
  }
@@ -0,0 +1,139 @@
1
+ import { TableProvenTx } from '../../index.client'
2
+ import { BlockHeader } from '../../services/chaintracker/chaintracks/Api/BlockHeaderApi'
3
+ import { DeactivedHeader, Monitor } from '../Monitor'
4
+ import { WalletMonitorTask } from './WalletMonitorTask'
5
+
6
+ /**
7
+ * Check the `monitor.deactivatedHeaders` for any headers that have been deactivated.
8
+ *
9
+ * When headers are found, review matching ProvenTx records and update proof data as appropriate.
10
+ *
11
+ * New deactivated headers are pushed onto the `deactivatedHeaders` array.
12
+ * They must be shifted out as they are processed.
13
+ *
14
+ * The current implementation ages deactivation notifications by 10 minutes with each retry.
15
+ * If a successful proof update confirms original proof data after 3 retries, the original is retained.
16
+ *
17
+ * In normal operation there should never be any work for this task to perform.
18
+ * The most common result is that there are no matching proven_txs records because
19
+ * generating new proven_txs records intentionally lags new block generation to
20
+ * minimize this disruption.
21
+ *
22
+ * It is very disruptive to update a proven_txs record because:
23
+ * - Sync'ed storage is impacted.
24
+ * - Generated beefs are impacted.
25
+ * - Updated proof data may be unavailable at the time a reorg is first reported.
26
+ *
27
+ * Instead of reorg notification derived from new header notification, reorg repair to
28
+ * the proven_txs table is more effectively driven by noticing that a beef generated for a new
29
+ * createAction fails to verify against the chaintracker.
30
+ *
31
+ * An alternate approach to processing these events is to revert the proven_txs record to a proven_tx_reqs record.
32
+ * Pros:
33
+ * - The same multiple attempt logic that already exists is reused.
34
+ * - Failing to obtain a new proof already has transaction failure handling in place.
35
+ * - Generated beefs automatically become one generation deeper, potentially allowing transaction outputs to be spent.
36
+ * Cons:
37
+ * - Transactions must revert to un-proven / un-mined.
38
+ */
39
+ export class TaskReorg extends WalletMonitorTask {
40
+ static taskName = 'Reorg'
41
+
42
+ process: DeactivedHeader[] = []
43
+
44
+ constructor(
45
+ monitor: Monitor,
46
+ public agedMsecs = Monitor.oneMinute * 10,
47
+ public maxRetries = 3
48
+ ) {
49
+ super(monitor, TaskReorg.taskName)
50
+ }
51
+
52
+ trigger(nowMsecsSinceEpoch: number): { run: boolean } {
53
+ const cutoff = nowMsecsSinceEpoch - this.agedMsecs
54
+ const q = this.monitor.deactivatedHeaders
55
+ while (q.length > 0 && cutoff > q[0].whenMsecs) {
56
+ // Prepare to process deactivated headers that have aged sufficiently (agedMsecs)
57
+ const header = q.shift()!
58
+ this.process.push(header)
59
+ }
60
+ return {
61
+ run: this.process.length > 0
62
+ }
63
+ }
64
+
65
+ async runTask(): Promise<string> {
66
+ let log = ''
67
+
68
+ for (;;) {
69
+ const header = this.process.shift()
70
+ if (!header) break
71
+
72
+ let ptxs: TableProvenTx[] = []
73
+
74
+ await this.storage.runAsStorageProvider(async sp => {
75
+ // Lookup all the proven_txs records matching the deactivated headers
76
+ ptxs = await sp.findProvenTxs({ partial: { blockHash: header.header.hash } })
77
+ })
78
+
79
+ log += ` block ${header.header.hash} orphaned with ${ptxs.length} impacted transactions\n`
80
+
81
+ let retry = false
82
+ for (const ptx of ptxs) {
83
+ const mpr = await this.monitor.services.getMerklePath(ptx.txid)
84
+ if (mpr.merklePath && mpr.header) {
85
+ const mp = mpr.merklePath
86
+ const h = mpr.header
87
+ const leaf = mp.path[0].find(leaf => leaf.txid === true && leaf.hash === ptx.txid)
88
+ if (leaf) {
89
+ const update: Partial<TableProvenTx> = {
90
+ height: mp.blockHeight,
91
+ index: leaf.offset,
92
+ merklePath: mp.toBinary(),
93
+ merkleRoot: h.merkleRoot,
94
+ blockHash: h.hash
95
+ }
96
+ if (update.blockHash === ptx.blockHash) {
97
+ log += ` txid ${ptx.txid} merkle path update still based on deactivated header ${ptx.blockHash}\n`
98
+ if (header.tries + 1 >= this.maxRetries) {
99
+ log += ` maximum retries ${this.maxRetries} exceeded\n`
100
+ } else {
101
+ retry = true
102
+ }
103
+ } else {
104
+ // Verify the new proof's validity.
105
+ const merkleRoot = mp.computeRoot(ptx.txid)
106
+ const chaintracker = await this.monitor.services.getChainTracker()
107
+ const isValid = await chaintracker.isValidRootForHeight(merkleRoot, update.height!)
108
+ const logUpdate = ` height ${ptx.height} ${ptx.height === update.height ? 'unchanged' : `-> ${update.height}`}\n`
109
+ log += ` blockHash ${ptx.blockHash} -> ${update.blockHash}\n`
110
+ log += ` merkleRoot ${ptx.merkleRoot} -> ${update.merkleRoot}\n`
111
+ log += ` index ${ptx.index} -> ${update.index}\n`
112
+ if (!isValid) {
113
+ log +=
114
+ ` txid ${ptx.txid} chaintracker fails to confirm updated merkle path update invalid\n` + logUpdate
115
+ } else {
116
+ await this.storage.runAsStorageProvider(async sp => {
117
+ await sp.updateProvenTx(ptx.provenTxId, update)
118
+ })
119
+ log += ` txid ${ptx.txid} proof data updated\n` + logUpdate
120
+ }
121
+ }
122
+ } else {
123
+ log += ` txid ${ptx.txid} merkle path update doesn't include txid\n`
124
+ retry = true
125
+ }
126
+ } else {
127
+ log += ` txid ${ptx.txid} merkle path update unavailable\n`
128
+ retry = true
129
+ }
130
+ }
131
+ if (retry) {
132
+ log += ` retrying...\n`
133
+ this.monitor.deactivatedHeaders.push({ header: header.header, whenMsecs: Date.now(), tries: header.tries + 1 })
134
+ }
135
+ }
136
+
137
+ return log
138
+ }
139
+ }
@@ -16,9 +16,9 @@ export class TaskSendWaiting extends WalletMonitorTask {
16
16
 
17
17
  constructor(
18
18
  monitor: Monitor,
19
- public triggerMsecs = monitor.oneSecond * 8,
20
- public agedMsecs = monitor.oneSecond * 7,
21
- public sendingMsecs = monitor.oneMinute * 5
19
+ public triggerMsecs = Monitor.oneSecond * 8,
20
+ public agedMsecs = Monitor.oneSecond * 7,
21
+ public sendingMsecs = Monitor.oneMinute * 5
22
22
  ) {
23
23
  super(monitor, TaskSendWaiting.taskName)
24
24
  }
@@ -25,7 +25,7 @@ export class TaskUnFail extends WalletMonitorTask {
25
25
 
26
26
  constructor(
27
27
  monitor: Monitor,
28
- public triggerMsecs = monitor.oneMinute * 10
28
+ public triggerMsecs = Monitor.oneMinute * 10
29
29
  ) {
30
30
  super(monitor, TaskUnFail.taskName)
31
31
  }
@@ -10,7 +10,12 @@ export type HeaderListener = (header: BlockHeader) => void
10
10
  /**
11
11
  * @public
12
12
  */
13
- export type ReorgListener = (depth: number, oldTip: BlockHeader, newTip: BlockHeader) => void
13
+ export type ReorgListener = (
14
+ depth: number,
15
+ oldTip: BlockHeader,
16
+ newTip: BlockHeader,
17
+ deactivatedHeaders?: BlockHeader[]
18
+ ) => void
14
19
 
15
20
  /**
16
21
  * @public
@@ -256,6 +256,10 @@ export type InsertHeaderResult = {
256
256
  * If `added` is true, this header was the active chain tip before the insert. It may or may not still be the active chain tip after the insert.
257
257
  */
258
258
  priorTip: LiveBlockHeader | undefined
259
+ /**
260
+ * If a reorg has occurred, these headers where active and are now deactivated.
261
+ */
262
+ deactivatedHeaders: LiveBlockHeader[]
259
263
  /**
260
264
  * header's previousHash was not found in database
261
265
  */
@@ -416,7 +416,9 @@ export class Chaintracks implements ChaintracksManagementApi {
416
416
  const reorgListener = this.callbacks.reorg[id]
417
417
  if (reorgListener) {
418
418
  try {
419
- reorgListener(ihr.reorgDepth, ihr.priorTip, header)
419
+ const priorTip: BlockHeader = { ...ihr.priorTip }
420
+ const deactivated: BlockHeader[] = ihr.deactivatedHeaders.map(lbh => ({ ...lbh }))
421
+ reorgListener(ihr.reorgDepth, priorTip, header, deactivated)
420
422
  } catch {
421
423
  /* ignore all errors thrown */
422
424
  }