@bsv/wallet-toolbox 1.3.25 → 1.3.26
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.
- package/mobile/out/src/sdk/WalletServices.interfaces.d.ts +100 -0
- package/mobile/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/mobile/out/src/services/ServiceCollection.d.ts +28 -18
- package/mobile/out/src/services/ServiceCollection.d.ts.map +1 -1
- package/mobile/out/src/services/ServiceCollection.js +90 -38
- package/mobile/out/src/services/ServiceCollection.js.map +1 -1
- package/mobile/out/src/services/Services.d.ts +2 -9
- package/mobile/out/src/services/Services.d.ts.map +1 -1
- package/mobile/out/src/services/Services.js +12 -9
- package/mobile/out/src/services/Services.js.map +1 -1
- package/mobile/out/src/storage/StorageProvider.d.ts +6 -1
- package/mobile/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/mobile/out/src/storage/StorageProvider.js.map +1 -1
- package/mobile/package-lock.json +6 -6
- package/mobile/package.json +2 -2
- package/out/src/sdk/WalletServices.interfaces.d.ts +100 -0
- package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/out/src/services/ServiceCollection.d.ts +28 -18
- package/out/src/services/ServiceCollection.d.ts.map +1 -1
- package/out/src/services/ServiceCollection.js +90 -38
- package/out/src/services/ServiceCollection.js.map +1 -1
- package/out/src/services/Services.d.ts +2 -9
- package/out/src/services/Services.d.ts.map +1 -1
- package/out/src/services/Services.js +12 -9
- package/out/src/services/Services.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +2 -2
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +5 -0
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts +6 -1
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js +11 -1
- package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js.map +1 -1
- package/out/test/Wallet/local/localWallet.man.test.js +3 -1
- package/out/test/Wallet/local/localWallet.man.test.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/sdk/WalletServices.interfaces.ts +103 -0
- package/src/services/ServiceCollection.ts +114 -54
- package/src/services/Services.ts +15 -11
- package/src/storage/StorageKnex.ts +10 -3
- package/src/storage/StorageProvider.ts +7 -1
- package/src/storage/schema/entities/__tests/ProvenTxTests.test.ts +12 -1
- package/test/Wallet/local/localWallet.man.test.ts +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsv/wallet-toolbox",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.26",
|
|
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",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@bsv/auth-express-middleware": "^1.1.2",
|
|
34
34
|
"@bsv/payment-express-middleware": "^1.0.6",
|
|
35
|
-
"@bsv/sdk": "^1.5.
|
|
35
|
+
"@bsv/sdk": "^1.5.2",
|
|
36
36
|
"express": "^4.21.2",
|
|
37
37
|
"idb": "^8.0.2",
|
|
38
38
|
"knex": "^3.1.0",
|
|
@@ -168,6 +168,12 @@ export interface WalletServices {
|
|
|
168
168
|
* @param txid
|
|
169
169
|
*/
|
|
170
170
|
getBeefForTxid(txid: string): Promise<Beef>
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param reset if true, ends current interval and starts a new one.
|
|
174
|
+
* @returns a history of service calls made to the configured services.
|
|
175
|
+
*/
|
|
176
|
+
getServicesCallHistory(reset?: boolean) : ServicesCallHistory
|
|
171
177
|
}
|
|
172
178
|
|
|
173
179
|
export type ScriptHashFormat = 'hashLE' | 'hashBE' | 'script'
|
|
@@ -497,3 +503,100 @@ export type UpdateFiatExchangeRateService = (
|
|
|
497
503
|
targetCurrencies: string[],
|
|
498
504
|
options: WalletServicesOptions
|
|
499
505
|
) => Promise<FiatExchangeRates>
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Type for the service call history returned by Services.getServicesCallHistory.
|
|
509
|
+
*/
|
|
510
|
+
export type ServicesCallHistory = {
|
|
511
|
+
version: number
|
|
512
|
+
getMerklePath: ServiceCallHistory
|
|
513
|
+
getRawTx: ServiceCallHistory
|
|
514
|
+
postBeef: ServiceCallHistory
|
|
515
|
+
getUtxoStatus: ServiceCallHistory
|
|
516
|
+
getStatusForTxids: ServiceCallHistory
|
|
517
|
+
getScriptHashHistory: ServiceCallHistory
|
|
518
|
+
updateFiatExchangeRates: ServiceCallHistory
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Minimum data tracked for each service call.
|
|
523
|
+
*/
|
|
524
|
+
export interface ServiceCall {
|
|
525
|
+
/**
|
|
526
|
+
* string value must be Date's toISOString format.
|
|
527
|
+
*/
|
|
528
|
+
when: Date | string
|
|
529
|
+
msecs: number
|
|
530
|
+
/**
|
|
531
|
+
* true iff service provider successfully processed the request
|
|
532
|
+
* false iff service provider failed to process the request which includes thrown errors.
|
|
533
|
+
*/
|
|
534
|
+
success: boolean
|
|
535
|
+
/**
|
|
536
|
+
* Simple text summary of result. e.g. `not a valid utxo` or `valid utxo`
|
|
537
|
+
*/
|
|
538
|
+
result?: string
|
|
539
|
+
/**
|
|
540
|
+
* Error code and message iff success is false and a exception was thrown.
|
|
541
|
+
*/
|
|
542
|
+
error?: { message: string, code: string }
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Counts of service calls over a time interval.
|
|
547
|
+
*/
|
|
548
|
+
export interface ServiceCallHistoryCounts {
|
|
549
|
+
/**
|
|
550
|
+
* count of calls returning success true.
|
|
551
|
+
*/
|
|
552
|
+
success: number
|
|
553
|
+
/**
|
|
554
|
+
* count of calls returning success false.
|
|
555
|
+
*/
|
|
556
|
+
failure: number
|
|
557
|
+
/**
|
|
558
|
+
* of failures (success false), count of calls with valid error code and message.
|
|
559
|
+
*/
|
|
560
|
+
error: number
|
|
561
|
+
/**
|
|
562
|
+
* Counts are of calls over interval `since` to `until`.
|
|
563
|
+
* string value must be Date's toISOString format.
|
|
564
|
+
*/
|
|
565
|
+
since: Date | string
|
|
566
|
+
/**
|
|
567
|
+
* Counts are of calls over interval `since` to `until`.
|
|
568
|
+
* string value must be Date's toISOString format.
|
|
569
|
+
*/
|
|
570
|
+
until: Date | string
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* History of service calls for a single service, single provider.
|
|
575
|
+
*/
|
|
576
|
+
export interface ProviderCallHistory {
|
|
577
|
+
providerName: string
|
|
578
|
+
serviceName: string
|
|
579
|
+
/**
|
|
580
|
+
* Most recent service calls.
|
|
581
|
+
* Array length is limited by Services configuration.
|
|
582
|
+
*/
|
|
583
|
+
calls: ServiceCall[]
|
|
584
|
+
/**
|
|
585
|
+
* Counts since creation of Services instance.
|
|
586
|
+
*/
|
|
587
|
+
totalCounts: ServiceCallHistoryCounts
|
|
588
|
+
/**
|
|
589
|
+
* Entry [0] is always the current interval being extended by new calls.
|
|
590
|
+
* when `getServiceCallHistory` with `reset` true is called, a new interval with zero counts is added to the start of array.
|
|
591
|
+
* Array length is limited by Services configuration.
|
|
592
|
+
*/
|
|
593
|
+
resetCounts: ServiceCallHistoryCounts[]
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* History of service calls for a single service, all providers.
|
|
598
|
+
*/
|
|
599
|
+
export interface ServiceCallHistory {
|
|
600
|
+
serviceName: string
|
|
601
|
+
historyByProvider: Record<string, ProviderCallHistory>
|
|
602
|
+
}
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { WalletError } from "../sdk/WalletError";
|
|
2
|
+
import { ProviderCallHistory, ServiceCallHistory } from "../sdk/WalletServices.interfaces";
|
|
3
|
+
|
|
4
|
+
const MAX_RESET_COUNTS = 32
|
|
5
|
+
const MAX_CALL_HISTORY = 32
|
|
2
6
|
|
|
3
7
|
export class ServiceCollection<T> {
|
|
4
|
-
since: Date
|
|
5
8
|
services: { name: string; service: T }[]
|
|
6
9
|
_index: number
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Start of currentCounts interval. Initially instance construction time.
|
|
13
|
+
*/
|
|
14
|
+
readonly since: Date
|
|
15
|
+
_historyByProvider: Record<string, ProviderCallHistory> = {}
|
|
9
16
|
|
|
10
|
-
constructor(services?: { name: string; service: T }[]) {
|
|
17
|
+
constructor(public serviceName: string, services?: { name: string; service: T }[]) {
|
|
11
18
|
this.services = services || []
|
|
12
19
|
this._index = 0
|
|
13
20
|
this.since = new Date()
|
|
@@ -34,8 +41,8 @@ export class ServiceCollection<T> {
|
|
|
34
41
|
const i = this._index
|
|
35
42
|
const name = this.services[i].name
|
|
36
43
|
const service = this.services[i].service
|
|
37
|
-
const call = { name, when: new Date(),
|
|
38
|
-
return { name, service, call }
|
|
44
|
+
const call = { name, when: new Date(), msecs: 0, success: false, result: undefined, error: undefined }
|
|
45
|
+
return { serviceName: this.serviceName, providerName: name, service, call }
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
get allServicesToCall(): ServiceToCall<T>[] {
|
|
@@ -68,28 +75,44 @@ export class ServiceCollection<T> {
|
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
clone(): ServiceCollection<T> {
|
|
71
|
-
return new ServiceCollection([...this.services])
|
|
78
|
+
return new ServiceCollection(this.serviceName, [...this.services])
|
|
72
79
|
}
|
|
73
80
|
|
|
74
|
-
_addServiceCall(
|
|
75
|
-
|
|
81
|
+
_addServiceCall(providerName: string, call: ServiceCall): ProviderCallHistory {
|
|
82
|
+
const now = new Date()
|
|
83
|
+
let h = this._historyByProvider[providerName]
|
|
76
84
|
if (!h) {
|
|
77
|
-
h = {
|
|
78
|
-
|
|
85
|
+
h = {
|
|
86
|
+
serviceName: this.serviceName,
|
|
87
|
+
providerName: providerName,
|
|
88
|
+
calls: [],
|
|
89
|
+
totalCounts: { success: 0, failure: 0, error: 0, since: this.since, until: now },
|
|
90
|
+
resetCounts: [{ success: 0, failure: 0, error: 0, since: this.since, until: now }]
|
|
91
|
+
}
|
|
92
|
+
this._historyByProvider[providerName] = h
|
|
79
93
|
}
|
|
80
|
-
h.calls.
|
|
81
|
-
h.
|
|
82
|
-
h.
|
|
94
|
+
h.calls.unshift(call)
|
|
95
|
+
h.calls = h.calls.slice(0,MAX_CALL_HISTORY)
|
|
96
|
+
h.totalCounts.until = now
|
|
97
|
+
h.resetCounts[0].until = now
|
|
83
98
|
return h
|
|
84
99
|
}
|
|
85
100
|
|
|
101
|
+
getDuration(since: Date | string): number {
|
|
102
|
+
const now = new Date()
|
|
103
|
+
if (typeof since === 'string') since = new Date(since)
|
|
104
|
+
return now.getTime() - since.getTime()
|
|
105
|
+
}
|
|
106
|
+
|
|
86
107
|
addServiceCallSuccess(stc: ServiceToCall<T>, result?: string): void {
|
|
87
108
|
const call = stc.call
|
|
88
109
|
call.success = true
|
|
89
110
|
call.result = result
|
|
90
111
|
call.error = undefined
|
|
91
|
-
call.
|
|
92
|
-
this._addServiceCall(
|
|
112
|
+
call.msecs = this.getDuration(call.when)
|
|
113
|
+
const h = this._addServiceCall(stc.providerName, call)
|
|
114
|
+
h.totalCounts.success++
|
|
115
|
+
h.resetCounts[0].success++
|
|
93
116
|
}
|
|
94
117
|
|
|
95
118
|
addServiceCallFailure(stc: ServiceToCall<T>, result?: string): void {
|
|
@@ -97,8 +120,10 @@ export class ServiceCollection<T> {
|
|
|
97
120
|
call.success = false
|
|
98
121
|
call.result = result
|
|
99
122
|
call.error = undefined
|
|
100
|
-
call.
|
|
101
|
-
this._addServiceCall(this.name, call)
|
|
123
|
+
call.msecs = this.getDuration(call.when)
|
|
124
|
+
const h = this._addServiceCall(this.name, call)
|
|
125
|
+
h.totalCounts.failure++
|
|
126
|
+
h.resetCounts[0].failure++
|
|
102
127
|
}
|
|
103
128
|
|
|
104
129
|
addServiceCallError(stc: ServiceToCall<T>, error: WalletError): void {
|
|
@@ -106,66 +131,101 @@ export class ServiceCollection<T> {
|
|
|
106
131
|
call.success = false
|
|
107
132
|
call.result = undefined
|
|
108
133
|
call.error = error
|
|
109
|
-
call.
|
|
110
|
-
this._addServiceCall(this.name, call)
|
|
134
|
+
call.msecs = this.getDuration(call.when)
|
|
135
|
+
const h = this._addServiceCall(this.name, call)
|
|
136
|
+
h.totalCounts.failure++
|
|
137
|
+
h.totalCounts.error++
|
|
138
|
+
h.resetCounts[0].failure++
|
|
139
|
+
h.resetCounts[0].error++
|
|
111
140
|
}
|
|
112
141
|
|
|
113
142
|
/**
|
|
114
143
|
* @returns A copy of current service call history
|
|
115
144
|
*/
|
|
116
|
-
getServiceCallHistory(reset?: boolean):
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
countFailure: h.countFailure,
|
|
125
|
-
countSuccess: h.countSuccess,
|
|
126
|
-
since: h.since,
|
|
145
|
+
getServiceCallHistory(reset?: boolean): ServiceCallHistory {
|
|
146
|
+
const now = new Date()
|
|
147
|
+
const history: ServiceCallHistory = { serviceName: this.serviceName, historyByProvider: {} }
|
|
148
|
+
for (const name of Object.keys(this._historyByProvider)) {
|
|
149
|
+
const h = this._historyByProvider[name]
|
|
150
|
+
const c: ProviderCallHistory = {
|
|
151
|
+
serviceName: h.serviceName,
|
|
152
|
+
providerName: h.providerName,
|
|
127
153
|
calls: h.calls.map(c => ({
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
durationMsecs: c.durationMsecs,
|
|
154
|
+
when: dateToString(c.when),
|
|
155
|
+
msecs: c.msecs,
|
|
131
156
|
success: c.success,
|
|
132
157
|
result: c.result,
|
|
133
158
|
error: c.error ? { message: c.error.message, code: c.error.code } : undefined
|
|
134
|
-
}))
|
|
159
|
+
})),
|
|
160
|
+
totalCounts: {
|
|
161
|
+
success: h.totalCounts.success,
|
|
162
|
+
failure: h.totalCounts.failure,
|
|
163
|
+
error: h.totalCounts.error,
|
|
164
|
+
since: dateToString(h.totalCounts.since),
|
|
165
|
+
until: dateToString(h.totalCounts.until)
|
|
166
|
+
},
|
|
167
|
+
resetCounts: []
|
|
168
|
+
}
|
|
169
|
+
for (let i = 0; i < h.resetCounts.length; i++) {
|
|
170
|
+
const r = h.resetCounts[i]
|
|
171
|
+
c.resetCounts.push({
|
|
172
|
+
success: r.success,
|
|
173
|
+
failure: r.failure,
|
|
174
|
+
error: r.error,
|
|
175
|
+
since: dateToString(r.since),
|
|
176
|
+
until: dateToString(r.until)
|
|
177
|
+
})
|
|
135
178
|
}
|
|
179
|
+
history.historyByProvider[name] = c
|
|
136
180
|
if (reset) {
|
|
137
|
-
|
|
138
|
-
h.
|
|
139
|
-
|
|
140
|
-
h.
|
|
141
|
-
|
|
181
|
+
// Make sure intervals are continuous.
|
|
182
|
+
h.resetCounts[0].until = now
|
|
183
|
+
// insert a new resetCounts interval
|
|
184
|
+
h.resetCounts.unshift({
|
|
185
|
+
success: 0,
|
|
186
|
+
failure: 0,
|
|
187
|
+
error: 0,
|
|
188
|
+
// start of new interval
|
|
189
|
+
since: now,
|
|
190
|
+
// end of new interval, gets bumped with each new call added
|
|
191
|
+
until: now
|
|
192
|
+
})
|
|
193
|
+
// limit history to most recent intervals
|
|
194
|
+
h.resetCounts = h.resetCounts.slice(0, MAX_CALL_HISTORY)
|
|
142
195
|
}
|
|
143
196
|
}
|
|
144
|
-
return
|
|
197
|
+
return history
|
|
198
|
+
|
|
199
|
+
function dateToString(d: Date | string): string {
|
|
200
|
+
return typeof d === 'string' ? d : d.toISOString()
|
|
201
|
+
}
|
|
145
202
|
}
|
|
146
203
|
}
|
|
147
204
|
|
|
148
205
|
export interface ServiceCall {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
206
|
+
/**
|
|
207
|
+
* string value must be Date's toISOString format.
|
|
208
|
+
*/
|
|
209
|
+
when: Date | string
|
|
210
|
+
msecs: number
|
|
211
|
+
/**
|
|
212
|
+
* true iff service provider successfully processed the request
|
|
213
|
+
* false iff service provider failed to process the request which includes thrown errors.
|
|
214
|
+
*/
|
|
152
215
|
success: boolean
|
|
216
|
+
/**
|
|
217
|
+
* Simple text summary of result. e.g. `not a valid utxo` or `valid utxo`
|
|
218
|
+
*/
|
|
153
219
|
result?: string
|
|
220
|
+
/**
|
|
221
|
+
* Error code and message iff success is false and a exception was thrown.
|
|
222
|
+
*/
|
|
154
223
|
error?: { message: string, code: string }
|
|
155
224
|
}
|
|
156
225
|
|
|
157
|
-
export interface ServiceCallHistory {
|
|
158
|
-
name: string
|
|
159
|
-
calls: ServiceCall[]
|
|
160
|
-
count: number
|
|
161
|
-
countSuccess: number
|
|
162
|
-
countFailure: number
|
|
163
|
-
countError: number
|
|
164
|
-
since: Date
|
|
165
|
-
}
|
|
166
|
-
|
|
167
226
|
export interface ServiceToCall<T> {
|
|
168
|
-
|
|
227
|
+
providerName: string
|
|
228
|
+
serviceName: string
|
|
169
229
|
service: T
|
|
170
230
|
call: ServiceCall
|
|
171
231
|
}
|
package/src/services/Services.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Transaction as BsvTransaction, Beef, ChainTracker, Utils } from '@bsv/sdk'
|
|
2
2
|
import { asArray, asString, doubleSha256BE, sdk, sha256Hash, TableOutput, wait } from '../index.client'
|
|
3
|
-
import {
|
|
3
|
+
import { ServiceCollection } from './ServiceCollection'
|
|
4
4
|
import { createDefaultWalletServicesOptions } from './createDefaultWalletServicesOptions'
|
|
5
5
|
import { ChaintracksChainTracker } from './chaintracker'
|
|
6
6
|
import { WhatsOnChain } from './providers/WhatsOnChain'
|
|
@@ -8,6 +8,7 @@ import { updateChaintracksFiatExchangeRates, updateExchangeratesapi } from './pr
|
|
|
8
8
|
import { ARC } from './providers/ARC'
|
|
9
9
|
import { Bitails } from './providers/Bitails'
|
|
10
10
|
import { getBeefForTxid } from './providers/getBeefForTxid'
|
|
11
|
+
import { ServicesCallHistory } from '../sdk/WalletServices.interfaces'
|
|
11
12
|
|
|
12
13
|
export class Services implements sdk.WalletServices {
|
|
13
14
|
static createDefaultOptions(chain: sdk.Chain): sdk.WalletServicesOptions {
|
|
@@ -45,15 +46,15 @@ export class Services implements sdk.WalletServices {
|
|
|
45
46
|
this.bitails = new Bitails(this.chain)
|
|
46
47
|
|
|
47
48
|
//prettier-ignore
|
|
48
|
-
this.getMerklePathServices = new ServiceCollection<sdk.GetMerklePathService>()
|
|
49
|
+
this.getMerklePathServices = new ServiceCollection<sdk.GetMerklePathService>('getMerklePath')
|
|
49
50
|
.add({ name: 'WhatsOnChain', service: this.whatsonchain.getMerklePath.bind(this.whatsonchain) })
|
|
50
51
|
.add({ name: 'Bitails', service: this.bitails.getMerklePath.bind(this.bitails) })
|
|
51
52
|
|
|
52
53
|
//prettier-ignore
|
|
53
|
-
this.getRawTxServices = new ServiceCollection<sdk.GetRawTxService>()
|
|
54
|
+
this.getRawTxServices = new ServiceCollection<sdk.GetRawTxService>('getRawTx')
|
|
54
55
|
.add({ name: 'WhatsOnChain', service: this.whatsonchain.getRawTxResult.bind(this.whatsonchain) })
|
|
55
56
|
|
|
56
|
-
this.postBeefServices = new ServiceCollection<sdk.PostBeefService>()
|
|
57
|
+
this.postBeefServices = new ServiceCollection<sdk.PostBeefService>('postBeef')
|
|
57
58
|
if (this.arcGorillaPool) {
|
|
58
59
|
//prettier-ignore
|
|
59
60
|
this.postBeefServices.add({ name: 'GorillaPool', service: this.arcGorillaPool.postBeef.bind(this.arcGorillaPool) })
|
|
@@ -66,32 +67,33 @@ export class Services implements sdk.WalletServices {
|
|
|
66
67
|
;
|
|
67
68
|
|
|
68
69
|
//prettier-ignore
|
|
69
|
-
this.getUtxoStatusServices = new ServiceCollection<sdk.GetUtxoStatusService>()
|
|
70
|
+
this.getUtxoStatusServices = new ServiceCollection<sdk.GetUtxoStatusService>('getUtxoStatus')
|
|
70
71
|
.add({ name: 'WhatsOnChain', service: this.whatsonchain.getUtxoStatus.bind(this.whatsonchain) })
|
|
71
72
|
|
|
72
73
|
//prettier-ignore
|
|
73
|
-
this.getStatusForTxidsServices = new ServiceCollection<sdk.GetStatusForTxidsService>()
|
|
74
|
+
this.getStatusForTxidsServices = new ServiceCollection<sdk.GetStatusForTxidsService>('getStatusForTxids')
|
|
74
75
|
.add({ name: 'WhatsOnChain', service: this.whatsonchain.getStatusForTxids.bind(this.whatsonchain) })
|
|
75
76
|
|
|
76
77
|
//prettier-ignore
|
|
77
|
-
this.getScriptHashHistoryServices = new ServiceCollection<sdk.GetScriptHashHistoryService>()
|
|
78
|
+
this.getScriptHashHistoryServices = new ServiceCollection<sdk.GetScriptHashHistoryService>('getScriptHashHistory')
|
|
78
79
|
.add({ name: 'WhatsOnChain', service: this.whatsonchain.getScriptHashHistory.bind(this.whatsonchain) })
|
|
79
80
|
|
|
80
81
|
//prettier-ignore
|
|
81
|
-
this.updateFiatExchangeRateServices = new ServiceCollection<sdk.UpdateFiatExchangeRateService>()
|
|
82
|
+
this.updateFiatExchangeRateServices = new ServiceCollection<sdk.UpdateFiatExchangeRateService>('updateFiatExchangeRate')
|
|
82
83
|
.add({ name: 'ChaintracksService', service: updateChaintracksFiatExchangeRates })
|
|
83
84
|
.add({ name: 'exchangeratesapi', service: updateExchangeratesapi })
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
getServicesCallHistory(reset?: boolean) {
|
|
87
|
+
getServicesCallHistory(reset?: boolean) : ServicesCallHistory {
|
|
87
88
|
return {
|
|
88
|
-
version:
|
|
89
|
+
version: 2,
|
|
89
90
|
getMerklePath: this.getMerklePathServices.getServiceCallHistory(reset),
|
|
90
91
|
getRawTx: this.getRawTxServices.getServiceCallHistory(reset),
|
|
91
92
|
postBeef: this.postBeefServices.getServiceCallHistory(reset),
|
|
92
93
|
getUtxoStatus: this.getUtxoStatusServices.getServiceCallHistory(reset),
|
|
93
94
|
getStatusForTxids: this.getStatusForTxidsServices.getServiceCallHistory(reset),
|
|
94
|
-
getScriptHashHistory: this.getScriptHashHistoryServices.getServiceCallHistory(reset)
|
|
95
|
+
getScriptHashHistory: this.getScriptHashHistoryServices.getServiceCallHistory(reset),
|
|
96
|
+
updateFiatExchangeRates: this.updateFiatExchangeRateServices.getServiceCallHistory(reset)
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
|
|
@@ -319,6 +321,8 @@ export class Services implements sdk.WalletServices {
|
|
|
319
321
|
|
|
320
322
|
if (r.error)
|
|
321
323
|
services.addServiceCallError(stc, r.error)
|
|
324
|
+
else if (!r.rawTx)
|
|
325
|
+
services.addServiceCallSuccess(stc, `not found`)
|
|
322
326
|
else
|
|
323
327
|
services.addServiceCallFailure(stc)
|
|
324
328
|
|
|
@@ -23,12 +23,13 @@ import {
|
|
|
23
23
|
} from './schema/tables'
|
|
24
24
|
import { KnexMigrations } from './schema/KnexMigrations'
|
|
25
25
|
import { Knex } from 'knex'
|
|
26
|
-
import {
|
|
26
|
+
import { AdminStatsResult, StorageProvider, StorageProviderOptions } from './StorageProvider'
|
|
27
27
|
import { purgeData } from './methods/purgeData'
|
|
28
28
|
import { listActions } from './methods/listActionsKnex'
|
|
29
29
|
import { listOutputs } from './methods/listOutputsKnex'
|
|
30
30
|
import { DBType } from './StorageReader'
|
|
31
31
|
import { reviewStatus } from './methods/reviewStatus'
|
|
32
|
+
import { ServicesCallHistory } from '../sdk/WalletServices.interfaces'
|
|
32
33
|
|
|
33
34
|
export interface StorageKnexOptions extends StorageProviderOptions {
|
|
34
35
|
/**
|
|
@@ -1152,9 +1153,13 @@ export class StorageKnex extends StorageProvider implements sdk.WalletStoragePro
|
|
|
1152
1153
|
return entities
|
|
1153
1154
|
}
|
|
1154
1155
|
|
|
1155
|
-
async adminStats(adminIdentityKey: string): Promise<
|
|
1156
|
+
async adminStats(adminIdentityKey: string): Promise<AdminStatsResult> {
|
|
1156
1157
|
if (this.dbtype !== 'MySQL') throw new sdk.WERR_NOT_IMPLEMENTED('adminStats, only MySQL is supported')
|
|
1157
1158
|
|
|
1159
|
+
const monitorEvent = verifyOneOrNone(await this.findMonitorEvents({ partial: { event: 'ServiceCallHistory'}, orderDescending: true, paged: { limit: 1 } }))
|
|
1160
|
+
const monitorStats: ServicesCallHistory | undefined = monitorEvent ? JSON.parse(monitorEvent.details!) : undefined
|
|
1161
|
+
const servicesStats = this.getServices().getServicesCallHistory(true)
|
|
1162
|
+
|
|
1158
1163
|
const one_day_ago = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString()
|
|
1159
1164
|
const one_week_ago = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()
|
|
1160
1165
|
const one_month_ago = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString()
|
|
@@ -1295,7 +1300,9 @@ select
|
|
|
1295
1300
|
(select count(*) from output_tags where created_at > '${one_month_ago}') as tagsMonth,
|
|
1296
1301
|
(select count(*) from output_tags) as tagsTotal
|
|
1297
1302
|
`)
|
|
1298
|
-
const r:
|
|
1303
|
+
const r: AdminStatsResult = {
|
|
1304
|
+
monitorStats,
|
|
1305
|
+
servicesStats,
|
|
1299
1306
|
requestedBy: adminIdentityKey,
|
|
1300
1307
|
when: new Date().toISOString(),
|
|
1301
1308
|
usersDay,
|
|
@@ -40,6 +40,7 @@ import { createAction } from './methods/createAction'
|
|
|
40
40
|
import { internalizeAction } from './methods/internalizeAction'
|
|
41
41
|
import { StorageReaderWriter, StorageReaderWriterOptions } from './StorageReaderWriter'
|
|
42
42
|
import { EntityProvenTx, EntityProvenTxReq, EntitySyncState, EntityTransaction } from './schema/entities'
|
|
43
|
+
import { ServicesCallHistory } from '../sdk/WalletServices.interfaces'
|
|
43
44
|
|
|
44
45
|
export abstract class StorageProvider extends StorageReaderWriter implements sdk.WalletStorageProvider {
|
|
45
46
|
isDirty = false
|
|
@@ -106,7 +107,7 @@ export abstract class StorageProvider extends StorageReaderWriter implements sdk
|
|
|
106
107
|
abstract findOutputsAuth(auth: sdk.AuthId, args: sdk.FindOutputsArgs): Promise<TableOutput[]>
|
|
107
108
|
abstract insertCertificateAuth(auth: sdk.AuthId, certificate: TableCertificateX): Promise<number>
|
|
108
109
|
|
|
109
|
-
abstract adminStats(adminIdentityKey: string): Promise<
|
|
110
|
+
abstract adminStats(adminIdentityKey: string): Promise<AdminStatsResult>
|
|
110
111
|
|
|
111
112
|
override isStorageProvider(): boolean {
|
|
112
113
|
return true
|
|
@@ -773,3 +774,8 @@ export interface StorageAdminStats {
|
|
|
773
774
|
tagsMonth: number
|
|
774
775
|
tagsTotal: number
|
|
775
776
|
}
|
|
777
|
+
|
|
778
|
+
export interface AdminStatsResult extends StorageAdminStats {
|
|
779
|
+
servicesStats?: ServicesCallHistory
|
|
780
|
+
monitorStats?: ServicesCallHistory
|
|
781
|
+
}
|
|
@@ -136,7 +136,18 @@ describe('ProvenTx class method tests', () => {
|
|
|
136
136
|
}),
|
|
137
137
|
nLockTimeIsFinal: async () => true,
|
|
138
138
|
|
|
139
|
-
getBeefForTxid: async () => new bsv.Beef()
|
|
139
|
+
getBeefForTxid: async () => new bsv.Beef(),
|
|
140
|
+
|
|
141
|
+
getServicesCallHistory: () => ({
|
|
142
|
+
version: 1,
|
|
143
|
+
getMerklePath: { serviceName: '', historyByProvider: {} },
|
|
144
|
+
getRawTx: { serviceName: '', historyByProvider: {} },
|
|
145
|
+
postBeef: { serviceName: '', historyByProvider: {} },
|
|
146
|
+
getStatusForTxids: { serviceName: '', historyByProvider: {} },
|
|
147
|
+
getUtxoStatus: { serviceName: '', historyByProvider: {} },
|
|
148
|
+
getScriptHashHistory: { serviceName: '', historyByProvider: {} },
|
|
149
|
+
updateFiatExchangeRates: { serviceName: '', historyByProvider: {} }
|
|
150
|
+
})
|
|
140
151
|
}
|
|
141
152
|
|
|
142
153
|
// Call the method under test
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EntitySyncState, sdk } from '../../../src'
|
|
2
|
-
import { _tu } from '../../utils/TestUtilsWalletStorage'
|
|
2
|
+
import { _tu, logger } from '../../utils/TestUtilsWalletStorage'
|
|
3
3
|
import { specOpInvalidChange } from '../../../src/sdk'
|
|
4
4
|
import { createOneSatTestOutput, createSetup, LocalWalletTestOptions } from '../../utils/localWalletMethods'
|
|
5
5
|
|
|
@@ -32,9 +32,10 @@ describe('localWallet tests', () => {
|
|
|
32
32
|
expect(key.publicKey.toString()).toBe(setup.identityKey)
|
|
33
33
|
await setup.services.getRawTx('6dd8e416dfaf14c04899ccad2bf76a67c1d5598fece25cf4dcb7a076012b7d8d')
|
|
34
34
|
await setup.services.getRawTx('ac9cced61e2491be55061ce6577e0c59b909922ba92d5cc1cd754b10d721ab0e')
|
|
35
|
+
await setup.monitor.runOnce()
|
|
35
36
|
await setup.services.getRawTx('0000e416dfaf14c04899ccad2bf76a67c1d5598fece25cf4dcb7a076012b7d8d')
|
|
36
37
|
await setup.services.getRawTx('0000ced61e2491be55061ce6577e0c59b909922ba92d5cc1cd754b10d721ab0e')
|
|
37
|
-
await setup.monitor.
|
|
38
|
+
logger(await setup.monitor.runTask('ServiceCallHistory'))
|
|
38
39
|
await setup.wallet.destroy()
|
|
39
40
|
})
|
|
40
41
|
|