@bsv/wallet-toolbox 1.2.35 → 1.2.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/wallet-toolbox",
3
- "version": "1.2.35",
3
+ "version": "1.2.36",
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",
@@ -31,7 +31,7 @@
31
31
  "homepage": "https://github.com/bitcoin-sv/wallet-toolbox#readme",
32
32
  "dependencies": {
33
33
  "@bsv/auth-express-middleware": "^1.1.2",
34
- "@bsv/payment-express-middleware": "^1.0.5",
34
+ "@bsv/payment-express-middleware": "^1.0.6",
35
35
  "@bsv/sdk": "^1.4.18",
36
36
  "express": "^4.21.2",
37
37
  "knex": "^3.1.0",
@@ -1,4 +1,4 @@
1
- import { WalletOutput } from '@bsv/sdk'
1
+ import { Beef, WalletOutput } from '@bsv/sdk'
2
2
  import { sdk, Services, Setup, StorageKnex, TableUser } from '../../../src'
3
3
  import { _tu, TuEnv } from '../../utils/TestUtilsWalletStorage'
4
4
  import { specOpInvalidChange, ValidListOutputsArgs, WERR_REVIEW_ACTIONS } from '../../../src/sdk'
@@ -146,7 +146,7 @@ describe('localWallet2 tests', () => {
146
146
 
147
147
  test('6 review and unfail false doubleSpends', async () => {
148
148
  const { env, storage, services } = await createMainReviewSetup()
149
- let offset = 900
149
+ let offset = 1100
150
150
  const limit = 100
151
151
  let allUnfails: number[] = []
152
152
  for (;;) {
@@ -200,6 +200,14 @@ describe('localWallet2 tests', () => {
200
200
  }
201
201
  await storage.destroy()
202
202
  })
203
+
204
+ test('8 jackie Beef', async () => {
205
+ const setup = await createSetup(chain, options)
206
+ const beef = Beef.fromBinary(beefJackie)
207
+ console.log(beef.toLogString())
208
+ const ok = beef.verify(await setup.services.getChainTracker())
209
+ await setup.wallet.destroy()
210
+ })
203
211
  })
204
212
 
205
213
  async function createMainReviewSetup(): Promise<{
@@ -223,3 +231,6 @@ async function createMainReviewSetup(): Promise<{
223
231
  await storage.makeAvailable()
224
232
  return { env, storage, services }
225
233
  }
234
+
235
+ const beefJackie = [
236
+ 1, 1, 1, 1, 196, 222, 98, 76, 119, 112, 138, 49, 125, 79, 3, 8, 17, 96, 88, 134, 18, 94, 233, 6, 43, 58, 55, 200, 53, 21, 225, 58, 243, 130, 114, 64, 2, 0, 190, 239, 0, 1, 0, 1, 0, 0, 0, 1, 157, 193, 59, 124, 10, 214, 21, 108, 182, 51, 203, 122, 124, 52, 230, 65, 248, 166, 3, 136, 224, 45, 213, 116, 91, 81, 101, 168, 142, 252, 196, 20, 110, 0, 0, 0, 107, 72, 48, 69, 2, 33, 0, 144, 86, 132, 240, 56, 253, 101, 20, 254, 1, 184, 144, 98, 236, 225, 242, 239, 88, 99, 196, 58, 33, 141, 79, 234, 140, 7, 22, 254, 140, 65, 83, 2, 32, 113, 198, 86, 176, 19, 16, 165, 168, 5, 227, 70, 44, 5, 22, 144, 179, 172, 170, 13, 148, 3, 236, 35, 2, 74, 238, 235, 84, 148, 192, 102, 138, 65, 33, 3, 15, 101, 106, 207, 42, 192, 187, 51, 59, 128, 27, 240, 244, 240, 4, 224, 230, 41, 166, 89, 216, 46, 7, 24, 242, 180, 20, 90, 12, 57, 59, 144, 255, 255, 255, 255, 2, 136, 19, 0, 0, 0, 0, 0, 0, 25, 118, 169, 20, 240, 178, 178, 204, 51, 126, 211, 251, 43, 177, 154, 94, 189, 29, 53, 41, 220, 136, 142, 80, 136, 172, 208, 140, 0, 0, 0, 0, 0, 0, 25, 118, 169, 20, 217, 48, 110, 108, 236, 100, 116, 90, 181, 114, 45, 176, 198, 216, 150, 134, 16, 251, 10, 177, 136, 172, 0, 0, 0, 0]
@@ -0,0 +1,183 @@
1
+ import { WalletOutput } from '@bsv/sdk'
2
+ import { sdk, Services, Setup, StorageKnex, TableOutput, TableUser, verifyOne, verifyOneOrNone } from '../../../src'
3
+ import { _tu, TuEnv } from '../../utils/TestUtilsWalletStorage'
4
+ import { specOpInvalidChange, ValidListOutputsArgs, WERR_REVIEW_ACTIONS } from '../../../src/sdk'
5
+ import {
6
+ burnOneSatTestOutput,
7
+ createOneSatTestOutput,
8
+ createSetup,
9
+ doubleSpendOldChange,
10
+ LocalWalletTestOptions,
11
+ recoverOneSatTestOutputs
12
+ } from '../../utils/localWalletMethods'
13
+
14
+ import * as dotenv from 'dotenv'
15
+ dotenv.config()
16
+
17
+ const chain: sdk.Chain = 'main'
18
+
19
+ const options: LocalWalletTestOptions = {
20
+ setActiveClient: true,
21
+ useMySQLConnectionForClient: true,
22
+ useTestIdentityKey: false,
23
+ useIdentityKey2: false
24
+ }
25
+
26
+ describe('operations1 tests', () => {
27
+ jest.setTimeout(99999999)
28
+
29
+ test('0 review and release all production invalid change utxos', async () => {
30
+ const { env, storage } = await createMainReviewSetup()
31
+ const users = await storage.findUsers({ partial: {} })
32
+ const withInvalid: Record<number, { user: TableUser; outputs: WalletOutput[]; total: number }> = {}
33
+ const vargs: ValidListOutputsArgs = {
34
+ basket: specOpInvalidChange,
35
+ tags: ['release'],
36
+ tagQueryMode: 'all',
37
+ includeLockingScripts: false,
38
+ includeTransactions: false,
39
+ includeCustomInstructions: false,
40
+ includeTags: false,
41
+ includeLabels: false,
42
+ limit: 0,
43
+ offset: 0,
44
+ seekPermission: false,
45
+ knownTxids: []
46
+ }
47
+ let log = ''
48
+ for (const user of users) {
49
+ const { userId } = user
50
+ const auth = { userId, identityKey: '' }
51
+ let r = await storage.listOutputs(auth, vargs)
52
+ if (r.totalOutputs > 0) {
53
+ const total: number = r.outputs.reduce((s, o) => (s += o.satoshis), 0)
54
+ log += `userId ${userId}: ${r.totalOutputs} unspendable utxos, total ${total}, ${user.identityKey}\n`
55
+ for (const o of r.outputs) {
56
+ log += ` ${o.outpoint} ${o.satoshis}\n`
57
+ }
58
+ withInvalid[userId] = { user, outputs: r.outputs, total }
59
+ }
60
+ }
61
+ console.log(log || 'Found zero invalid change outputs.')
62
+ await storage.destroy()
63
+ })
64
+
65
+ test('6 review and unfail false doubleSpends', async () => {
66
+ const { env, storage, services } = await createMainReviewSetup()
67
+ let offset = 2200
68
+ const limit = 100
69
+ let allUnfails: number[] = []
70
+ for (; ;) {
71
+ let log = ''
72
+ const unfails: number[] = []
73
+ const reqs = await storage.findProvenTxReqs({ partial: { status: 'doubleSpend' }, paged: { limit, offset } })
74
+ for (const req of reqs) {
75
+ const gsr = await services.getStatusForTxids([req.txid])
76
+ if (gsr.results[0].status !== 'unknown') {
77
+ log += `unfail ${req.provenTxReqId} ${req.txid}\n`
78
+ unfails.push(req.provenTxReqId)
79
+ }
80
+ }
81
+ console.log(`DoubleSpends OFFSET: ${offset} ${unfails.length} unfails\n${log}`)
82
+ allUnfails = allUnfails.concat(unfails)
83
+ if (reqs.length < limit) break
84
+ offset += reqs.length
85
+ }
86
+ for (const id of allUnfails) {
87
+ await storage.updateProvenTxReq(id, { status: 'unfail' })
88
+ }
89
+ await storage.destroy()
90
+ })
91
+
92
+ test('7 review and unfail false invalids', async () => {
93
+ const { env, storage, services } = await createMainReviewSetup()
94
+ let offset = 400
95
+ const limit = 100
96
+ let allUnfails: number[] = []
97
+ for (; ;) {
98
+ let log = ''
99
+ const unfails: number[] = []
100
+ const reqs = await storage.findProvenTxReqs({ partial: { status: 'invalid' }, paged: { limit, offset } })
101
+ for (const req of reqs) {
102
+ if (!req.txid || !req.rawTx) continue
103
+ const gsr = await services.getStatusForTxids([req.txid])
104
+ if (gsr.results[0].status !== 'unknown') {
105
+ log += `unfail ${req.provenTxReqId} ${req.txid}\n`
106
+ unfails.push(req.provenTxReqId)
107
+ }
108
+ }
109
+ console.log(`Failed OFFSET: ${offset} ${unfails.length} unfails\n${log}`)
110
+ allUnfails = allUnfails.concat(unfails)
111
+ if (reqs.length < limit) break
112
+ offset += reqs.length
113
+ }
114
+ for (const id of allUnfails) {
115
+ await storage.updateProvenTxReq(id, { status: 'unfail' })
116
+ }
117
+ await storage.destroy()
118
+ })
119
+
120
+ test.skip('8 re-internalize failed WUI exports', async () => {
121
+ const { env, storage, services } = await createMainReviewSetup()
122
+ const user0 = verifyOne(await storage.findUsers({ partial: { userId: 2 } }))
123
+ const users = await storage.findUsers({ partial: { userId: 141 } }) // 111, 141
124
+ for (const user of users) {
125
+ const { userId, identityKey } = user
126
+ const [outputs] = await storage.knex.raw<TableOutput[][]>(`
127
+ SELECT f.* FROM outputs as f where f.userId = 2 and not f.customInstructions is null
128
+ and JSON_EXTRACT(f.customInstructions, '$.payee') = '${identityKey}'
129
+ and not exists(select * from outputs as r where r.userId = ${userId} and r.txid = f.txid)
130
+ `)
131
+ if (outputs.length > 0)
132
+ console.log(`userId ${userId} ${identityKey} ${outputs.length} outputs`)
133
+ for (const output of outputs) {
134
+ const req = verifyOneOrNone(await storage.findProvenTxReqs({ partial: { txid: output.txid, status: 'completed' } }))
135
+ const { type, derivationPrefix, derivationSuffix, payee } = JSON.parse(output.customInstructions!)
136
+ if (req && type === 'BRC29' && derivationPrefix && derivationSuffix) {
137
+ const beef = await storage.getBeefForTransaction(req.txid, {})
138
+ // {"type":"BRC29","derivationPrefix":"LDFooHSsXzw=","derivationSuffix":"4f4ixKv+6SY=","payee":"0352caa755d5b6279e15e47e096db908e7c4a73a31775e7e8720bdd4cf2d44873a"}
139
+ await storage.internalizeAction({ userId, identityKey: user.identityKey }, {
140
+ tx: beef.toBinaryAtomic(req.txid),
141
+ outputs: [{
142
+ outputIndex: 0,
143
+ protocol: 'wallet payment',
144
+ paymentRemittance: {
145
+ derivationPrefix: derivationPrefix,
146
+ derivationSuffix: derivationSuffix,
147
+ senderIdentityKey: user0.identityKey,
148
+ }
149
+ }],
150
+ description: 'Internalizing export funds tx into foreign wallet'
151
+ })
152
+ console.log('internalize', userId, output.txid)
153
+ }
154
+ }
155
+ }
156
+ /*
157
+ */
158
+ await storage.destroy()
159
+ })
160
+
161
+ })
162
+
163
+ async function createMainReviewSetup(): Promise<{
164
+ env: TuEnv
165
+ storage: StorageKnex
166
+ services: Services
167
+ }> {
168
+ const env = _tu.getEnv('main')
169
+ const knex = Setup.createMySQLKnex(process.env.MAIN_CLOUD_MYSQL_CONNECTION!)
170
+ const storage = new StorageKnex({
171
+ chain: env.chain,
172
+ knex: knex,
173
+ commissionSatoshis: 0,
174
+ commissionPubKeyHex: undefined,
175
+ feeModel: { model: 'sat/kb', value: 1 }
176
+ })
177
+ const servicesOptions = Services.createDefaultOptions(env.chain)
178
+ if (env.whatsonchainApiKey) servicesOptions.whatsOnChainApiKey = env.whatsonchainApiKey
179
+ const services = new Services(servicesOptions)
180
+ storage.setServices(services)
181
+ await storage.makeAvailable()
182
+ return { env, storage, services }
183
+ }