@bopen-io/wallet-toolbox 2.14.5 → 2.15.0-bopen.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +47 -2
  2. package/README.md +73 -7
  3. package/docs/client.md +3020 -2729
  4. package/docs/monitor.md +164 -153
  5. package/docs/services.md +856 -710
  6. package/docs/setup.md +46 -1
  7. package/docs/storage.md +1654 -1636
  8. package/docs/wallet.md +2090 -1842
  9. package/out/src/Setup.d.ts +10 -0
  10. package/out/src/Setup.d.ts.map +1 -1
  11. package/out/src/Setup.js +24 -0
  12. package/out/src/Setup.js.map +1 -1
  13. package/out/src/monitor/MonitorDaemon.d.ts +2 -0
  14. package/out/src/monitor/MonitorDaemon.d.ts.map +1 -1
  15. package/out/src/monitor/MonitorDaemon.js +9 -1
  16. package/out/src/monitor/MonitorDaemon.js.map +1 -1
  17. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts +5 -0
  18. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
  19. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +11 -3
  20. package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
  21. package/out/src/storage/StorageKnex.d.ts +3 -0
  22. package/out/src/storage/StorageKnex.d.ts.map +1 -1
  23. package/out/src/storage/StorageKnex.js +115 -207
  24. package/out/src/storage/StorageKnex.js.map +1 -1
  25. package/out/src/storage/adminServer/adminServer.d.ts.map +1 -1
  26. package/out/src/storage/adminServer/adminServer.js +3 -41
  27. package/out/src/storage/adminServer/adminServer.js.map +1 -1
  28. package/out/src/storage/adminServer/reqReviewQuery.d.ts +41 -0
  29. package/out/src/storage/adminServer/reqReviewQuery.d.ts.map +1 -0
  30. package/out/src/storage/adminServer/reqReviewQuery.js +67 -0
  31. package/out/src/storage/adminServer/reqReviewQuery.js.map +1 -0
  32. package/out/src/storage/index.all.d.ts +1 -0
  33. package/out/src/storage/index.all.d.ts.map +1 -1
  34. package/out/src/storage/index.all.js +1 -0
  35. package/out/src/storage/index.all.js.map +1 -1
  36. package/out/src/storage/knexPostgres.d.ts +16 -0
  37. package/out/src/storage/knexPostgres.d.ts.map +1 -0
  38. package/out/src/storage/knexPostgres.js +34 -0
  39. package/out/src/storage/knexPostgres.js.map +1 -0
  40. package/out/src/storage/methods/listActionsKnex.d.ts.map +1 -1
  41. package/out/src/storage/methods/listActionsKnex.js +0 -1
  42. package/out/src/storage/methods/listActionsKnex.js.map +1 -1
  43. package/out/src/storage/methods/listOutputsKnex.d.ts.map +1 -1
  44. package/out/src/storage/methods/listOutputsKnex.js +0 -1
  45. package/out/src/storage/methods/listOutputsKnex.js.map +1 -1
  46. package/out/src/storage/methods/purgeData.d.ts.map +1 -1
  47. package/out/src/storage/methods/purgeData.js +0 -3
  48. package/out/src/storage/methods/purgeData.js.map +1 -1
  49. package/out/src/storage/methods/reviewStatus.d.ts.map +1 -1
  50. package/out/src/storage/methods/reviewStatus.js +0 -3
  51. package/out/src/storage/methods/reviewStatus.js.map +1 -1
  52. package/out/src/storage/portable/index.js +38 -12
  53. package/out/src/storage/portable/index.js.map +1 -1
  54. package/out/src/storage/remoting/StorageServer.d.ts +17 -4
  55. package/out/src/storage/remoting/StorageServer.d.ts.map +1 -1
  56. package/out/src/storage/remoting/StorageServer.js +22 -13
  57. package/out/src/storage/remoting/StorageServer.js.map +1 -1
  58. package/out/src/storage/schema/KnexMigrations.d.ts +7 -2
  59. package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
  60. package/out/src/storage/schema/KnexMigrations.js +162 -60
  61. package/out/src/storage/schema/KnexMigrations.js.map +1 -1
  62. package/package.json +5 -4
package/CHANGELOG.md CHANGED
@@ -4,8 +4,53 @@ This document captures the history of significant changes to the wallet-toolbox
4
4
  The git commit history contains the details but is unable to draw
5
5
  attention to changes that materially alter behavior or extend functionality.
6
6
 
7
- ## wallet-toolbox 2.14.5
8
-
7
+ ## wallet-toolbox 2.15.0
8
+
9
+ - `StorageKnex` runs on Postgres through the knex `pg` client. Settings report
10
+ `dbtype: 'Postgres'`, and `StorageClient` accepts that value from a remote
11
+ `StorageServer`; older clients reject it. Install `pg` in the application.
12
+ - On a Postgres knex, `StorageKnex` sets an int8 parser on each connection it
13
+ acquires, so bigint columns and counts come back as numbers, as with mysql2
14
+ and better-sqlite3. The process-wide `pg.types` defaults are not changed.
15
+ `usePostgresInt8Numbers(knex)` applies the same parser to a knex directly, and
16
+ `Setup.createPostgresKnex(connectionJson, database)` creates one with it.
17
+ - Postgres runs at READ COMMITTED. The findOrInsert helpers retry a failed
18
+ insert as a find in the same transaction; on Postgres the insert now runs in
19
+ a savepoint so the transaction stays usable. `allocateChangeInput` re-checks
20
+ action batch reservations after taking the output row lock.
21
+ - On Postgres, migrations that add indexes to existing tables run outside a
22
+ transaction and use `CREATE INDEX CONCURRENTLY IF NOT EXISTS`; an invalid
23
+ index left by an interrupted build is dropped and rebuilt. `StorageKnex.migrate`
24
+ runs Postgres migrations one at a time so every other migration keeps its
25
+ journal row in its own transaction. SQLite and MySQL migrations are unchanged.
26
+ - `adminStats` and the admin server's proof request review run on MySQL and
27
+ Postgres. `adminStats` still reports `WERR_NOT_IMPLEMENTED` on SQLite.
28
+ - `MonitorDaemon` accepts `postgresConnection` (JSON node-postgres config), and
29
+ the operator `monitor-daemon` command accepts `--database-client postgres`.
30
+ - `ChaintracksStorageKnex` rejects a Postgres knex before running migrations.
31
+ - Paged `StorageKnex` find queries and the `get*ForUser` sync queries order rows
32
+ by key. Without an order, Postgres could return consecutive LIMIT/OFFSET pages
33
+ in different orders, so `getSyncChunk` repeated some rows and skipped others.
34
+ - `StorageServer.app` is public, so a host can mount the storage server in its
35
+ own Express application (`hostApp.use('/storage', server.app)`) instead of
36
+ calling `start()`. `port` is optional and only required by `start()`.
37
+ - `preRpcMiddleware` adds Express handlers on `POST /` after authentication,
38
+ the authenticated rate limit and payment, immediately before JSON-RPC
39
+ dispatch. A handler that responds stops the call before dispatch.
40
+ - `publicRoutes: false` removes the unauthenticated `GET /`, `/robots.txt` and
41
+ `/healthz` routes. Defaults are unchanged.
42
+
43
+ - Knex storage adds a unique index on `sync_states` (`userId`,
44
+ `storageIdentityKey`). Concurrent `findOrInsertSyncStateAuth` calls for a new
45
+ source could each insert a row, after which every sync with that source failed
46
+ with `Storage identity has conflicting sync states`. The losing insert now
47
+ re-reads the row that won. The migration deletes existing duplicates, keeping
48
+ the oldest row; when the duplicates had different storage names, the kept row
49
+ restarts as a new sync state because its checkpoint may belong to a different
50
+ source database.
51
+ - BRC-38 import keeps one sync state per storage identity. An export holding
52
+ several for one identity imports the oldest under the same rule, and merge
53
+ updates the target's row for that identity even when its storage name differs.
9
54
  - `WalletPermissionsManager` retires no-send transaction ownership and reference
10
55
  aliases when `createAction` or `signAction` reports them as `sending` or
11
56
  `unproven`, including sendWith-only calls and successful members of an
package/README.md CHANGED
@@ -66,16 +66,23 @@ journal before recovery; do not delete journal rows or wallet data blindly.
66
66
  ### Postgres storage
67
67
 
68
68
  `StorageKnex` runs on Postgres through the knex `pg` client. Install `pg` in the
69
- application and pass a Postgres knex:
69
+ application. Settings report `dbtype: 'Postgres'`; remote clients older than
70
+ this release reject that value.
70
71
 
71
- ```ts
72
- import { knex as makeKnex } from 'knex'
72
+ node-postgres returns int8 (bigint columns, counts) as strings by default.
73
+ `StorageKnex` sets a parser on each connection its knex acquires so these come
74
+ back as numbers, as with mysql2 and better-sqlite3. The process-wide `pg.types`
75
+ defaults are not changed. `Setup.createPostgresKnex(connectionJson, database)`
76
+ creates a knex with the same parser installed.
73
77
 
74
- const knex = makeKnex({ client: 'pg', connection: { host, port, user, password, database } })
75
- const storage = new StorageKnex({ ...StorageKnex.defaultOptions(), chain: 'main', knex })
76
- ```
78
+ Postgres migrations run one at a time. Migrations that add indexes to existing
79
+ tables run outside a transaction and use `CREATE INDEX CONCURRENTLY`, so writes
80
+ continue while an index is built. `MonitorDaemon` takes a `postgresConnection`
81
+ (JSON node-postgres config). `ChaintracksStorageKnex` does not support Postgres.
77
82
 
78
- `ChaintracksStorageKnex` and `adminStats` do not support Postgres.
83
+ Set `RUNPOSTGRES=1` and `POSTGRES_CONNECTION` (JSON node-postgres connection
84
+ config) to include Postgres in the Knex test suites. Test databases are created
85
+ on that server as needed.
79
86
 
80
87
  ## Overview
81
88
 
@@ -278,6 +285,10 @@ serialized RPC response exceeds the service ceiling, remote clients retry the
278
285
  read-only request with a smaller chunk budget and remember the working limit
279
286
  for the rest of the session.
280
287
 
288
+ Knex storage keeps one sync state per user and source storage identity, enforced
289
+ by a unique index. Concurrent registrations of the same source return the row the
290
+ first caller inserted.
291
+
281
292
  Output synchronization requires a local mapping for every non-null source basket
282
293
  ID. A missing mapping rejects the page so its transaction and checkpoint can roll
283
294
  back; retry after transferring the missing basket. Newer source updates apply
@@ -1024,6 +1035,61 @@ Run `StorageKnex.migrate(...)` before constructing the manager during an
1024
1035
  upgrade. `makeAvailable()` validates and loads an already-migrated database; it
1025
1036
  does not apply schema changes.
1026
1037
 
1038
+ ### Mounting StorageServer in an Express application
1039
+
1040
+ `server.app` is the configured Express application. Mount it in a host
1041
+ application instead of calling `start()`; `port` and `http` are only used by
1042
+ `start()`.
1043
+
1044
+ ```typescript
1045
+ import express from 'express'
1046
+ import { SessionManager } from '@bsv/sdk'
1047
+ import { AuthRequest, createAuthMiddleware } from '@bsv/auth-express-middleware'
1048
+ import { StorageServer } from '@bsv/wallet-toolbox'
1049
+
1050
+ // Use KnexSessionManager when the host runs more than one process.
1051
+ const sessionManager = new SessionManager()
1052
+
1053
+ const storageServer = new StorageServer(storage, {
1054
+ wallet,
1055
+ monetize: false,
1056
+ sessionManager,
1057
+ // Leave GET /, /robots.txt and /healthz to the host.
1058
+ publicRoutes: false,
1059
+ preRpcMiddleware: [
1060
+ async (req, res, next) => {
1061
+ if (await overQuota((req as AuthRequest).auth.identityKey, req.body.method)) {
1062
+ res.status(507).json({ status: 'error', code: 'ERR_QUOTA_EXCEEDED' })
1063
+ return
1064
+ }
1065
+ next()
1066
+ }
1067
+ ]
1068
+ })
1069
+
1070
+ const app = express()
1071
+ app.use('/storage', storageServer.app)
1072
+ app.use(express.json())
1073
+ app.use(createAuthMiddleware({ wallet, sessionManager }))
1074
+ // ...host routes
1075
+ app.listen(8080)
1076
+ ```
1077
+
1078
+ Clients connect with `new StorageClient(wallet, 'https://host.example/storage')`.
1079
+ `AuthFetch` sends the BRC-104 handshake to the origin's `/.well-known/auth`,
1080
+ not to the mount path, so the host must answer it with its own auth middleware
1081
+ using the same `wallet` and the same `sessionManager` as the storage server.
1082
+ Mount the storage server before the host's auth middleware and body parsers;
1083
+ the storage app authenticates and parses its own requests. It keeps its own
1084
+ security headers, CORS, concurrency and rate limits, and inherits the host's
1085
+ `trust proxy` setting unless `trustProxy` is set.
1086
+
1087
+ `preRpcMiddleware` handlers run on JSON-RPC `POST /` requests after
1088
+ authentication, the authenticated rate limit and, when `monetize` is set, the
1089
+ payment middleware. They see `req.auth` and the parsed body. A handler that
1090
+ responds instead of calling `next()` stops the call before dispatch. They do not
1091
+ run on the action batch upload routes.
1092
+
1027
1093
  ## Development
1028
1094
 
1029
1095
  ### Overlay identity verification