@bsv/wallet-toolbox 1.1.51 → 1.1.53
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/out/src/storage/methods/listOutputs.d.ts.map +1 -1
- package/out/src/storage/methods/listOutputs.js +80 -12
- package/out/src/storage/methods/listOutputs.js.map +1 -1
- package/out/src/storage/schema/entities/Transaction.js +2 -2
- package/out/src/storage/schema/entities/Transaction.js.map +1 -1
- package/out/test/Wallet/local/localWallet.man.test.d.ts.map +1 -1
- package/out/test/Wallet/local/localWallet.man.test.js +2 -1
- package/out/test/Wallet/local/localWallet.man.test.js.map +1 -1
- package/out/test/Wallet/specOps/specOps.man.test.d.ts +2 -0
- package/out/test/Wallet/specOps/specOps.man.test.d.ts.map +1 -0
- package/out/test/Wallet/specOps/specOps.man.test.js +49 -0
- package/out/test/Wallet/specOps/specOps.man.test.js.map +1 -0
- package/out/test/utils/TestUtilsWalletStorage.d.ts +1 -0
- package/out/test/utils/TestUtilsWalletStorage.d.ts.map +1 -1
- package/out/test/utils/TestUtilsWalletStorage.js +20 -4
- package/out/test/utils/TestUtilsWalletStorage.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/storage/methods/listOutputs.ts +112 -12
- package/src/storage/schema/entities/Transaction.ts +2 -2
- package/test/Wallet/local/localWallet.man.test.ts +2 -1
- package/test/Wallet/specOps/specOps.man.test.ts +58 -0
- package/test/utils/TestUtilsWalletStorage.ts +24 -5
package/package.json
CHANGED
|
@@ -7,6 +7,89 @@ import {
|
|
|
7
7
|
import { TableOutput, TableOutputBasket, TableOutputTag } from '../index.client'
|
|
8
8
|
import { asString, sdk, verifyId, verifyOne } from '../../index.client'
|
|
9
9
|
import { StorageKnex } from '../StorageKnex'
|
|
10
|
+
import { ValidListOutputsArgs } from '../../sdk'
|
|
11
|
+
|
|
12
|
+
interface SpecOp {
|
|
13
|
+
name: string
|
|
14
|
+
useBasket?: string
|
|
15
|
+
ignoreLimit?: boolean
|
|
16
|
+
resultFromOutputs?: (
|
|
17
|
+
s: StorageKnex,
|
|
18
|
+
vargs: ValidListOutputsArgs,
|
|
19
|
+
outputs: TableOutput[]
|
|
20
|
+
) => Promise<ListOutputsResult>
|
|
21
|
+
filterOutputs?: (
|
|
22
|
+
s: StorageKnex,
|
|
23
|
+
vargs: ValidListOutputsArgs,
|
|
24
|
+
outputs: TableOutput[]
|
|
25
|
+
) => Promise<TableOutput[]>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const basketToSpecOp: Record<string, SpecOp> = {
|
|
29
|
+
f61dc9289ceea604247ebde125b93a4099931f69c0e95ecd43ce0a480b9bb6c9: {
|
|
30
|
+
name: 'reserved...'
|
|
31
|
+
},
|
|
32
|
+
'69a57cc2b34058d5218927ecfd3e9e4254d8395b6fda9d57c689c753c6d6cad5': {
|
|
33
|
+
name: 'reserved...'
|
|
34
|
+
},
|
|
35
|
+
'893b7646de0e1c9f741bd6e9169b76a8847ae34adef7bef1e6a285371206d2e8': {
|
|
36
|
+
name: 'totalOutputsIsWalletBalance',
|
|
37
|
+
useBasket: 'default',
|
|
38
|
+
ignoreLimit: true,
|
|
39
|
+
resultFromOutputs: async (
|
|
40
|
+
s: StorageKnex,
|
|
41
|
+
vargs: ValidListOutputsArgs,
|
|
42
|
+
outputs: TableOutput[]
|
|
43
|
+
): Promise<ListOutputsResult> => {
|
|
44
|
+
let totalOutputs = 0
|
|
45
|
+
for (const o of outputs) totalOutputs += o.satoshis
|
|
46
|
+
return { totalOutputs, outputs: [] }
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
'5a76fd430a311f8bc0553859061710a4475c19fed46e2ff95969aa918e612e57': {
|
|
50
|
+
name: 'invalidChangeOutputs',
|
|
51
|
+
useBasket: 'default',
|
|
52
|
+
ignoreLimit: true,
|
|
53
|
+
filterOutputs: async (
|
|
54
|
+
s: StorageKnex,
|
|
55
|
+
vargs: ValidListOutputsArgs,
|
|
56
|
+
outputs: TableOutput[]
|
|
57
|
+
): Promise<TableOutput[]> => {
|
|
58
|
+
const filteredOutputs: TableOutput[] = []
|
|
59
|
+
let ok = false
|
|
60
|
+
|
|
61
|
+
for (const o of outputs) {
|
|
62
|
+
if (o.lockingScript && o.lockingScript.length > 0) {
|
|
63
|
+
const r = await s
|
|
64
|
+
.getServices()
|
|
65
|
+
.getUtxoStatus(asString(o.lockingScript), 'script')
|
|
66
|
+
if (r.status === 'success' && r.isUtxo && r.details?.length > 0) {
|
|
67
|
+
if (
|
|
68
|
+
r.details.some(
|
|
69
|
+
d =>
|
|
70
|
+
d.txid === o.txid &&
|
|
71
|
+
d.satoshis === o.satoshis &&
|
|
72
|
+
d.index === o.vout
|
|
73
|
+
)
|
|
74
|
+
) {
|
|
75
|
+
ok = true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!ok) {
|
|
81
|
+
filteredOutputs.push(o)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (vargs.tags[0] === 'release') {
|
|
85
|
+
for (const o of filteredOutputs) {
|
|
86
|
+
await s.updateOutput(o.outputId, { spendable: false })
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return filteredOutputs
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
10
93
|
|
|
11
94
|
export async function listOutputs(
|
|
12
95
|
dsk: StorageKnex,
|
|
@@ -38,20 +121,26 @@ export async function listOutputs(
|
|
|
38
121
|
}
|
|
39
122
|
*/
|
|
40
123
|
|
|
124
|
+
let specOp: SpecOp | undefined = undefined
|
|
41
125
|
let basketId: number | undefined = undefined
|
|
42
126
|
const basketsById: Record<number, TableOutputBasket> = {}
|
|
43
127
|
if (vargs.basket) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
128
|
+
let b = vargs.basket
|
|
129
|
+
specOp = basketToSpecOp[b]
|
|
130
|
+
b = specOp ? (specOp.useBasket ? specOp.useBasket : '') : b
|
|
131
|
+
if (b) {
|
|
132
|
+
const baskets = await dsk.findOutputBaskets({
|
|
133
|
+
partial: { userId, name: b },
|
|
134
|
+
trx
|
|
135
|
+
})
|
|
136
|
+
if (baskets.length !== 1) {
|
|
137
|
+
// If basket does not exist, result is no outputs.
|
|
138
|
+
return r
|
|
139
|
+
}
|
|
140
|
+
const basket = baskets[0]
|
|
141
|
+
basketId = basket.basketId!
|
|
142
|
+
basketsById[basketId!] = basket
|
|
51
143
|
}
|
|
52
|
-
const basket = baskets[0]
|
|
53
|
-
basketId = basket.basketId!
|
|
54
|
-
basketsById[basketId!] = basket
|
|
55
144
|
}
|
|
56
145
|
|
|
57
146
|
let tagIds: number[] = []
|
|
@@ -132,9 +221,20 @@ export async function listOutputs(
|
|
|
132
221
|
: makeWithTagsQueries()
|
|
133
222
|
|
|
134
223
|
// Sort order when limit and offset are possible must be ascending for determinism.
|
|
135
|
-
q.limit(limit).offset(offset)
|
|
224
|
+
if (!specOp || !specOp.ignoreLimit) q.limit(limit).offset(offset)
|
|
136
225
|
|
|
137
|
-
|
|
226
|
+
q.orderBy('outputId', 'asc')
|
|
227
|
+
|
|
228
|
+
let outputs: TableOutput[] = await q
|
|
229
|
+
|
|
230
|
+
if (specOp) {
|
|
231
|
+
if (specOp.filterOutputs)
|
|
232
|
+
outputs = await specOp.filterOutputs(dsk, vargs, outputs)
|
|
233
|
+
if (specOp.resultFromOutputs) {
|
|
234
|
+
const r = await specOp.resultFromOutputs(dsk, vargs, outputs)
|
|
235
|
+
return r
|
|
236
|
+
}
|
|
237
|
+
}
|
|
138
238
|
|
|
139
239
|
if (!limit || outputs.length < limit) r.totalOutputs = outputs.length
|
|
140
240
|
else {
|
|
@@ -242,7 +242,7 @@ export class EntityTransaction extends EntityBase<TableTransaction> {
|
|
|
242
242
|
(ei.provenTxId &&
|
|
243
243
|
eo.provenTxId !==
|
|
244
244
|
(syncMap
|
|
245
|
-
? syncMap.
|
|
245
|
+
? syncMap.provenTx.idMap[verifyId(ei.provenTxId)]
|
|
246
246
|
: ei.provenTxId))
|
|
247
247
|
)
|
|
248
248
|
return false
|
|
@@ -303,7 +303,7 @@ export class EntityTransaction extends EntityBase<TableTransaction> {
|
|
|
303
303
|
this.isOutgoing = ei.isOutgoing
|
|
304
304
|
this.status = ei.status
|
|
305
305
|
this.provenTxId = ei.provenTxId
|
|
306
|
-
? syncMap.
|
|
306
|
+
? syncMap.provenTx.idMap[ei.provenTxId]
|
|
307
307
|
: undefined
|
|
308
308
|
this.satoshis = ei.satoshis
|
|
309
309
|
this.txid = ei.txid
|
|
@@ -163,7 +163,8 @@ async function createSetup(chain: sdk.Chain): Promise<TestWalletNoSetup> {
|
|
|
163
163
|
rootKeyHex: env.devKeys[env.testIdentityKey],
|
|
164
164
|
filePath: env.testFilePath,
|
|
165
165
|
setActiveClient: false,
|
|
166
|
-
addLocalBackup: false
|
|
166
|
+
addLocalBackup: false,
|
|
167
|
+
useMySQLConnectionForClient: false
|
|
167
168
|
})
|
|
168
169
|
|
|
169
170
|
console.log(`ACTIVE STORAGE: ${setup.storage.getActiveStoreName()}`)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { sdk } from '../../../src'
|
|
2
|
+
import { _tu, TestWalletNoSetup } from '../../utils/TestUtilsWalletStorage'
|
|
3
|
+
|
|
4
|
+
describe('specOps tests', () => {
|
|
5
|
+
jest.setTimeout(99999999)
|
|
6
|
+
|
|
7
|
+
test('00', () => {})
|
|
8
|
+
if (_tu.noTestEnv('test')) return
|
|
9
|
+
if (_tu.noTestEnv('main')) return
|
|
10
|
+
|
|
11
|
+
test('0 wallet balance specOp', async () => {
|
|
12
|
+
const setup = await createSetup('test')
|
|
13
|
+
|
|
14
|
+
const r = await setup.wallet.listOutputs({
|
|
15
|
+
basket: '893b7646de0e1c9f741bd6e9169b76a8847ae34adef7bef1e6a285371206d2e8'
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
expect(r.totalOutputs > 0).toBe(true)
|
|
19
|
+
expect(r.outputs.length === 0).toBe(true)
|
|
20
|
+
|
|
21
|
+
await setup.wallet.destroy()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('1 wallet invalid change outputs', async () => {
|
|
25
|
+
const setup = await createSetup('test')
|
|
26
|
+
|
|
27
|
+
const r = await setup.wallet.listOutputs({
|
|
28
|
+
basket: '5a76fd430a311f8bc0553859061710a4475c19fed46e2ff95969aa918e612e57'
|
|
29
|
+
// tags: ['release']
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
expect(r.totalOutputs).toBe(0)
|
|
33
|
+
expect(r.outputs.length).toBe(0)
|
|
34
|
+
|
|
35
|
+
await setup.wallet.destroy()
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
async function createSetup(chain: sdk.Chain): Promise<TestWalletNoSetup> {
|
|
40
|
+
const env = _tu.getEnv(chain)
|
|
41
|
+
if (!env.testIdentityKey)
|
|
42
|
+
throw new sdk.WERR_INVALID_PARAMETER('env.testIdentityKey', 'valid')
|
|
43
|
+
if (!env.testFilePath)
|
|
44
|
+
throw new sdk.WERR_INVALID_PARAMETER('env.testFilePath', 'valid')
|
|
45
|
+
|
|
46
|
+
const setup = await _tu.createTestWallet({
|
|
47
|
+
chain,
|
|
48
|
+
rootKeyHex: env.devKeys[env.testIdentityKey],
|
|
49
|
+
filePath: env.testFilePath,
|
|
50
|
+
setActiveClient: false,
|
|
51
|
+
addLocalBackup: false,
|
|
52
|
+
useMySQLConnectionForClient: false
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
console.log(`ACTIVE STORAGE: ${setup.storage.getActiveStoreName()}`)
|
|
56
|
+
|
|
57
|
+
return setup
|
|
58
|
+
}
|
|
@@ -352,6 +352,7 @@ export abstract class TestUtilsWalletStorage {
|
|
|
352
352
|
let filePath: string
|
|
353
353
|
let addLocalBackup = false
|
|
354
354
|
let setActiveClient = false
|
|
355
|
+
let useMySQLConnectionForClient = false
|
|
355
356
|
if (typeof args === 'string') {
|
|
356
357
|
chain = args
|
|
357
358
|
const env = _tu.getEnv(chain)
|
|
@@ -369,6 +370,7 @@ export abstract class TestUtilsWalletStorage {
|
|
|
369
370
|
filePath = args.filePath
|
|
370
371
|
addLocalBackup = args.addLocalBackup === true
|
|
371
372
|
setActiveClient = args.setActiveClient === true
|
|
373
|
+
useMySQLConnectionForClient = args.useMySQLConnectionForClient === true
|
|
372
374
|
}
|
|
373
375
|
|
|
374
376
|
const databaseName = path.parse(filePath).name
|
|
@@ -380,12 +382,28 @@ export abstract class TestUtilsWalletStorage {
|
|
|
380
382
|
})
|
|
381
383
|
setup.localStorageIdentityKey = setup.storage.getActiveStore()
|
|
382
384
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
385
|
+
let client: sdk.WalletStorageProvider
|
|
386
|
+
if (useMySQLConnectionForClient) {
|
|
387
|
+
const env = _tu.getEnv(chain)
|
|
388
|
+
if (!env.cloudMySQLConnection)
|
|
389
|
+
throw new sdk.WERR_INVALID_PARAMETER(
|
|
390
|
+
'env.cloundMySQLConnection',
|
|
391
|
+
'valid'
|
|
392
|
+
)
|
|
393
|
+
const connection = JSON.parse(env.cloudMySQLConnection)
|
|
394
|
+
client = new StorageKnex({
|
|
395
|
+
...StorageKnex.defaultOptions(),
|
|
396
|
+
knex: _tu.createMySQLFromConnection(connection),
|
|
397
|
+
chain: env.chain
|
|
398
|
+
})
|
|
399
|
+
} else {
|
|
400
|
+
const endpointUrl =
|
|
401
|
+
chain === 'main'
|
|
402
|
+
? 'https://storage.babbage.systems'
|
|
403
|
+
: 'https://staging-storage.babbage.systems'
|
|
387
404
|
|
|
388
|
-
|
|
405
|
+
client = new StorageClient(setup.wallet, endpointUrl)
|
|
406
|
+
}
|
|
389
407
|
setup.clientStorageIdentityKey = (
|
|
390
408
|
await client.makeAvailable()
|
|
391
409
|
).storageIdentityKey
|
|
@@ -2515,4 +2533,5 @@ export interface CreateTestWalletArgs {
|
|
|
2515
2533
|
filePath: string
|
|
2516
2534
|
addLocalBackup?: boolean
|
|
2517
2535
|
setActiveClient?: boolean
|
|
2536
|
+
useMySQLConnectionForClient?: boolean
|
|
2518
2537
|
}
|