@bsv/wallet-toolbox 1.1.13 → 1.1.14
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/docs/README.md +8 -2
- package/docs/client.md +453 -346
- package/docs/open-rpc/index.html +46 -0
- package/docs/services.md +236 -211
- package/docs/setup.md +20 -4
- package/docs/storage.md +30 -5
- package/docs/wallet.md +453 -346
- package/out/src/Setup.d.ts.map +1 -1
- package/out/src/Setup.js.map +1 -1
- package/out/src/SetupClient.d.ts +9 -0
- package/out/src/SetupClient.d.ts.map +1 -1
- package/out/src/SetupClient.js +19 -3
- package/out/src/SetupClient.js.map +1 -1
- package/out/src/Wallet.d.ts +6 -0
- package/out/src/Wallet.d.ts.map +1 -1
- package/out/src/Wallet.js +57 -0
- package/out/src/Wallet.js.map +1 -1
- package/out/src/sdk/WalletServices.interfaces.d.ts +18 -13
- package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
- package/out/src/services/Services.d.ts +4 -11
- package/out/src/services/Services.d.ts.map +1 -1
- package/out/src/services/Services.js +19 -37
- package/out/src/services/Services.js.map +1 -1
- package/out/src/services/__tests/ARC.test.d.ts +2 -0
- package/out/src/services/__tests/ARC.test.d.ts.map +1 -0
- package/out/src/services/__tests/ARC.test.js +98 -0
- package/out/src/services/__tests/ARC.test.js.map +1 -0
- package/out/src/services/__tests/arcServices.test.d.ts +2 -0
- package/out/src/services/__tests/arcServices.test.d.ts.map +1 -0
- package/out/src/services/__tests/arcServices.test.js +7 -0
- package/out/src/services/__tests/arcServices.test.js.map +1 -0
- package/out/src/services/__tests/postBeef.test.js +45 -7
- package/out/src/services/__tests/postBeef.test.js.map +1 -1
- package/out/src/services/createDefaultWalletServicesOptions.d.ts +1 -0
- package/out/src/services/createDefaultWalletServicesOptions.d.ts.map +1 -1
- package/out/src/services/createDefaultWalletServicesOptions.js +16 -4
- package/out/src/services/createDefaultWalletServicesOptions.js.map +1 -1
- package/out/src/services/providers/ARC.d.ts +91 -0
- package/out/src/services/providers/ARC.d.ts.map +1 -0
- package/out/src/services/providers/ARC.js +192 -0
- package/out/src/services/providers/ARC.js.map +1 -0
- package/out/src/services/providers/SdkWhatsOnChain.d.ts +21 -0
- package/out/src/services/providers/SdkWhatsOnChain.d.ts.map +1 -0
- package/out/src/services/providers/SdkWhatsOnChain.js +67 -0
- package/out/src/services/providers/SdkWhatsOnChain.js.map +1 -0
- package/out/src/services/providers/WhatsOnChain.d.ts +35 -0
- package/out/src/services/providers/WhatsOnChain.d.ts.map +1 -0
- package/out/src/services/providers/WhatsOnChain.js +266 -0
- package/out/src/services/providers/WhatsOnChain.js.map +1 -0
- package/out/src/services/providers/__tests/WhatsOnChain.test.d.ts +2 -0
- package/out/src/services/providers/__tests/WhatsOnChain.test.d.ts.map +1 -0
- package/out/src/services/providers/__tests/WhatsOnChain.test.js +176 -0
- package/out/src/services/providers/__tests/WhatsOnChain.test.js.map +1 -0
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js +9 -2
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/methods/generateChange.d.ts +12 -1
- package/out/src/storage/methods/generateChange.d.ts.map +1 -1
- package/out/src/storage/methods/generateChange.js +24 -1
- package/out/src/storage/methods/generateChange.js.map +1 -1
- package/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/out/src/storage/methods/processAction.js +1 -1
- package/out/src/storage/methods/processAction.js.map +1 -1
- package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js +0 -1
- package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js.map +1 -1
- package/out/src/storage/sync/StorageMySQLDojoReader.js +1 -1
- package/out/src/storage/sync/StorageMySQLDojoReader.js.map +1 -1
- package/out/src/utility/utilityHelpers.js +1 -1
- package/out/src/utility/utilityHelpers.js.map +1 -1
- package/out/test/Wallet/StorageClient/storageClient.man.test.js +22 -3
- package/out/test/Wallet/StorageClient/storageClient.man.test.js.map +1 -1
- package/out/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.js +40 -0
- package/out/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.js.map +1 -1
- package/out/test/services/Services.test.js +0 -31
- package/out/test/services/Services.test.js.map +1 -1
- package/out/test/utils/TestUtilsWalletStorage.d.ts +26 -18
- package/out/test/utils/TestUtilsWalletStorage.d.ts.map +1 -1
- package/out/test/utils/TestUtilsWalletStorage.js +135 -27
- package/out/test/utils/TestUtilsWalletStorage.js.map +1 -1
- package/out/test/wallet/list/listActions2.test.js +36 -2
- package/out/test/wallet/list/listActions2.test.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +5 -7
- package/src/Setup.ts +0 -1
- package/src/SetupClient.ts +26 -6
- package/src/Wallet.ts +66 -2
- package/src/sdk/WalletServices.interfaces.ts +19 -14
- package/src/services/Services.ts +23 -62
- package/src/services/__tests/ARC.test.ts +110 -0
- package/src/services/__tests/arcServices.test.ts +8 -0
- package/src/services/__tests/postBeef.test.ts +47 -9
- package/src/services/createDefaultWalletServicesOptions.ts +19 -6
- package/src/services/providers/ARC.ts +289 -0
- package/src/services/providers/SdkWhatsOnChain.ts +96 -0
- package/src/services/providers/WhatsOnChain.ts +369 -0
- package/src/services/providers/__tests/WhatsOnChain.test.ts +227 -0
- package/src/storage/methods/createAction.ts +26 -4
- package/src/storage/methods/generateChange.ts +42 -2
- package/src/storage/methods/processAction.ts +2 -1
- package/src/storage/schema/entities/__tests/ProvenTxTests.test.ts +0 -1
- package/src/storage/sync/StorageMySQLDojoReader.ts +1 -1
- package/src/utility/utilityHelpers.ts +1 -1
- package/test/Wallet/StorageClient/storageClient.man.test.ts +30 -4
- package/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.ts +54 -0
- package/test/services/Services.test.ts +0 -30
- package/test/utils/TestUtilsWalletStorage.ts +175 -45
- package/test/wallet/list/listActions2.test.ts +4 -7
- package/out/src/services/__tests/postBeefToArcTaal.test.d.ts +0 -2
- package/out/src/services/__tests/postBeefToArcTaal.test.d.ts.map +0 -1
- package/out/src/services/__tests/postBeefToArcTaal.test.js +0 -479
- package/out/src/services/__tests/postBeefToArcTaal.test.js.map +0 -1
- package/out/src/services/__tests/postTxs.test.d.ts +0 -2
- package/out/src/services/__tests/postTxs.test.d.ts.map +0 -1
- package/out/src/services/__tests/postTxs.test.js +0 -28
- package/out/src/services/__tests/postTxs.test.js.map +0 -1
- package/out/src/services/providers/arcServices.d.ts +0 -62
- package/out/src/services/providers/arcServices.d.ts.map +0 -1
- package/out/src/services/providers/arcServices.js +0 -375
- package/out/src/services/providers/arcServices.js.map +0 -1
- package/out/src/services/providers/whatsonchain.d.ts +0 -17
- package/out/src/services/providers/whatsonchain.d.ts.map +0 -1
- package/out/src/services/providers/whatsonchain.js +0 -130
- package/out/src/services/providers/whatsonchain.js.map +0 -1
- package/out/test/examples/README.man.test.d.ts +0 -2
- package/out/test/examples/README.man.test.d.ts.map +0 -1
- package/out/test/examples/README.man.test.js +0 -47
- package/out/test/examples/README.man.test.js.map +0 -1
- package/src/services/__tests/postBeefToArcTaal.test.ts +0 -487
- package/src/services/__tests/postTxs.test.ts +0 -28
- package/src/services/providers/arcServices.ts +0 -578
- package/src/services/providers/whatsonchain.ts +0 -170
- package/test/examples/README.man.test.ts +0 -53
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { sdk, validateStorageFeeModel } from '../../index.client'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* An output of this satoshis amount will be adjusted to the largest fundable amount.
|
|
5
|
+
*/
|
|
6
|
+
export const maxPossibleSatoshis = 2099999999999999
|
|
7
|
+
|
|
3
8
|
export interface GenerateChangeSdkResult {
|
|
4
9
|
allocatedChangeInputs: GenerateChangeSdkChangeInput[]
|
|
5
10
|
changeOutputs: GenerateChangeSdkChangeOutput[]
|
|
6
11
|
size: number
|
|
7
12
|
fee: number
|
|
8
13
|
satsPerKb: number
|
|
14
|
+
maxPossibleSatoshisAdjustment?: {
|
|
15
|
+
fixedOutputIndex: number
|
|
16
|
+
satoshis: number
|
|
17
|
+
}
|
|
9
18
|
}
|
|
10
19
|
|
|
11
20
|
/**
|
|
@@ -38,7 +47,7 @@ export async function generateChangeSdk(
|
|
|
38
47
|
|
|
39
48
|
// eslint-disable-next-line no-useless-catch
|
|
40
49
|
try {
|
|
41
|
-
validateGenerateChangeSdkParams(params)
|
|
50
|
+
const vgcpr = validateGenerateChangeSdkParams(params)
|
|
42
51
|
|
|
43
52
|
const satsPerKb = params.feeModel.value || 0
|
|
44
53
|
|
|
@@ -269,6 +278,20 @@ export async function generateChangeSdk(
|
|
|
269
278
|
*/
|
|
270
279
|
await fundTransaction()
|
|
271
280
|
|
|
281
|
+
if (feeExcess() < 0 && vgcpr.hasMaxPossibleOutput !== undefined) {
|
|
282
|
+
// Reduce the fixed output with satoshis of maxPossibleSatoshis to what will just fund the transaction...
|
|
283
|
+
if (
|
|
284
|
+
fixedOutputs[vgcpr.hasMaxPossibleOutput].satoshis !==
|
|
285
|
+
maxPossibleSatoshis
|
|
286
|
+
)
|
|
287
|
+
throw new sdk.WERR_INTERNAL()
|
|
288
|
+
fixedOutputs[vgcpr.hasMaxPossibleOutput].satoshis += feeExcess()
|
|
289
|
+
r.maxPossibleSatoshisAdjustment = {
|
|
290
|
+
fixedOutputIndex: vgcpr.hasMaxPossibleOutput,
|
|
291
|
+
satoshis: fixedOutputs[vgcpr.hasMaxPossibleOutput].satoshis
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
272
295
|
/**
|
|
273
296
|
* Trigger an account funding event if we don't have enough to cover this transaction.
|
|
274
297
|
*/
|
|
@@ -448,11 +471,18 @@ export interface GenerateChangeSdkChangeOutput {
|
|
|
448
471
|
lockingScriptLength: number
|
|
449
472
|
}
|
|
450
473
|
|
|
474
|
+
export interface ValidateGenerateChangeSdkParamsResult {
|
|
475
|
+
hasMaxPossibleOutput?: number
|
|
476
|
+
}
|
|
477
|
+
|
|
451
478
|
export function validateGenerateChangeSdkParams(
|
|
452
479
|
params: GenerateChangeSdkParams
|
|
453
|
-
) {
|
|
480
|
+
): ValidateGenerateChangeSdkParamsResult {
|
|
454
481
|
if (!Array.isArray(params.fixedInputs))
|
|
455
482
|
throw new sdk.WERR_INVALID_PARAMETER('fixedInputs', 'an array of objects')
|
|
483
|
+
|
|
484
|
+
const r: ValidateGenerateChangeSdkParamsResult = {}
|
|
485
|
+
|
|
456
486
|
params.fixedInputs.forEach((x, i) => {
|
|
457
487
|
sdk.validateSatoshis(x.satoshis, `fixedInputs[${i}].satoshis`)
|
|
458
488
|
sdk.validateInteger(
|
|
@@ -473,6 +503,14 @@ export function validateGenerateChangeSdkParams(
|
|
|
473
503
|
undefined,
|
|
474
504
|
0
|
|
475
505
|
)
|
|
506
|
+
if (x.satoshis === maxPossibleSatoshis) {
|
|
507
|
+
if (r.hasMaxPossibleOutput !== undefined)
|
|
508
|
+
throw new sdk.WERR_INVALID_PARAMETER(
|
|
509
|
+
`fixedOutputs[${i}].satoshis`,
|
|
510
|
+
`valid satoshis amount. Only one 'maxPossibleSatoshis' output allowed.`
|
|
511
|
+
)
|
|
512
|
+
r.hasMaxPossibleOutput = i
|
|
513
|
+
}
|
|
476
514
|
})
|
|
477
515
|
|
|
478
516
|
params.feeModel = validateStorageFeeModel(params.feeModel)
|
|
@@ -492,6 +530,8 @@ export function validateGenerateChangeSdkParams(
|
|
|
492
530
|
params.changeUnlockingScriptLength,
|
|
493
531
|
`changeUnlockingScriptLength`
|
|
494
532
|
)
|
|
533
|
+
|
|
534
|
+
return r
|
|
495
535
|
}
|
|
496
536
|
|
|
497
537
|
export interface GenerateChangeSdkStorageChange
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
TxScriptOffsets,
|
|
25
25
|
validateStorageFeeModel,
|
|
26
26
|
verifyId,
|
|
27
|
+
verifyInteger,
|
|
27
28
|
verifyNumber,
|
|
28
29
|
verifyOne,
|
|
29
30
|
verifyOneOrNone,
|
|
@@ -359,7 +360,7 @@ async function validateCommitNewTxToStorageArgs(
|
|
|
359
360
|
// outputs spendable will be updated for change to true and all others to !!o.tracked when tx has been broadcast
|
|
360
361
|
// MAX_OUTPUTSCRIPT_LENGTH is limit for scripts left in outputs table
|
|
361
362
|
for (const o of vargs.outputOutputs) {
|
|
362
|
-
const vout =
|
|
363
|
+
const vout = verifyInteger(o.vout)
|
|
363
364
|
const offset = vargs.txScriptOffsets.outputs[vout]
|
|
364
365
|
const rawTxScript = asString(
|
|
365
366
|
vargs.rawTx.slice(offset.offset, offset.offset + offset.length)
|
|
@@ -100,7 +100,6 @@ describe('ProvenTx class method tests', () => {
|
|
|
100
100
|
getHeight: async () => height,
|
|
101
101
|
getBsvExchangeRate: async () => 0,
|
|
102
102
|
getFiatExchangeRate: async () => 1,
|
|
103
|
-
postTxs: async () => [],
|
|
104
103
|
postBeef: async () => [],
|
|
105
104
|
getUtxoStatus: async () => ({
|
|
106
105
|
name: 'mock-service',
|
|
@@ -298,7 +298,7 @@ export class StorageMySQLDojoReader extends StorageReader {
|
|
|
298
298
|
spendable: !!d.spendable,
|
|
299
299
|
change: d.providedBy !== 'you' && d.purpose === 'change',
|
|
300
300
|
outputDescription: (d.description || '').trim(),
|
|
301
|
-
vout: verifyInteger(d.vout),
|
|
301
|
+
vout: verifyInteger(typeof d.vout !== 'number' ? 9999 : d.vout),
|
|
302
302
|
satoshis: verifyInteger(d.amount),
|
|
303
303
|
providedBy: verifyTruthy(d.providedBy || '')
|
|
304
304
|
.trim()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
import { StorageClient } from '../../../src/index.all'
|
|
2
|
+
import { sdk, StorageClient } from '../../../src/index.all'
|
|
3
3
|
import { _tu, TestWalletOnly } from '../../utils/TestUtilsWalletStorage'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -32,17 +32,17 @@ describe('walletStorageClient test', () => {
|
|
|
32
32
|
{
|
|
33
33
|
const client = new StorageClient(
|
|
34
34
|
wallet,
|
|
35
|
-
'https://staging-
|
|
35
|
+
'https://staging-storage.babbage.systems'
|
|
36
36
|
)
|
|
37
37
|
await storage.addWalletStorageProvider(client)
|
|
38
38
|
await storage.updateBackups()
|
|
39
39
|
}
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
test('2 create storage client wallet', async () => {
|
|
42
|
+
test('2 create storage client backup for test wallet', async () => {
|
|
43
43
|
const ctx = await _tu.createTestWalletWithStorageClient({
|
|
44
44
|
rootKeyHex: '1'.repeat(64),
|
|
45
|
-
endpointUrl: 'https://staging-
|
|
45
|
+
endpointUrl: 'https://staging-storage.babbage.systems'
|
|
46
46
|
})
|
|
47
47
|
ctxs.push(ctx)
|
|
48
48
|
const { wallet, storage } = ctx
|
|
@@ -52,4 +52,30 @@ describe('walletStorageClient test', () => {
|
|
|
52
52
|
expect(auth.userId).toBeTruthy()
|
|
53
53
|
}
|
|
54
54
|
})
|
|
55
|
+
|
|
56
|
+
test('3 create storage client backup for main wallet', async () => {
|
|
57
|
+
const filePath = process.env.MY_MAIN_FILEPATH
|
|
58
|
+
const identityKey = process.env.MY_MAIN_IDENTITY || ''
|
|
59
|
+
const rootKeyHex = env.devKeys[identityKey]
|
|
60
|
+
expect(filePath && identityKey && rootKeyHex)
|
|
61
|
+
|
|
62
|
+
const chain: sdk.Chain = 'main'
|
|
63
|
+
|
|
64
|
+
const main = await _tu.createSQLiteTestWallet({
|
|
65
|
+
filePath,
|
|
66
|
+
databaseName: 'tone42',
|
|
67
|
+
chain,
|
|
68
|
+
rootKeyHex
|
|
69
|
+
})
|
|
70
|
+
ctxs.push(main)
|
|
71
|
+
|
|
72
|
+
{
|
|
73
|
+
const client = new StorageClient(
|
|
74
|
+
main.wallet,
|
|
75
|
+
'https://storage.babbage.systems'
|
|
76
|
+
)
|
|
77
|
+
await main.storage.addWalletStorageProvider(client)
|
|
78
|
+
await main.storage.updateBackups()
|
|
79
|
+
}
|
|
80
|
+
})
|
|
55
81
|
})
|
|
@@ -66,6 +66,60 @@ describe('Wallet sync tests', () => {
|
|
|
66
66
|
done0 = true
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
+
test.skip('0a sync production dojo to local MySQL', async () => {
|
|
70
|
+
console.log(
|
|
71
|
+
'Importing from production dojo to local MySQL productiondojotone'
|
|
72
|
+
)
|
|
73
|
+
const identityKeyTone = process.env.MY_MAIN_IDENTITY || ''
|
|
74
|
+
const rootKeyHex = env.devKeys[identityKeyTone]
|
|
75
|
+
const chain: sdk.Chain = 'main'
|
|
76
|
+
const connection = JSON.parse(process.env.MAIN_DOJO_CONNECTION || '')
|
|
77
|
+
const readerKnex = _tu.createMySQLFromConnection(connection)
|
|
78
|
+
const reader = new StorageMySQLDojoReader({ chain, knex: readerKnex })
|
|
79
|
+
const writer = await _tu.createMySQLTestWallet({
|
|
80
|
+
databaseName: 'productiondojotone',
|
|
81
|
+
chain: 'main',
|
|
82
|
+
rootKeyHex,
|
|
83
|
+
dropAll: true
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const identityKey = writer.identityKey
|
|
87
|
+
await writer.storage.syncFromReader(
|
|
88
|
+
identityKey,
|
|
89
|
+
new StorageSyncReader({ identityKey }, reader)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
await reader.destroy()
|
|
93
|
+
await writer.activeStorage.destroy()
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
test('0b sweep mysql dojo sync to new sqlite', async () => {
|
|
97
|
+
const identityKeyTone = process.env.MY_MAIN_IDENTITY || ''
|
|
98
|
+
const rootKeyHex = env.devKeys[identityKeyTone]
|
|
99
|
+
const chain: sdk.Chain = 'main'
|
|
100
|
+
|
|
101
|
+
const sweepFrom = await _tu.createMySQLTestWallet({
|
|
102
|
+
databaseName: 'productiondojotone',
|
|
103
|
+
chain: 'main',
|
|
104
|
+
rootKeyHex
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const sweepTo = await _tu.createSQLiteTestWallet({
|
|
108
|
+
filePath: '/Users/tone/Kz/tone42.sqlite',
|
|
109
|
+
databaseName: 'tone42',
|
|
110
|
+
chain: 'main',
|
|
111
|
+
rootKeyHex
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
//await sweepTo.activeStorage.updateProvenTxReq(2, { status: 'invalid' })
|
|
115
|
+
//await sweepTo.activeStorage.updateTransactionStatus('failed', 2)
|
|
116
|
+
|
|
117
|
+
await sweepFrom.wallet.sweepTo(sweepTo.wallet)
|
|
118
|
+
|
|
119
|
+
await sweepTo.wallet.destroy()
|
|
120
|
+
await sweepFrom.wallet.destroy()
|
|
121
|
+
})
|
|
122
|
+
|
|
69
123
|
test('1 aggressively purge records from MySQL stagingdojotone', async () => {
|
|
70
124
|
await waitFor0()
|
|
71
125
|
|
|
@@ -120,34 +120,4 @@ describe('Wallet services tests', () => {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
})
|
|
123
|
-
|
|
124
|
-
test('6 postBeef', async () => {
|
|
125
|
-
for (const { chain, wallet, services } of ctxs) {
|
|
126
|
-
if (!wallet.services || !services)
|
|
127
|
-
throw new sdk.WERR_INTERNAL('test requires setup with services')
|
|
128
|
-
{
|
|
129
|
-
if (chain === 'main') {
|
|
130
|
-
const txid =
|
|
131
|
-
'b56ccf7dd0eb6bb0341cb92a2045d902106e4c2add0a4af057c85e9dfaaebddf'
|
|
132
|
-
const rawTx = await wallet.services.getRawTx(txid)
|
|
133
|
-
const mp = await wallet.services.getMerklePath(txid)
|
|
134
|
-
const beef = new Beef()
|
|
135
|
-
beef.mergeBump(mp.merklePath!)
|
|
136
|
-
beef.mergeRawTx(rawTx.rawTx!)
|
|
137
|
-
// Using postTxs as postBeef is problematic still...
|
|
138
|
-
const r = await wallet.services.postTxs(beef, [txid])
|
|
139
|
-
if (r[0].status === 'error') {
|
|
140
|
-
console.log(`
|
|
141
|
-
${r[0].error?.message}
|
|
142
|
-
${beef.toLogString()}
|
|
143
|
-
${beef.toHex()}
|
|
144
|
-
`)
|
|
145
|
-
} else {
|
|
146
|
-
expect(r[0].txidResults[0].txid).toBe(txid)
|
|
147
|
-
expect(r[0].status).toBe('success')
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
})
|
|
153
123
|
})
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
SatoshiValue,
|
|
12
12
|
SignActionArgs,
|
|
13
13
|
SignActionResult,
|
|
14
|
+
Transaction,
|
|
14
15
|
Utils,
|
|
15
16
|
WalletAction,
|
|
16
17
|
WalletActionInput,
|
|
@@ -49,7 +50,9 @@ import {
|
|
|
49
50
|
TableCertificate,
|
|
50
51
|
TableCertificateField,
|
|
51
52
|
TableOutputTagMap,
|
|
52
|
-
TableOutputTag
|
|
53
|
+
TableOutputTag,
|
|
54
|
+
ScriptTemplateBRC29,
|
|
55
|
+
Setup
|
|
53
56
|
} from '../../src/index.all'
|
|
54
57
|
|
|
55
58
|
import { Knex, knex as makeKnex } from 'knex'
|
|
@@ -57,22 +60,22 @@ import { Knex, knex as makeKnex } from 'knex'
|
|
|
57
60
|
import * as dotenv from 'dotenv'
|
|
58
61
|
dotenv.config()
|
|
59
62
|
|
|
60
|
-
const localMySqlConnection = process.env.
|
|
63
|
+
const localMySqlConnection = process.env.MYSQL_CONNECTION || ''
|
|
61
64
|
|
|
62
65
|
export interface TuEnv {
|
|
63
66
|
chain: sdk.Chain
|
|
64
|
-
userId: number
|
|
65
67
|
identityKey: string
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
identityKey2: string
|
|
69
|
+
taalApiKey: string
|
|
68
70
|
devKeys: Record<string, string>
|
|
69
|
-
|
|
71
|
+
runMySQL: boolean
|
|
70
72
|
runSlowTests: boolean
|
|
71
73
|
logTests: boolean
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
export abstract class TestUtilsWalletStorage {
|
|
75
|
-
|
|
77
|
+
|
|
78
|
+
static getEnv(chain: sdk.Chain): TuEnv {
|
|
76
79
|
// Identity keys of the lead maintainer of this repo...
|
|
77
80
|
const identityKey =
|
|
78
81
|
(chain === 'main'
|
|
@@ -86,18 +89,13 @@ export abstract class TestUtilsWalletStorage {
|
|
|
86
89
|
const logTests = !!process.env.LOGTESTS
|
|
87
90
|
const runMySQL = !!process.env.RUNMYSQL
|
|
88
91
|
const runSlowTests = !!process.env.RUNSLOWTESTS
|
|
92
|
+
const mainTaalApiKey = process.env.MAIN_TAAL_API_KEY || ''
|
|
93
|
+
const testTaalApiKey = process.env.TEST_TAAL_API_KEY || ''
|
|
89
94
|
return {
|
|
90
95
|
chain,
|
|
91
96
|
identityKey,
|
|
92
97
|
identityKey2,
|
|
93
|
-
mainTaalApiKey:
|
|
94
|
-
process.env.MAIN_TAAL_API_KEY || '',
|
|
95
|
-
`.env value for 'mainTaalApiKey' is required.`
|
|
96
|
-
),
|
|
97
|
-
testTaalApiKey: verifyTruthy(
|
|
98
|
-
process.env.TEST_TAAL_API_KEY || '',
|
|
99
|
-
`.env value for 'testTaalApiKey' is required.`
|
|
100
|
-
),
|
|
98
|
+
taalApiKey: chain === 'main' ? mainTaalApiKey : testTaalApiKey,
|
|
101
99
|
devKeys: JSON.parse(DEV_KEYS) as Record<string, string>,
|
|
102
100
|
runMySQL,
|
|
103
101
|
runSlowTests,
|
|
@@ -281,17 +279,16 @@ export abstract class TestUtilsWalletStorage {
|
|
|
281
279
|
endpointUrl?: string
|
|
282
280
|
chain?: sdk.Chain
|
|
283
281
|
}): Promise<TestWalletOnly> {
|
|
284
|
-
|
|
285
|
-
throw new sdk.WERR_INVALID_PARAMETER(
|
|
286
|
-
'chain',
|
|
287
|
-
`'test' for now, 'main' is not yet supported.`
|
|
288
|
-
)
|
|
289
|
-
|
|
282
|
+
args.chain ||= 'test'
|
|
290
283
|
const wo = await _tu.createWalletOnly({
|
|
291
|
-
chain:
|
|
284
|
+
chain: args.chain,
|
|
292
285
|
rootKeyHex: args.rootKeyHex
|
|
293
286
|
})
|
|
294
|
-
args.endpointUrl ||=
|
|
287
|
+
args.endpointUrl ||=
|
|
288
|
+
args.chain === 'main'
|
|
289
|
+
? 'https://storage.babbage.systems'
|
|
290
|
+
: 'https://staging-storage.babbage.systems'
|
|
291
|
+
|
|
295
292
|
const client = new StorageClient(wo.wallet, args.endpointUrl)
|
|
296
293
|
await wo.storage.addWalletStorageProvider(client)
|
|
297
294
|
await wo.storage.makeAvailable()
|
|
@@ -1224,7 +1221,7 @@ export abstract class TestUtilsWalletStorage {
|
|
|
1224
1221
|
|
|
1225
1222
|
// Need to convert
|
|
1226
1223
|
const lockingScriptValue = input.sourceLockingScript
|
|
1227
|
-
?
|
|
1224
|
+
? Utils.toArray(input.sourceLockingScript, 'hex')
|
|
1228
1225
|
: undefined
|
|
1229
1226
|
|
|
1230
1227
|
prevOutput = await _tu.insertTestOutput(
|
|
@@ -1396,6 +1393,160 @@ export abstract class TestUtilsWalletStorage {
|
|
|
1396
1393
|
)
|
|
1397
1394
|
}
|
|
1398
1395
|
}
|
|
1396
|
+
|
|
1397
|
+
static async createWalletSetupEnv(chain: sdk.Chain): Promise<TestWalletOnly> {
|
|
1398
|
+
const env = Setup.getEnv(chain)
|
|
1399
|
+
const rootKeyHex = env.devKeys[env.identityKey]
|
|
1400
|
+
|
|
1401
|
+
if (env.filePath) {
|
|
1402
|
+
return await _tu.createSQLiteTestWallet({
|
|
1403
|
+
filePath: env.filePath,
|
|
1404
|
+
databaseName: 'setupEnvWallet',
|
|
1405
|
+
chain,
|
|
1406
|
+
rootKeyHex
|
|
1407
|
+
})
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
return await _tu.createTestWalletWithStorageClient({
|
|
1411
|
+
chain,
|
|
1412
|
+
rootKeyHex
|
|
1413
|
+
})
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* Create a pair of transacitons that cancel out, other than the transaciton fees.
|
|
1418
|
+
* Both created transactions are left with status 'noSend'.
|
|
1419
|
+
* This allows the transactions to either be broadcast by an external party,
|
|
1420
|
+
* or they may be aborted.
|
|
1421
|
+
*
|
|
1422
|
+
* `doubleSpendTx` should only be used for double spend testing.
|
|
1423
|
+
* It attempts to forward the txidDo input, which should already have been reclaimed by txidUndo, to a random private key output.
|
|
1424
|
+
*
|
|
1425
|
+
* @param wallet the wallet that will create both transactions, or Chain and createWalletEnv is used to create a wallet.
|
|
1426
|
+
* @param satoshis amount of new output created and consumed. Defaults to 41.
|
|
1427
|
+
* @returns { txidDo: string, txidUndo: string, beef: Beef, doubleSpendTx: transaction }
|
|
1428
|
+
*/
|
|
1429
|
+
static async createNoSendTxPair(
|
|
1430
|
+
wallet: Wallet | sdk.Chain,
|
|
1431
|
+
satoshis = 41
|
|
1432
|
+
): Promise<{
|
|
1433
|
+
txidDo: string
|
|
1434
|
+
txidUndo: string
|
|
1435
|
+
beef: Beef
|
|
1436
|
+
doubleSpendTx: Transaction
|
|
1437
|
+
}> {
|
|
1438
|
+
let destroyWallet = false
|
|
1439
|
+
if (wallet === 'main' || wallet === 'test') {
|
|
1440
|
+
wallet = (await _tu.createWalletSetupEnv(wallet)).wallet
|
|
1441
|
+
destroyWallet = true
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
const derivationPrefix = randomBytesBase64(8)
|
|
1445
|
+
const derivationSuffix = randomBytesBase64(8)
|
|
1446
|
+
const keyDeriver = wallet.keyDeriver
|
|
1447
|
+
|
|
1448
|
+
const t = new ScriptTemplateBRC29({
|
|
1449
|
+
derivationPrefix,
|
|
1450
|
+
derivationSuffix,
|
|
1451
|
+
keyDeriver
|
|
1452
|
+
})
|
|
1453
|
+
|
|
1454
|
+
let label = 'doTxPair'
|
|
1455
|
+
const car = await wallet.createAction({
|
|
1456
|
+
outputs: [
|
|
1457
|
+
{
|
|
1458
|
+
lockingScript: t
|
|
1459
|
+
.lock(keyDeriver.rootKey.toString(), wallet.identityKey)
|
|
1460
|
+
.toHex(),
|
|
1461
|
+
satoshis,
|
|
1462
|
+
outputDescription: label,
|
|
1463
|
+
customInstructions: JSON.stringify({
|
|
1464
|
+
derivationPrefix,
|
|
1465
|
+
derivationSuffix,
|
|
1466
|
+
type: 'BRC29'
|
|
1467
|
+
})
|
|
1468
|
+
}
|
|
1469
|
+
],
|
|
1470
|
+
options: {
|
|
1471
|
+
randomizeOutputs: false,
|
|
1472
|
+
noSend: true
|
|
1473
|
+
},
|
|
1474
|
+
description: label
|
|
1475
|
+
})
|
|
1476
|
+
|
|
1477
|
+
const beef = Beef.fromBinary(car.tx!)
|
|
1478
|
+
const txidDo = car.txid!
|
|
1479
|
+
const outpoint = `${car.txid!}.0`
|
|
1480
|
+
|
|
1481
|
+
const unlock = t.unlock(
|
|
1482
|
+
keyDeriver.rootKey.toString(),
|
|
1483
|
+
wallet.identityKey,
|
|
1484
|
+
satoshis
|
|
1485
|
+
)
|
|
1486
|
+
|
|
1487
|
+
label = 'undoTxPair'
|
|
1488
|
+
|
|
1489
|
+
const car2 = await wallet.createAction({
|
|
1490
|
+
inputBEEF: beef.toBinary(),
|
|
1491
|
+
inputs: [
|
|
1492
|
+
{
|
|
1493
|
+
outpoint,
|
|
1494
|
+
unlockingScriptLength: t.unlockLength,
|
|
1495
|
+
inputDescription: label
|
|
1496
|
+
}
|
|
1497
|
+
],
|
|
1498
|
+
description: label,
|
|
1499
|
+
options: {
|
|
1500
|
+
noSend: true,
|
|
1501
|
+
noSendChange: car.noSendChange
|
|
1502
|
+
}
|
|
1503
|
+
})
|
|
1504
|
+
|
|
1505
|
+
const st = car2.signableTransaction!
|
|
1506
|
+
const stBeef = Beef.fromBinary(st.tx)
|
|
1507
|
+
const tx = wallet.beef.findAtomicTransaction(stBeef.txs.slice(-1)[0].txid)!
|
|
1508
|
+
tx.inputs[0].unlockingScriptTemplate = unlock
|
|
1509
|
+
await tx.sign()
|
|
1510
|
+
const unlockingScript = tx.inputs[0].unlockingScript!.toHex()
|
|
1511
|
+
|
|
1512
|
+
const signArgs: SignActionArgs = {
|
|
1513
|
+
reference: st.reference,
|
|
1514
|
+
spends: { 0: { unlockingScript } },
|
|
1515
|
+
options: {
|
|
1516
|
+
noSend: true
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
const sar = await wallet.signAction(signArgs)
|
|
1521
|
+
|
|
1522
|
+
beef.mergeBeef(sar.tx!)
|
|
1523
|
+
const txidUndo = sar.txid!
|
|
1524
|
+
|
|
1525
|
+
if (destroyWallet) await wallet.destroy()
|
|
1526
|
+
|
|
1527
|
+
const doubleSpendTx = new Transaction()
|
|
1528
|
+
const sourceTXID = txidDo
|
|
1529
|
+
const sourceOutputIndex = 0
|
|
1530
|
+
const sourceSatoshis = satoshis
|
|
1531
|
+
doubleSpendTx.addInput({
|
|
1532
|
+
sourceOutputIndex,
|
|
1533
|
+
sourceTXID,
|
|
1534
|
+
sourceTransaction: beef.findAtomicTransaction(sourceTXID),
|
|
1535
|
+
unlockingScriptTemplate: unlock
|
|
1536
|
+
})
|
|
1537
|
+
doubleSpendTx.addOutput({
|
|
1538
|
+
satoshis: sourceSatoshis - 10,
|
|
1539
|
+
lockingScript: new P2PKH().lock(PrivateKey.fromRandom().toAddress())
|
|
1540
|
+
})
|
|
1541
|
+
await doubleSpendTx.sign()
|
|
1542
|
+
|
|
1543
|
+
return {
|
|
1544
|
+
txidDo,
|
|
1545
|
+
txidUndo,
|
|
1546
|
+
beef,
|
|
1547
|
+
doubleSpendTx
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1399
1550
|
}
|
|
1400
1551
|
|
|
1401
1552
|
export abstract class _tu extends TestUtilsWalletStorage {}
|
|
@@ -1535,18 +1686,6 @@ function mockPostServices(
|
|
|
1535
1686
|
return Promise.resolve([r])
|
|
1536
1687
|
}
|
|
1537
1688
|
)
|
|
1538
|
-
services.postTxs = jest
|
|
1539
|
-
.fn()
|
|
1540
|
-
.mockImplementation(
|
|
1541
|
-
(beef: Beef, txids: string[]): Promise<sdk.PostBeefResult[]> => {
|
|
1542
|
-
const r: sdk.PostBeefResult = {
|
|
1543
|
-
name: 'mock',
|
|
1544
|
-
status: 'success',
|
|
1545
|
-
txidResults: txids.map(txid => ({ txid, status }))
|
|
1546
|
-
}
|
|
1547
|
-
return Promise.resolve([r])
|
|
1548
|
-
}
|
|
1549
|
-
)
|
|
1550
1689
|
}
|
|
1551
1690
|
}
|
|
1552
1691
|
|
|
@@ -2179,12 +2318,3 @@ export async function logInput(
|
|
|
2179
2318
|
export function logBasket(basket: TableOutputBasket): string {
|
|
2180
2319
|
return `\n-- Basket --\nName: ${basket.name}\n`
|
|
2181
2320
|
}
|
|
2182
|
-
|
|
2183
|
-
export function hexStringToNumberArray(hexString: string): number[] {
|
|
2184
|
-
const sanitizedHex = hexString.replace(/[^a-fA-F0-9]/g, '')
|
|
2185
|
-
const result: number[] = []
|
|
2186
|
-
for (let i = 0; i < sanitizedHex.length; i += 2) {
|
|
2187
|
-
result.push(parseInt(sanitizedHex.substr(i, 2), 16))
|
|
2188
|
-
}
|
|
2189
|
-
return result
|
|
2190
|
-
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
//@ts-nocheck
|
|
2
1
|
import * as bsv from '@bsv/sdk'
|
|
3
2
|
import { sdk, StorageProvider } from '../../../src/index.client'
|
|
4
3
|
import {
|
|
5
4
|
_tu,
|
|
6
5
|
expectToThrowWERR,
|
|
7
|
-
hexStringToNumberArray,
|
|
8
6
|
MockData,
|
|
9
|
-
TestSetup2,
|
|
10
7
|
TestWalletNoSetup
|
|
11
8
|
} from '../../utils/TestUtilsWalletStorage'
|
|
12
9
|
|
|
@@ -57,7 +54,7 @@ describe('listActions2 single action tests', () => {
|
|
|
57
54
|
beforeEach(async () => {
|
|
58
55
|
ctxs = []
|
|
59
56
|
const args = {
|
|
60
|
-
chain: 'test',
|
|
57
|
+
chain: <sdk.Chain>'test',
|
|
61
58
|
mockData,
|
|
62
59
|
databaseName: testName(),
|
|
63
60
|
rootKeyHex: '2'.repeat(64),
|
|
@@ -743,7 +740,7 @@ describe('listActions2 single action tests', () => {
|
|
|
743
740
|
vout: 2,
|
|
744
741
|
outputDescription: 'new description',
|
|
745
742
|
basketId: 1,
|
|
746
|
-
lockingScript:
|
|
743
|
+
lockingScript: bsv.Utils.toArray('0123456789abcdef', 'hex')
|
|
747
744
|
})
|
|
748
745
|
await storage.updateOutputTag(2, { tag: 'new tag' })
|
|
749
746
|
await storage.updateOutputTagMap(1, 2, {})
|
|
@@ -773,7 +770,7 @@ describe('listActions2 single action tests', () => {
|
|
|
773
770
|
vout: 2,
|
|
774
771
|
outputDescription: 'new description',
|
|
775
772
|
basketId: 1,
|
|
776
|
-
lockingScript:
|
|
773
|
+
lockingScript: bsv.Utils.toArray('0123456789abcdef', 'hex')
|
|
777
774
|
})
|
|
778
775
|
await storage.updateOutputTag(2, { tag: 'new tag' })
|
|
779
776
|
await storage.updateOutputTagMap(1, 2, {})
|
|
@@ -1243,7 +1240,7 @@ describe('listActions2 two action tests', () => {
|
|
|
1243
1240
|
beforeEach(async () => {
|
|
1244
1241
|
ctxs = []
|
|
1245
1242
|
const args = {
|
|
1246
|
-
chain: 'test',
|
|
1243
|
+
chain: <sdk.Chain>'test',
|
|
1247
1244
|
mockData,
|
|
1248
1245
|
databaseName: testName(),
|
|
1249
1246
|
rootKeyHex: '2'.repeat(64),
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"postBeefToArcTaal.test.d.ts","sourceRoot":"","sources":["../../../../src/services/__tests/postBeefToArcTaal.test.ts"],"names":[],"mappings":""}
|