@bsv/wallet-toolbox 1.1.13 → 1.1.15

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 (132) hide show
  1. package/docs/README.md +8 -2
  2. package/docs/client.md +465 -346
  3. package/docs/open-rpc/index.html +46 -0
  4. package/docs/services.md +236 -211
  5. package/docs/setup.md +32 -4
  6. package/docs/storage.md +30 -5
  7. package/docs/wallet.md +465 -346
  8. package/out/src/Setup.d.ts.map +1 -1
  9. package/out/src/Setup.js.map +1 -1
  10. package/out/src/SetupClient.d.ts +9 -0
  11. package/out/src/SetupClient.d.ts.map +1 -1
  12. package/out/src/SetupClient.js +19 -3
  13. package/out/src/SetupClient.js.map +1 -1
  14. package/out/src/Wallet.d.ts +6 -0
  15. package/out/src/Wallet.d.ts.map +1 -1
  16. package/out/src/Wallet.js +57 -0
  17. package/out/src/Wallet.js.map +1 -1
  18. package/out/src/sdk/WalletServices.interfaces.d.ts +18 -13
  19. package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
  20. package/out/src/services/Services.d.ts +4 -11
  21. package/out/src/services/Services.d.ts.map +1 -1
  22. package/out/src/services/Services.js +19 -37
  23. package/out/src/services/Services.js.map +1 -1
  24. package/out/src/services/__tests/ARC.test.d.ts +2 -0
  25. package/out/src/services/__tests/ARC.test.d.ts.map +1 -0
  26. package/out/src/services/__tests/ARC.test.js +98 -0
  27. package/out/src/services/__tests/ARC.test.js.map +1 -0
  28. package/out/src/services/__tests/arcServices.test.d.ts +2 -0
  29. package/out/src/services/__tests/arcServices.test.d.ts.map +1 -0
  30. package/out/src/services/__tests/arcServices.test.js +7 -0
  31. package/out/src/services/__tests/arcServices.test.js.map +1 -0
  32. package/out/src/services/__tests/postBeef.test.js +45 -7
  33. package/out/src/services/__tests/postBeef.test.js.map +1 -1
  34. package/out/src/services/createDefaultWalletServicesOptions.d.ts +1 -0
  35. package/out/src/services/createDefaultWalletServicesOptions.d.ts.map +1 -1
  36. package/out/src/services/createDefaultWalletServicesOptions.js +16 -4
  37. package/out/src/services/createDefaultWalletServicesOptions.js.map +1 -1
  38. package/out/src/services/providers/ARC.d.ts +91 -0
  39. package/out/src/services/providers/ARC.d.ts.map +1 -0
  40. package/out/src/services/providers/ARC.js +192 -0
  41. package/out/src/services/providers/ARC.js.map +1 -0
  42. package/out/src/services/providers/SdkWhatsOnChain.d.ts +21 -0
  43. package/out/src/services/providers/SdkWhatsOnChain.d.ts.map +1 -0
  44. package/out/src/services/providers/SdkWhatsOnChain.js +67 -0
  45. package/out/src/services/providers/SdkWhatsOnChain.js.map +1 -0
  46. package/out/src/services/providers/WhatsOnChain.d.ts +35 -0
  47. package/out/src/services/providers/WhatsOnChain.d.ts.map +1 -0
  48. package/out/src/services/providers/WhatsOnChain.js +266 -0
  49. package/out/src/services/providers/WhatsOnChain.js.map +1 -0
  50. package/out/src/services/providers/__tests/WhatsOnChain.test.d.ts +2 -0
  51. package/out/src/services/providers/__tests/WhatsOnChain.test.d.ts.map +1 -0
  52. package/out/src/services/providers/__tests/WhatsOnChain.test.js +176 -0
  53. package/out/src/services/providers/__tests/WhatsOnChain.test.js.map +1 -0
  54. package/out/src/storage/methods/createAction.d.ts.map +1 -1
  55. package/out/src/storage/methods/createAction.js +9 -2
  56. package/out/src/storage/methods/createAction.js.map +1 -1
  57. package/out/src/storage/methods/generateChange.d.ts +12 -1
  58. package/out/src/storage/methods/generateChange.d.ts.map +1 -1
  59. package/out/src/storage/methods/generateChange.js +24 -1
  60. package/out/src/storage/methods/generateChange.js.map +1 -1
  61. package/out/src/storage/methods/processAction.d.ts.map +1 -1
  62. package/out/src/storage/methods/processAction.js +1 -1
  63. package/out/src/storage/methods/processAction.js.map +1 -1
  64. package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js +0 -1
  65. package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js.map +1 -1
  66. package/out/src/storage/sync/StorageMySQLDojoReader.js +1 -1
  67. package/out/src/storage/sync/StorageMySQLDojoReader.js.map +1 -1
  68. package/out/src/utility/utilityHelpers.js +1 -1
  69. package/out/src/utility/utilityHelpers.js.map +1 -1
  70. package/out/test/Wallet/StorageClient/storageClient.man.test.js +22 -3
  71. package/out/test/Wallet/StorageClient/storageClient.man.test.js.map +1 -1
  72. package/out/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.js +40 -0
  73. package/out/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.js.map +1 -1
  74. package/out/test/services/Services.test.js +0 -31
  75. package/out/test/services/Services.test.js.map +1 -1
  76. package/out/test/utils/TestUtilsWalletStorage.d.ts +26 -18
  77. package/out/test/utils/TestUtilsWalletStorage.d.ts.map +1 -1
  78. package/out/test/utils/TestUtilsWalletStorage.js +135 -27
  79. package/out/test/utils/TestUtilsWalletStorage.js.map +1 -1
  80. package/out/test/wallet/list/listActions2.test.js +36 -2
  81. package/out/test/wallet/list/listActions2.test.js.map +1 -1
  82. package/out/tsconfig.all.tsbuildinfo +1 -1
  83. package/package.json +4 -6
  84. package/src/Setup.ts +0 -1
  85. package/src/SetupClient.ts +25 -6
  86. package/src/Wallet.ts +66 -2
  87. package/src/sdk/WalletServices.interfaces.ts +19 -14
  88. package/src/services/Services.ts +23 -62
  89. package/src/services/__tests/ARC.test.ts +110 -0
  90. package/src/services/__tests/arcServices.test.ts +8 -0
  91. package/src/services/__tests/postBeef.test.ts +47 -9
  92. package/src/services/createDefaultWalletServicesOptions.ts +19 -6
  93. package/src/services/providers/ARC.ts +289 -0
  94. package/src/services/providers/SdkWhatsOnChain.ts +96 -0
  95. package/src/services/providers/WhatsOnChain.ts +369 -0
  96. package/src/services/providers/__tests/WhatsOnChain.test.ts +227 -0
  97. package/src/storage/methods/createAction.ts +26 -4
  98. package/src/storage/methods/generateChange.ts +42 -2
  99. package/src/storage/methods/processAction.ts +2 -1
  100. package/src/storage/schema/entities/__tests/ProvenTxTests.test.ts +0 -1
  101. package/src/storage/sync/StorageMySQLDojoReader.ts +1 -1
  102. package/src/utility/utilityHelpers.ts +1 -1
  103. package/test/Wallet/StorageClient/storageClient.man.test.ts +30 -4
  104. package/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.ts +54 -0
  105. package/test/services/Services.test.ts +0 -30
  106. package/test/utils/TestUtilsWalletStorage.ts +174 -45
  107. package/test/wallet/list/listActions2.test.ts +4 -7
  108. package/out/src/services/__tests/postBeefToArcTaal.test.d.ts +0 -2
  109. package/out/src/services/__tests/postBeefToArcTaal.test.d.ts.map +0 -1
  110. package/out/src/services/__tests/postBeefToArcTaal.test.js +0 -479
  111. package/out/src/services/__tests/postBeefToArcTaal.test.js.map +0 -1
  112. package/out/src/services/__tests/postTxs.test.d.ts +0 -2
  113. package/out/src/services/__tests/postTxs.test.d.ts.map +0 -1
  114. package/out/src/services/__tests/postTxs.test.js +0 -28
  115. package/out/src/services/__tests/postTxs.test.js.map +0 -1
  116. package/out/src/services/providers/arcServices.d.ts +0 -62
  117. package/out/src/services/providers/arcServices.d.ts.map +0 -1
  118. package/out/src/services/providers/arcServices.js +0 -375
  119. package/out/src/services/providers/arcServices.js.map +0 -1
  120. package/out/src/services/providers/whatsonchain.d.ts +0 -17
  121. package/out/src/services/providers/whatsonchain.d.ts.map +0 -1
  122. package/out/src/services/providers/whatsonchain.js +0 -130
  123. package/out/src/services/providers/whatsonchain.js.map +0 -1
  124. package/out/test/examples/README.man.test.d.ts +0 -2
  125. package/out/test/examples/README.man.test.d.ts.map +0 -1
  126. package/out/test/examples/README.man.test.js +0 -47
  127. package/out/test/examples/README.man.test.js.map +0 -1
  128. package/src/services/__tests/postBeefToArcTaal.test.ts +0 -487
  129. package/src/services/__tests/postTxs.test.ts +0 -28
  130. package/src/services/providers/arcServices.ts +0 -578
  131. package/src/services/providers/whatsonchain.ts +0 -170
  132. package/test/examples/README.man.test.ts +0 -53
@@ -0,0 +1,289 @@
1
+ import {
2
+ Beef,
3
+ BEEF_V1,
4
+ BEEF_V2,
5
+ defaultHttpClient,
6
+ HexString,
7
+ HttpClient,
8
+ HttpClientRequestOptions,
9
+ Random,
10
+ Utils
11
+ } from '@bsv/sdk'
12
+ import { doubleSha256BE, sdk } from '../../index.client'
13
+
14
+ /** Configuration options for the ARC broadcaster. */
15
+ export interface ArcConfig {
16
+ /** Authentication token for the ARC API */
17
+ apiKey?: string
18
+ /** The HTTP client used to make requests to the ARC API. */
19
+ httpClient?: HttpClient
20
+ /** Deployment id used annotating api calls in XDeployment-ID header - this value will be randomly generated if not set */
21
+ deploymentId?: string
22
+ /** notification callback endpoint for proofs and double spend notification */
23
+ callbackUrl?: string
24
+ /** default access token for notification callback endpoint. It will be used as a Authorization header for the http callback */
25
+ callbackToken?: string
26
+ /** additional headers to be attached to all tx submissions. */
27
+ headers?: Record<string, string>
28
+ }
29
+
30
+ function defaultDeploymentId(): string {
31
+ return `ts-sdk-${Utils.toHex(Random(16))}`
32
+ }
33
+
34
+ /**
35
+ * Represents an ARC transaction broadcaster.
36
+ */
37
+ export default class ARC {
38
+ readonly URL: string
39
+ readonly apiKey: string | undefined
40
+ readonly deploymentId: string
41
+ readonly callbackUrl: string | undefined
42
+ readonly callbackToken: string | undefined
43
+ readonly headers: Record<string, string> | undefined
44
+ private readonly httpClient: HttpClient
45
+
46
+ /**
47
+ * Constructs an instance of the ARC broadcaster.
48
+ *
49
+ * @param {string} URL - The URL endpoint for the ARC API.
50
+ * @param {ArcConfig} config - Configuration options for the ARC broadcaster.
51
+ */
52
+ constructor(URL: string, config?: ArcConfig)
53
+ /**
54
+ * Constructs an instance of the ARC broadcaster.
55
+ *
56
+ * @param {string} URL - The URL endpoint for the ARC API.
57
+ * @param {string} apiKey - The API key used for authorization with the ARC API.
58
+ */
59
+ constructor(URL: string, apiKey?: string)
60
+
61
+ constructor(URL: string, config?: string | ArcConfig) {
62
+ this.URL = URL
63
+ if (typeof config === 'string') {
64
+ this.apiKey = config
65
+ this.httpClient = defaultHttpClient()
66
+ this.deploymentId = defaultDeploymentId()
67
+ this.callbackToken = undefined
68
+ this.callbackUrl = undefined
69
+ } else {
70
+ const configObj: ArcConfig = config ?? {}
71
+ const {
72
+ apiKey,
73
+ deploymentId,
74
+ httpClient,
75
+ callbackToken,
76
+ callbackUrl,
77
+ headers
78
+ } = configObj
79
+ this.apiKey = apiKey
80
+ this.httpClient = httpClient ?? defaultHttpClient()
81
+ this.deploymentId = deploymentId ?? defaultDeploymentId()
82
+ this.callbackToken = callbackToken
83
+ this.callbackUrl = callbackUrl
84
+ this.headers = headers
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Constructs a dictionary of the default & supplied request headers.
90
+ */
91
+ private requestHeaders(): Record<string, string> {
92
+ const headers: Record<string, string> = {
93
+ 'Content-Type': 'application/json',
94
+ 'XDeployment-ID': this.deploymentId
95
+ }
96
+
97
+ if (this.apiKey != null && this.apiKey !== '') {
98
+ headers.Authorization = `Bearer ${this.apiKey}`
99
+ }
100
+
101
+ if (this.callbackUrl != null && this.callbackUrl !== '') {
102
+ headers['X-CallbackUrl'] = this.callbackUrl
103
+ }
104
+
105
+ if (this.callbackToken != null && this.callbackToken !== '') {
106
+ headers['X-CallbackToken'] = this.callbackToken
107
+ }
108
+
109
+ if (this.headers != null) {
110
+ for (const key in this.headers) {
111
+ headers[key] = this.headers[key]
112
+ }
113
+ }
114
+
115
+ return headers
116
+ }
117
+
118
+ /**
119
+ * The ARC '/v1/tx' endpoint, as of 2025-02-17 supports all of the following hex string formats:
120
+ * 1. Single serialized raw transaction.
121
+ * 2. Single EF serialized raw transaction (untested).
122
+ * 3. V1 serialized Beef (results returned reflect only the last transaction in the beef)
123
+ *
124
+ * The ARC '/v1/tx' endpoint, as of 2025-02-17 DOES NOT support the following hex string formats:
125
+ * 1. V2 serialized Beef
126
+ *
127
+ * @param rawTx
128
+ * @param txids
129
+ * @returns
130
+ */
131
+ async postRawTx(
132
+ rawTx: HexString,
133
+ txids?: string[]
134
+ ): Promise<sdk.PostTxResultForTxid> {
135
+ let txid = Utils.toHex(doubleSha256BE(Utils.toArray(rawTx, 'hex')))
136
+ if (txids) {
137
+ txid = txids.slice(-1)[0]
138
+ }
139
+
140
+ const requestOptions: HttpClientRequestOptions = {
141
+ method: 'POST',
142
+ headers: this.requestHeaders(),
143
+ data: { rawTx }
144
+ }
145
+
146
+ const r: sdk.PostTxResultForTxid = {
147
+ txid,
148
+ status: 'success'
149
+ }
150
+
151
+ try {
152
+ const response = await this.httpClient.request<ArcResponse>(
153
+ `${this.URL}/v1/tx`,
154
+ requestOptions
155
+ )
156
+
157
+ if (response.ok) {
158
+ const { txid, extraInfo, txStatus, competingTxs } = response.data
159
+ r.data = `${txStatus} ${extraInfo}`
160
+ if (r.txid !== txid) r.data += ` txid altered from ${r.txid} to ${txid}`
161
+ r.txid = txid
162
+ if (txStatus === 'DOUBLE_SPEND_ATTEMPTED') {
163
+ r.status = 'error'
164
+ r.doubleSpend = true
165
+ r.competingTxs = competingTxs
166
+ }
167
+ } else {
168
+ r.status = 'error'
169
+ const ed: sdk.PostTxResultForTxidError = {}
170
+ r.data = ed
171
+ const st = typeof response.status
172
+ ed.status =
173
+ st === 'number' || st === 'string'
174
+ ? response.status.toString()
175
+ : 'ERR_UNKNOWN'
176
+
177
+ let d = response.data
178
+ if (d && typeof d === 'string') {
179
+ try {
180
+ d = JSON.parse(d)
181
+ } catch {
182
+ // Intentionally left empty
183
+ }
184
+ }
185
+ if (d && typeof d === 'object') {
186
+ ed.more = d
187
+ ed.detail = d['detail']
188
+ if (typeof ed.detail !== 'string') ed.detail = undefined
189
+ }
190
+ }
191
+ } catch (eu: unknown) {
192
+ const e = sdk.WalletError.fromUnknown(eu)
193
+ r.status = 'error'
194
+ r.data = `${e.code} ${e.message}`
195
+ }
196
+
197
+ return r
198
+ }
199
+
200
+ /**
201
+ * ARC does not natively support a postBeef end-point aware of multiple txids of interest in the Beef.
202
+ *
203
+ * It does process multiple new transactions, however, which allows results for all txids of interest
204
+ * to be collected by the `/v1/tx/${txid}` endpoint.
205
+ *
206
+ * @param beef
207
+ * @param txids
208
+ * @returns
209
+ */
210
+ async postBeef(beef: Beef, txids: string[]): Promise<sdk.PostBeefResult> {
211
+ if (beef.version === BEEF_V2 && beef.txs.every(btx => !btx.isTxidOnly)) {
212
+ beef.version = BEEF_V1
213
+ }
214
+
215
+ const beefHex = beef.toHex()
216
+
217
+ const prtr = await this.postRawTx(beefHex, txids)
218
+
219
+ const r: sdk.PostBeefResult = {
220
+ name: 'ARC',
221
+ status: prtr.status,
222
+ txidResults: [prtr]
223
+ }
224
+
225
+ for (const txid of txids) {
226
+ if (prtr.txid === txid) continue
227
+ const tr: sdk.PostTxResultForTxid = {
228
+ txid,
229
+ status: 'success'
230
+ }
231
+ const dr = await this.getTxData(txid)
232
+ if (dr.txid !== txid) {
233
+ tr.status = 'error'
234
+ tr.data = 'internal error'
235
+ } else if (
236
+ dr.txStatus === 'SEEN_ON_NETWORK' ||
237
+ dr.txStatus === 'STORED'
238
+ ) {
239
+ tr.data = dr.txStatus
240
+ } else {
241
+ tr.status = 'error'
242
+ tr.data = dr
243
+ }
244
+ r.txidResults.push(tr)
245
+ if (r.status === 'success' && tr.status === 'error') r.status = 'error'
246
+ }
247
+
248
+ return r
249
+ }
250
+
251
+ /**
252
+ * This seems to only work for recently submitted txids...but that's all we need to complete postBeef!
253
+ * @param txid
254
+ * @returns
255
+ */
256
+ async getTxData(txid: string): Promise<ArcMinerGetTxData> {
257
+ const requestOptions: HttpClientRequestOptions = {
258
+ method: 'GET',
259
+ headers: this.requestHeaders()
260
+ }
261
+
262
+ const response = await this.httpClient.request<ArcMinerGetTxData>(
263
+ `${this.URL}/v1/tx/${txid}`,
264
+ requestOptions
265
+ )
266
+
267
+ return response.data
268
+ }
269
+ }
270
+
271
+ interface ArcResponse {
272
+ txid: string
273
+ extraInfo: string
274
+ txStatus: string
275
+ competingTxs?: string[]
276
+ }
277
+
278
+ export interface ArcMinerGetTxData {
279
+ status: number // 200
280
+ title: string // OK
281
+ blockHash: string
282
+ blockHeight: number
283
+ competingTxs: null | string[]
284
+ extraInfo: string
285
+ merklePath: string
286
+ timestamp: string // ISO Z
287
+ txid: string
288
+ txStatus: string // 'SEEN_IN_ORPHAN_MEMPOOL'
289
+ }
@@ -0,0 +1,96 @@
1
+ import {
2
+ ChainTracker,
3
+ defaultHttpClient,
4
+ HttpClient,
5
+ WhatsOnChainConfig
6
+ } from '@bsv/sdk'
7
+
8
+ interface WhatsOnChainBlockHeader {
9
+ merkleroot: string
10
+ }
11
+
12
+ /**
13
+ * Represents a chain tracker based on What's On Chain .
14
+ */
15
+ export default class SdkWhatsOnChain implements ChainTracker {
16
+ readonly network: string
17
+ readonly apiKey: string
18
+ protected readonly URL: string
19
+ protected readonly httpClient: HttpClient
20
+
21
+ /**
22
+ * Constructs an instance of the WhatsOnChain ChainTracker.
23
+ *
24
+ * @param {'main' | 'test' | 'stn'} network - The BSV network to use when calling the WhatsOnChain API.
25
+ * @param {WhatsOnChainConfig} config - Configuration options for the WhatsOnChain ChainTracker.
26
+ */
27
+ constructor(
28
+ network: 'main' | 'test' | 'stn' = 'main',
29
+ config: WhatsOnChainConfig = {}
30
+ ) {
31
+ const { apiKey, httpClient } = config
32
+ this.network = network
33
+ this.URL = `https://api.whatsonchain.com/v1/bsv/${network}`
34
+ this.httpClient = httpClient ?? defaultHttpClient()
35
+ this.apiKey = apiKey ?? ''
36
+ }
37
+
38
+ async isValidRootForHeight(root: string, height: number): Promise<boolean> {
39
+ const requestOptions = {
40
+ method: 'GET',
41
+ headers: this.getHttpHeaders()
42
+ }
43
+
44
+ const response = await this.httpClient.request<WhatsOnChainBlockHeader>(
45
+ `${this.URL}/block/${height}/header`,
46
+ requestOptions
47
+ )
48
+ if (response.ok) {
49
+ const { merkleroot } = response.data
50
+ return merkleroot === root
51
+ } else if (response.status === 404) {
52
+ return false
53
+ } else {
54
+ throw new Error(
55
+ `Failed to verify merkleroot for height ${height} because of an error: ${JSON.stringify(response.data)} `
56
+ )
57
+ }
58
+ }
59
+
60
+ async currentHeight(): Promise<number> {
61
+ try {
62
+ const requestOptions = {
63
+ method: 'GET',
64
+ headers: this.getHttpHeaders()
65
+ }
66
+
67
+ const response = await this.httpClient.request<{ height: number }>(
68
+ `${this.URL}/block/headers`,
69
+ requestOptions
70
+ )
71
+ if (response.ok) {
72
+ return response.data[0].height
73
+ } else {
74
+ throw new Error(
75
+ `Failed to get current height because of an error: ${JSON.stringify(response.data)} `
76
+ )
77
+ }
78
+ } catch (error) {
79
+ throw new Error(
80
+ `Failed to get current height because of an error: ${error instanceof Error ? error.message : String(error)}`
81
+ )
82
+ }
83
+ }
84
+
85
+ protected getHttpHeaders(): Record<string, string> {
86
+ const headers: Record<string, string> = {
87
+ Accept: 'application/json'
88
+ }
89
+
90
+ if (typeof this.apiKey === 'string' && this.apiKey.trim() !== '') {
91
+ headers.Authorization = this.apiKey
92
+ }
93
+
94
+ return headers
95
+ }
96
+ }