@bsv/wallet-toolbox 1.2.50 → 1.3.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.
- package/CHANGELOG.md +19 -0
- package/out/src/services/providers/WhatsOnChain.d.ts.map +1 -1
- package/out/src/services/providers/WhatsOnChain.js +25 -27
- package/out/src/services/providers/WhatsOnChain.js.map +1 -1
- package/out/src/storage/methods/listOutputs.d.ts.map +1 -1
- package/out/src/storage/methods/listOutputs.js +15 -6
- package/out/src/storage/methods/listOutputs.js.map +1 -1
- package/out/test/Wallet/support/opers1.man.test.js +2 -2
- package/out/test/Wallet/support/opers1.man.test.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/services/providers/WhatsOnChain.ts +63 -32
- package/src/storage/methods/listOutputs.ts +16 -6
- package/test/Wallet/support/opers1.man.test.ts +2 -2
package/package.json
CHANGED
|
@@ -466,8 +466,8 @@ export class WhatsOnChain extends SdkWhatsOnChain {
|
|
|
466
466
|
headers: this.getHttpHeaders()
|
|
467
467
|
}
|
|
468
468
|
|
|
469
|
-
const response = await this.httpClient.request<WhatsOnChainUtxoStatus
|
|
470
|
-
`${this.URL}/script/${scriptHash}/unspent`,
|
|
469
|
+
const response = await this.httpClient.request<WhatsOnChainUtxoStatus>(
|
|
470
|
+
`${this.URL}/script/${scriptHash}/unspent/all`,
|
|
471
471
|
requestOptions
|
|
472
472
|
)
|
|
473
473
|
if (response.statusText === 'Too Many Requests' && retry < 2) {
|
|
@@ -479,30 +479,31 @@ export class WhatsOnChain extends SdkWhatsOnChain {
|
|
|
479
479
|
if (!response.data || !response.ok || response.status !== 200)
|
|
480
480
|
throw new sdk.WERR_INVALID_OPERATION(`WoC getUtxoStatus response ${response.statusText}`)
|
|
481
481
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
r.details.push({
|
|
493
|
-
txid: s.tx_hash,
|
|
494
|
-
satoshis: s.value,
|
|
495
|
-
height: s.height,
|
|
496
|
-
index: s.tx_pos
|
|
497
|
-
})
|
|
498
|
-
}
|
|
499
|
-
if (outpoint) {
|
|
500
|
-
const { txid, vout } = parseWalletOutpoint(outpoint)
|
|
501
|
-
r.isUtxo = r.details.find(d => d.txid === txid && d.index === vout) !== undefined
|
|
502
|
-
} else r.isUtxo = r.details.length > 0
|
|
503
|
-
}
|
|
482
|
+
const data = response.data
|
|
483
|
+
|
|
484
|
+
if (data.script !== scriptHash || !Array.isArray(data.result)) {
|
|
485
|
+
throw new sdk.WERR_INTERNAL('data. is not an array')
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (data.result.length === 0) {
|
|
489
|
+
r.status = 'success'
|
|
490
|
+
r.error = undefined
|
|
491
|
+
r.isUtxo = false
|
|
504
492
|
} else {
|
|
505
|
-
|
|
493
|
+
r.status = 'success'
|
|
494
|
+
r.error = undefined
|
|
495
|
+
for (const s of data.result) {
|
|
496
|
+
r.details.push({
|
|
497
|
+
txid: s.tx_hash,
|
|
498
|
+
satoshis: s.value,
|
|
499
|
+
height: s.height,
|
|
500
|
+
index: s.tx_pos
|
|
501
|
+
})
|
|
502
|
+
}
|
|
503
|
+
if (outpoint) {
|
|
504
|
+
const { txid, vout } = parseWalletOutpoint(outpoint)
|
|
505
|
+
r.isUtxo = r.details.find(d => d.txid === txid && d.index === vout) !== undefined
|
|
506
|
+
} else r.isUtxo = r.details.length > 0
|
|
506
507
|
}
|
|
507
508
|
|
|
508
509
|
return r
|
|
@@ -661,13 +662,6 @@ interface WhatsOnChainTscProof {
|
|
|
661
662
|
txOrId: string
|
|
662
663
|
}
|
|
663
664
|
|
|
664
|
-
interface WhatsOnChainUtxoStatus {
|
|
665
|
-
value: number
|
|
666
|
-
height: number
|
|
667
|
-
tx_pos: number
|
|
668
|
-
tx_hash: string
|
|
669
|
-
}
|
|
670
|
-
|
|
671
665
|
interface WhatsOnChainScriptHashHistory {
|
|
672
666
|
tx_hash: string
|
|
673
667
|
height?: number
|
|
@@ -691,3 +685,40 @@ interface WhatsOnChainTxsStatusData {
|
|
|
691
685
|
*/
|
|
692
686
|
error?: string
|
|
693
687
|
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* GET https://api.whatsonchain.com/v1/bsv/<network>/script/<scriptHash>/unspent/all
|
|
691
|
+
*
|
|
692
|
+
* Response
|
|
693
|
+
{
|
|
694
|
+
"error":"",
|
|
695
|
+
"status":200,
|
|
696
|
+
"statusText":"OK",
|
|
697
|
+
"ok":true,
|
|
698
|
+
"data":{
|
|
699
|
+
"script":"d3ef8eeb691e7405caca142bfcd6f499b142884d7883e6701a0ee76047b4af32",
|
|
700
|
+
"result":[
|
|
701
|
+
{
|
|
702
|
+
"height":893652,
|
|
703
|
+
"tx_pos":11,
|
|
704
|
+
"tx_hash":"2178a1e93d46edda946d9069f9b157ddfacb451fee0278e657941f09bfdb5d8f",
|
|
705
|
+
"value":1005,
|
|
706
|
+
"isSpentInMempoolTx":false,
|
|
707
|
+
"status":"confirmed"
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
*
|
|
713
|
+
*/
|
|
714
|
+
interface WhatsOnChainUtxoStatus {
|
|
715
|
+
script: string
|
|
716
|
+
result: {
|
|
717
|
+
value: number
|
|
718
|
+
height: number
|
|
719
|
+
tx_pos: number
|
|
720
|
+
tx_hash: string
|
|
721
|
+
isSpentInMempoolTx: boolean
|
|
722
|
+
status: string // 'confirmed'
|
|
723
|
+
}[]
|
|
724
|
+
}
|
|
@@ -3,11 +3,13 @@ import { TableOutput, TableOutputBasket, TableOutputTag } from '../index.client'
|
|
|
3
3
|
import { asString, sdk, verifyId, verifyInteger, verifyOne } from '../../index.client'
|
|
4
4
|
import { StorageKnex } from '../StorageKnex'
|
|
5
5
|
import { ValidListOutputsArgs } from '../../sdk'
|
|
6
|
+
import { spec } from 'node:test/reporters'
|
|
6
7
|
|
|
7
8
|
interface ListOutputsSpecOp {
|
|
8
9
|
name: string
|
|
9
10
|
useBasket?: string
|
|
10
11
|
ignoreLimit?: boolean
|
|
12
|
+
includeSpent?: boolean
|
|
11
13
|
includeOutputScripts?: boolean
|
|
12
14
|
resultFromTags?: (
|
|
13
15
|
s: StorageKnex,
|
|
@@ -62,6 +64,7 @@ const basketToSpecOp: Record<string, ListOutputsSpecOp> = {
|
|
|
62
64
|
name: 'invalidChangeOutputs',
|
|
63
65
|
useBasket: 'default',
|
|
64
66
|
ignoreLimit: true,
|
|
67
|
+
includeSpent: false,
|
|
65
68
|
includeOutputScripts: true,
|
|
66
69
|
tagsToIntercept: ['release', 'all'],
|
|
67
70
|
filterOutputs: async (
|
|
@@ -71,7 +74,8 @@ const basketToSpecOp: Record<string, ListOutputsSpecOp> = {
|
|
|
71
74
|
specOpTags: string[],
|
|
72
75
|
outputs: TableOutput[]
|
|
73
76
|
): Promise<TableOutput[]> => {
|
|
74
|
-
const
|
|
77
|
+
const updateToSpent: TableOutput[] = []
|
|
78
|
+
const updateToSpendable: TableOutput[] = []
|
|
75
79
|
const services = s.getServices()
|
|
76
80
|
for (const o of outputs) {
|
|
77
81
|
await s.validateOutputScript(o)
|
|
@@ -84,17 +88,23 @@ const basketToSpecOp: Record<string, ListOutputsSpecOp> = {
|
|
|
84
88
|
} else {
|
|
85
89
|
ok = undefined
|
|
86
90
|
}
|
|
87
|
-
if (ok === false) {
|
|
88
|
-
|
|
91
|
+
if (ok === false && o.spendable) {
|
|
92
|
+
updateToSpent.push(o)
|
|
93
|
+
} else if (ok === true && !o.spendable) {
|
|
94
|
+
updateToSpendable.push(o)
|
|
89
95
|
}
|
|
90
96
|
}
|
|
91
97
|
if (specOpTags.indexOf('release') >= 0) {
|
|
92
|
-
for (const o of
|
|
98
|
+
for (const o of updateToSpent) {
|
|
93
99
|
await s.updateOutput(o.outputId, { spendable: false })
|
|
94
100
|
o.spendable = false
|
|
95
101
|
}
|
|
102
|
+
for (const o of updateToSpendable) {
|
|
103
|
+
await s.updateOutput(o.outputId, { spendable: true })
|
|
104
|
+
o.spendable = true
|
|
105
|
+
}
|
|
96
106
|
}
|
|
97
|
-
return
|
|
107
|
+
return updateToSpent.concat(updateToSpendable)
|
|
98
108
|
}
|
|
99
109
|
},
|
|
100
110
|
[sdk.specOpSetWalletChangeParams]: {
|
|
@@ -236,7 +246,7 @@ export async function listOutputs(
|
|
|
236
246
|
]
|
|
237
247
|
|
|
238
248
|
const noTags = tagIds.length === 0
|
|
239
|
-
const includeSpent = false
|
|
249
|
+
const includeSpent = specOp && specOp.includeSpent ? specOp.includeSpent : false
|
|
240
250
|
|
|
241
251
|
const txStatusOk = `(select status as tstatus from transactions where transactions.transactionId = outputs.transactionId) in ('completed', 'unproven', 'nosend')`
|
|
242
252
|
const txStatusOkCteq = `(select status as tstatus from transactions where transactions.transactionId = o.transactionId) in ('completed', 'unproven', 'nosend')`
|
|
@@ -51,9 +51,9 @@ describe('operations1 tests', () => {
|
|
|
51
51
|
let r = await storage.listOutputs(auth, vargs)
|
|
52
52
|
if (r.totalOutputs > 0) {
|
|
53
53
|
const total: number = r.outputs.reduce((s, o) => (s += o.satoshis), 0)
|
|
54
|
-
log += `userId ${userId}: ${r.totalOutputs}
|
|
54
|
+
log += `userId ${userId}: ${r.totalOutputs} utxos updated, total ${total}, ${user.identityKey}\n`
|
|
55
55
|
for (const o of r.outputs) {
|
|
56
|
-
log += ` ${o.outpoint} ${o.satoshis}\n`
|
|
56
|
+
log += ` ${o.outpoint} ${o.satoshis} now ${o.spendable ? 'spendable' : 'spent'}\n`
|
|
57
57
|
}
|
|
58
58
|
withInvalid[userId] = { user, outputs: r.outputs, total }
|
|
59
59
|
}
|