@bsv/wallet-toolbox 1.6.43 → 1.7.0
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 +7 -0
- package/docs/client.md +152 -88
- package/docs/storage.md +47 -11
- package/docs/wallet.md +152 -88
- package/mobile/out/src/sdk/WERR_errors.d.ts +13 -0
- package/mobile/out/src/sdk/WERR_errors.d.ts.map +1 -1
- package/mobile/out/src/sdk/WERR_errors.js +25 -1
- package/mobile/out/src/sdk/WERR_errors.js.map +1 -1
- package/mobile/out/src/sdk/WalletStorage.interfaces.d.ts +3 -1
- package/mobile/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/createAction.d.ts +1 -13
- package/mobile/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/createAction.js +3 -40
- package/mobile/out/src/storage/methods/createAction.js.map +1 -1
- package/mobile/out/src/storage/methods/getBeefForTransaction.js +9 -1
- package/mobile/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
- package/mobile/out/src/storage/methods/offsetKey.d.ts +24 -0
- package/mobile/out/src/storage/methods/offsetKey.d.ts.map +1 -0
- package/mobile/out/src/storage/methods/offsetKey.js +67 -0
- package/mobile/out/src/storage/methods/offsetKey.js.map +1 -0
- package/mobile/package-lock.json +6 -6
- package/mobile/package.json +2 -2
- package/out/src/sdk/WERR_errors.d.ts +13 -0
- package/out/src/sdk/WERR_errors.d.ts.map +1 -1
- package/out/src/sdk/WERR_errors.js +25 -1
- package/out/src/sdk/WERR_errors.js.map +1 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts +3 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/out/src/storage/methods/__test/offsetKey.test.d.ts +2 -0
- package/out/src/storage/methods/__test/offsetKey.test.d.ts.map +1 -0
- package/out/src/storage/methods/__test/offsetKey.test.js +216 -0
- package/out/src/storage/methods/__test/offsetKey.test.js.map +1 -0
- package/out/src/storage/methods/createAction.d.ts +1 -13
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js +3 -40
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/methods/getBeefForTransaction.js +9 -1
- package/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
- package/out/src/storage/methods/offsetKey.d.ts +24 -0
- package/out/src/storage/methods/offsetKey.d.ts.map +1 -0
- package/out/src/storage/methods/offsetKey.js +67 -0
- package/out/src/storage/methods/offsetKey.js.map +1 -0
- package/out/test/Wallet/support/operations.man.test.js +2 -2
- package/out/test/Wallet/support/operations.man.test.js.map +1 -1
- package/out/test/WalletClient/WERR.man.test.js +26 -16
- package/out/test/WalletClient/WERR.man.test.js.map +1 -1
- 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 +2 -0
- package/out/test/utils/TestUtilsWalletStorage.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/sdk/WERR_errors.ts +25 -0
- package/src/sdk/WalletStorage.interfaces.ts +3 -0
- package/src/storage/methods/__test/offsetKey.test.ts +274 -0
- package/src/storage/methods/createAction.ts +3 -68
- package/src/storage/methods/getBeefForTransaction.ts +10 -2
- package/src/storage/methods/offsetKey.ts +89 -0
- package/test/Wallet/support/operations.man.test.ts +2 -2
- package/test/WalletClient/WERR.man.test.ts +27 -16
- package/test/utils/TestUtilsWalletStorage.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsv/wallet-toolbox",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@bsv/auth-express-middleware": "^1.2.3",
|
|
35
35
|
"@bsv/payment-express-middleware": "^1.2.3",
|
|
36
|
-
"@bsv/sdk": "^1.
|
|
36
|
+
"@bsv/sdk": "^1.9.3",
|
|
37
37
|
"express": "^4.21.2",
|
|
38
38
|
"idb": "^8.0.2",
|
|
39
39
|
"knex": "^3.1.0",
|
package/src/sdk/WERR_errors.ts
CHANGED
|
@@ -62,6 +62,31 @@ export class WERR_INVALID_PARAMETER extends WalletError {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Invalid merkleRoot ${merkleRoot} for block ${blockHash} at height ${blockHeight}${txid ? ` for txid ${txid}` : ''}.
|
|
67
|
+
*
|
|
68
|
+
* Typically thrown when a chain tracker fails to validate a merkle root.
|
|
69
|
+
*/
|
|
70
|
+
export class WERR_INVALID_MERKLE_ROOT extends WalletError {
|
|
71
|
+
constructor(
|
|
72
|
+
public blockHash: string,
|
|
73
|
+
public blockHeight: number,
|
|
74
|
+
public merkleRoot: string,
|
|
75
|
+
public txid?: string,
|
|
76
|
+
) {
|
|
77
|
+
super('WERR_INVALID_MERKLE_ROOT', `Invalid merkleRoot ${merkleRoot} for block ${blockHash} at height ${blockHeight}${txid ? ` for txid ${txid}` : ''}.`)
|
|
78
|
+
}
|
|
79
|
+
override toJson(): string {
|
|
80
|
+
const obj = JSON.parse(super.toJson())
|
|
81
|
+
obj.code = 8 // Must match HTTPWalletJSON.ts code
|
|
82
|
+
obj.blockHash = this.blockHash
|
|
83
|
+
obj.blockHeight = this.blockHeight
|
|
84
|
+
obj.merkleRoot = this.merkleRoot
|
|
85
|
+
obj.txid = this.txid
|
|
86
|
+
return JSON.stringify(obj)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
65
90
|
/**
|
|
66
91
|
* The required ${parameter} parameter is missing.
|
|
67
92
|
*
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
AbortActionArgs,
|
|
3
3
|
AbortActionResult,
|
|
4
4
|
Beef,
|
|
5
|
+
ChainTracker,
|
|
5
6
|
InternalizeActionArgs,
|
|
6
7
|
InternalizeActionResult,
|
|
7
8
|
ListActionsArgs,
|
|
@@ -387,6 +388,8 @@ export interface StorageGetBeefOptions {
|
|
|
387
388
|
ignoreNewProven?: boolean
|
|
388
389
|
/** optional. Default is zero. Ignores available merkle paths until recursion detpth equals or exceeds value */
|
|
389
390
|
minProofLevel?: number
|
|
391
|
+
/** optional. If valid, any merkleRoot that fails to validate will result in an exception without merging to `mergeToBeef`. */
|
|
392
|
+
chainTracker?: ChainTracker
|
|
390
393
|
}
|
|
391
394
|
|
|
392
395
|
export interface StorageSyncReaderOptions {
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Beef,
|
|
3
|
+
BigNumber,
|
|
4
|
+
CreateActionArgs,
|
|
5
|
+
CreateActionInput,
|
|
6
|
+
CreateActionOptions,
|
|
7
|
+
Curve,
|
|
8
|
+
P2PKH,
|
|
9
|
+
PositiveIntegerOrZero,
|
|
10
|
+
PrivateKey,
|
|
11
|
+
SignActionArgs,
|
|
12
|
+
SignActionSpend,
|
|
13
|
+
Utils
|
|
14
|
+
} from '@bsv/sdk'
|
|
15
|
+
import { keyOffsetToHashedSecret, lockScriptWithKeyOffsetFromPubKey, offsetPrivKey, offsetPubKey } from '../offsetKey'
|
|
16
|
+
import { _tu, TestWalletOnly } from '../../../../test/utils/TestUtilsWalletStorage'
|
|
17
|
+
import { Setup } from '../../../Setup'
|
|
18
|
+
import { StorageKnex } from '../../StorageKnex'
|
|
19
|
+
import { FindCommissionsArgs, FindTransactionsArgs } from '../../../sdk'
|
|
20
|
+
import { verifyOne, verifyTruthy } from '../../../utility/utilityHelpers'
|
|
21
|
+
import { TableCommission } from '../../schema/tables/TableCommission'
|
|
22
|
+
import { WalletStorageManager } from '../../WalletStorageManager'
|
|
23
|
+
|
|
24
|
+
describe('offsetKey tests', () => {
|
|
25
|
+
jest.setTimeout(99999999)
|
|
26
|
+
|
|
27
|
+
test('1_offsetPrivKey', async () => {
|
|
28
|
+
const bn2 = BigNumber.fromHex('FFF0000000000000000000000000000000000000000000000000000000000100', 'big')
|
|
29
|
+
|
|
30
|
+
const priv2 = new PrivateKey(bn2)
|
|
31
|
+
|
|
32
|
+
const privKey2 = priv2.toWif()
|
|
33
|
+
|
|
34
|
+
const keyOffset = 'KyaVZ1AnxYN4oB8JnxYVyZ8xYC9ySpq2Umzx6jwzQGVo71k1EgSt'
|
|
35
|
+
const oPrivKey = 'KyMYVLNeyF4qQsgHW3N1eJv9WcRd2aZC8hw7iLgCojQsyizqKsV4'
|
|
36
|
+
|
|
37
|
+
const r12 = offsetPrivKey(privKey2, keyOffset)
|
|
38
|
+
|
|
39
|
+
expect(r12.keyOffset).toBe(keyOffset)
|
|
40
|
+
|
|
41
|
+
expect(r12.offsetPrivKey).toBe(oPrivKey)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('2_offsetPubKey', async () => {
|
|
45
|
+
const bn2 = BigNumber.fromHex('FFF0000000000000000000000000000000000000000000000000000000000100', 'big')
|
|
46
|
+
|
|
47
|
+
const priv2 = new PrivateKey(bn2)
|
|
48
|
+
|
|
49
|
+
const pub2 = priv2.toPublicKey()
|
|
50
|
+
|
|
51
|
+
const keyOffset = 'KyaVZ1AnxYN4oB8JnxYVyZ8xYC9ySpq2Umzx6jwzQGVo71k1EgSt'
|
|
52
|
+
const oPrivKey = 'KyMYVLNeyF4qQsgHW3N1eJv9WcRd2aZC8hw7iLgCojQsyizqKsV4'
|
|
53
|
+
const oPubKey = '024b4362ce98e0afd22bf3319831cfaf691ad2f08471a3386bcda98d65435a0f24'
|
|
54
|
+
|
|
55
|
+
const r22 = offsetPubKey(pub2.toString(), keyOffset)
|
|
56
|
+
|
|
57
|
+
expect(r22.keyOffset).toBe(keyOffset)
|
|
58
|
+
|
|
59
|
+
expect(r22.offsetPubKey).toBe(oPubKey)
|
|
60
|
+
|
|
61
|
+
const pubKey2 = PrivateKey.fromWif(oPrivKey).toPublicKey().toString()
|
|
62
|
+
|
|
63
|
+
expect(pubKey2).toBe(oPubKey)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('3_lockScriptWithKeyOffsetFromPubKey', async () => {
|
|
67
|
+
const pubKey = '0397742eaef6c7f08c4aa057397d45529f93ab90345b84ce5a5aac06ea9cdd132e'
|
|
68
|
+
|
|
69
|
+
const ko = 'Kx9MjojdkjL3bEo5tQwHpwT1voKN1z56NjpATsa2Sx6QTrVjgMQJ'
|
|
70
|
+
const script = '76a9149d09d0ee09b212c548f6b1a7835641f33654246788ac'
|
|
71
|
+
|
|
72
|
+
const r1 = lockScriptWithKeyOffsetFromPubKey(pubKey, ko)
|
|
73
|
+
|
|
74
|
+
expect(r1.script).toBe(script)
|
|
75
|
+
expect(r1.keyOffset).toBe(ko)
|
|
76
|
+
|
|
77
|
+
// And with a random keyOffset...
|
|
78
|
+
const r2 = lockScriptWithKeyOffsetFromPubKey(pubKey)
|
|
79
|
+
|
|
80
|
+
expect(r2.script).not.toBe(script)
|
|
81
|
+
expect(r2.keyOffset).not.toBe(ko)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('4a_check keyOffset address', async () => {
|
|
85
|
+
if (_tu.noEnv('main')) return
|
|
86
|
+
|
|
87
|
+
const env = _tu.getEnv('main')
|
|
88
|
+
const privHex = env.devKeys[env.commissionsIdentity]!
|
|
89
|
+
const priv = PrivateKey.fromHex(privHex)
|
|
90
|
+
const pub = priv.toPublicKey()
|
|
91
|
+
|
|
92
|
+
const keyOffset = 'L2hMY5uW6Vh46DEFMzrYiKSFWDRSMGDTsaeDvhiKNNJGihwKD17w'
|
|
93
|
+
|
|
94
|
+
const r = offsetPrivKey(priv.toWif(), keyOffset)
|
|
95
|
+
const privO = PrivateKey.fromWif(r.offsetPrivKey)
|
|
96
|
+
const address = privO.toAddress()
|
|
97
|
+
expect(address).toBe('1EZz5oxwXoG6LgGLxeYPeg1NfzQrP1vL6M')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test('4_redeemServiceCharges', async () => {
|
|
101
|
+
if (_tu.noEnv('main')) return
|
|
102
|
+
|
|
103
|
+
const env = _tu.getEnv('main')
|
|
104
|
+
if (!env.devKeys[env.commissionsIdentity]) {
|
|
105
|
+
throw new Error('No dev key for commissions identity')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const knex = Setup.createMySQLKnex(process.env.MAIN_CLOUD_MYSQL_CONNECTION!)
|
|
109
|
+
const storage = new StorageKnex({
|
|
110
|
+
chain: env.chain,
|
|
111
|
+
knex: knex,
|
|
112
|
+
commissionSatoshis: 0,
|
|
113
|
+
commissionPubKeyHex: undefined,
|
|
114
|
+
feeModel: { model: 'sat/kb', value: 1 }
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
let setup: TestWalletOnly
|
|
118
|
+
await storage.makeAvailable()
|
|
119
|
+
|
|
120
|
+
setup = await _tu.createTestWalletWithStorageClient({
|
|
121
|
+
chain: 'main',
|
|
122
|
+
rootKeyHex: env.devKeys[env.commissionsIdentity]
|
|
123
|
+
})
|
|
124
|
+
storage.setServices(setup.services)
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// await setup.wallet.abortAction({ reference: 'e9c03bdf603e90ebe482044e8d0f7afbf2d6fe480a13dbd8689e2e5e5183bed4' })
|
|
128
|
+
|
|
129
|
+
// txid b6f72df4224efbacab42a16e1e88f48c217f03929c36987b9067d2556de47c10
|
|
130
|
+
// height 922107
|
|
131
|
+
// hash 00000000000000001957bfadf841d1709d5039b3243c33ba58e4a6a97b44d2a8
|
|
132
|
+
const sm = new WalletStorageManager(setup.identityKey, storage)
|
|
133
|
+
sm.setServices(setup.services)
|
|
134
|
+
await sm.reproveHeader('000000000000000014d97d19bf82956c1f7ce3977da10b7fbdab9a10653c02e7')
|
|
135
|
+
|
|
136
|
+
const comms: TableCommission[] = []
|
|
137
|
+
const beef = new Beef()
|
|
138
|
+
const chainTracker = await setup.services.getChainTracker()
|
|
139
|
+
const inputs: CreateActionInput[] = []
|
|
140
|
+
|
|
141
|
+
const fca: FindCommissionsArgs = {
|
|
142
|
+
partial: { isRedeemed: false },
|
|
143
|
+
paged: { limit: 200, offset: 0 }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
for (; comms.length < fca.paged!.limit; ) {
|
|
147
|
+
const unredeemedComms = await storage.findCommissions(fca)
|
|
148
|
+
if (unredeemedComms.length === 0) break
|
|
149
|
+
for (const comm of unredeemedComms) {
|
|
150
|
+
const tt = verifyTruthy(await storage.findTransactionById(comm.transactionId, undefined, true))
|
|
151
|
+
if (tt.provenTxId && tt.txid) {
|
|
152
|
+
// Only add merge valid beefs...
|
|
153
|
+
try {
|
|
154
|
+
await storage.getBeefForTransaction(tt.txid, { mergeToBeef: beef, chainTracker })
|
|
155
|
+
} catch (e) {
|
|
156
|
+
// Ignore errors in merging beefs
|
|
157
|
+
}
|
|
158
|
+
const tx = verifyTruthy(beef.findTxid(tt.txid)).tx!
|
|
159
|
+
const commVOut = tx.outputs.findIndex(
|
|
160
|
+
o => o.satoshis === comm.satoshis && o.lockingScript.toHex() === Utils.toHex(comm.lockingScript)
|
|
161
|
+
)
|
|
162
|
+
const commOut = tx.outputs[commVOut]
|
|
163
|
+
const input: CreateActionInput = {
|
|
164
|
+
outpoint: `${tt.txid}.${commVOut}`,
|
|
165
|
+
inputDescription: `commId:${comm.commissionId}`,
|
|
166
|
+
unlockingScriptLength: 108
|
|
167
|
+
}
|
|
168
|
+
inputs.push(input)
|
|
169
|
+
comms.push(comm)
|
|
170
|
+
if (comms.length >= fca.paged!.limit) break
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
fca.paged!.offset! += unredeemedComms.length
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (comms.length > 0) {
|
|
177
|
+
console.log(beef.toLogString())
|
|
178
|
+
const verified = await beef.verify(await setup.services.getChainTracker(), false)
|
|
179
|
+
expect(verified).toBe(true)
|
|
180
|
+
|
|
181
|
+
const cao: CreateActionOptions = {
|
|
182
|
+
randomizeOutputs: false,
|
|
183
|
+
//signAndProcess: false,
|
|
184
|
+
noSend: true
|
|
185
|
+
}
|
|
186
|
+
const ca: CreateActionArgs = {
|
|
187
|
+
description: 'redeem commissions',
|
|
188
|
+
inputs: inputs,
|
|
189
|
+
inputBEEF: beef.toBinary(),
|
|
190
|
+
options: cao
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const car = await setup.wallet.createAction(ca)
|
|
194
|
+
expect(car.signableTransaction).toBeTruthy()
|
|
195
|
+
|
|
196
|
+
const st = car.signableTransaction!
|
|
197
|
+
expect(st.reference).toBeTruthy()
|
|
198
|
+
const atomicBeef = Beef.fromBinary(st.tx)
|
|
199
|
+
const txid = atomicBeef.txs[atomicBeef.txs.length - 1].txid!
|
|
200
|
+
const tx = atomicBeef.findTransactionForSigning(txid)!
|
|
201
|
+
|
|
202
|
+
const priv = PrivateKey.fromHex(env.devKeys[env.commissionsIdentity])
|
|
203
|
+
const pub = priv.toPublicKey()
|
|
204
|
+
const curve = new Curve()
|
|
205
|
+
const p2pkh = new P2PKH()
|
|
206
|
+
const spends: Record<PositiveIntegerOrZero, SignActionSpend> = {}
|
|
207
|
+
let vin = 0
|
|
208
|
+
// set an unlockingScriptTemplate for each commission input being redeemed in unsigned tx
|
|
209
|
+
for (const comm of comms) {
|
|
210
|
+
const { hashedSecret } = keyOffsetToHashedSecret(pub, comm.keyOffset)
|
|
211
|
+
const bn = priv.add(hashedSecret).mod(curve.n)
|
|
212
|
+
const offsetPrivKey = new PrivateKey(bn)
|
|
213
|
+
const unlock = p2pkh.unlock(offsetPrivKey, 'all', false)
|
|
214
|
+
tx.inputs[vin].unlockingScriptTemplate = unlock
|
|
215
|
+
vin++
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// sign each input
|
|
219
|
+
await tx.sign()
|
|
220
|
+
|
|
221
|
+
vin = 0
|
|
222
|
+
// extract all the signed unlocking scripts
|
|
223
|
+
for (const comm of comms) {
|
|
224
|
+
const script = tx.inputs[vin].unlockingScript!
|
|
225
|
+
const unlockingScript = script.toHex()
|
|
226
|
+
spends[vin] = { unlockingScript }
|
|
227
|
+
vin++
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const signArgs: SignActionArgs = {
|
|
231
|
+
reference: st.reference,
|
|
232
|
+
spends,
|
|
233
|
+
options: {
|
|
234
|
+
returnTXIDOnly: true,
|
|
235
|
+
noSend: true
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Forward all the unlocking scripts to storage and create the ProvenTxReq for the noSend txid.
|
|
240
|
+
const sr = await setup.wallet.signAction(signArgs)
|
|
241
|
+
expect(sr.txid).toBeTruthy()
|
|
242
|
+
|
|
243
|
+
// Update the commissions as redeemed in storage
|
|
244
|
+
for (const comm of comms) {
|
|
245
|
+
await storage.updateCommission(comm.commissionId, { isRedeemed: true })
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
{
|
|
249
|
+
// Get the transaction broadcast
|
|
250
|
+
const createArgs: CreateActionArgs = {
|
|
251
|
+
description: `broadcasting noSend`,
|
|
252
|
+
options: {
|
|
253
|
+
acceptDelayedBroadcast: false,
|
|
254
|
+
sendWith: [sr.txid!]
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const cr = await setup.wallet.createAction(createArgs)
|
|
259
|
+
|
|
260
|
+
expect(cr.noSendChange).not.toBeTruthy()
|
|
261
|
+
expect(cr.sendWithResults?.length).toBe(1)
|
|
262
|
+
const [swr] = cr.sendWithResults!
|
|
263
|
+
expect(swr.status !== 'failed').toBe(true)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
} catch (err) {
|
|
267
|
+
console.error('Error in 4_redeemServiceCharges test:', err)
|
|
268
|
+
throw err
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
await storage.destroy()
|
|
272
|
+
await setup.wallet.destroy()
|
|
273
|
+
})
|
|
274
|
+
})
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Beef,
|
|
3
|
-
BigNumber,
|
|
4
|
-
Curve,
|
|
5
|
-
OriginatorDomainNameStringUnder250Bytes,
|
|
6
|
-
P2PKH,
|
|
7
|
-
PrivateKey,
|
|
8
|
-
PubKeyHex,
|
|
9
|
-
PublicKey,
|
|
10
|
-
Random,
|
|
11
|
-
ReviewActionResult,
|
|
12
|
-
Script,
|
|
13
|
-
Utils
|
|
14
|
-
} from '@bsv/sdk'
|
|
1
|
+
import { Beef, OriginatorDomainNameStringUnder250Bytes, Random, ReviewActionResult, Script, Utils } from '@bsv/sdk'
|
|
15
2
|
import {
|
|
16
3
|
generateChangeSdk,
|
|
17
4
|
GenerateChangeSdkChangeInput,
|
|
@@ -37,7 +24,6 @@ import {
|
|
|
37
24
|
import { WERR_INTERNAL, WERR_INVALID_PARAMETER, WERR_REVIEW_ACTIONS } from '../../sdk/WERR_errors'
|
|
38
25
|
import {
|
|
39
26
|
randomBytesBase64,
|
|
40
|
-
sha256Hash,
|
|
41
27
|
verifyId,
|
|
42
28
|
verifyInteger,
|
|
43
29
|
verifyNumber,
|
|
@@ -52,6 +38,7 @@ import { TableOutputTag } from '../schema/tables/TableOutputTag'
|
|
|
52
38
|
import { TableTransaction } from '../schema/tables/TableTransaction'
|
|
53
39
|
import { EntityProvenTx } from '../schema/entities/EntityProvenTx'
|
|
54
40
|
import { throwDummyReviewActions } from '../../Wallet'
|
|
41
|
+
import { createStorageServiceChargeScript } from './offsetKey'
|
|
55
42
|
|
|
56
43
|
let disableDoubleSpendCheckForTest = true
|
|
57
44
|
export function setDisableDoubleSpendCheckForTest(v: boolean) {
|
|
@@ -244,7 +231,7 @@ async function createNewInputs(
|
|
|
244
231
|
if (o2.spendable != true) {
|
|
245
232
|
throw new WERR_INVALID_PARAMETER(
|
|
246
233
|
`inputs[${i.vin}]`,
|
|
247
|
-
`spendable output. output ${o.txid}:${o.vout} appears to have been spent.`
|
|
234
|
+
`spendable output. output ${o.txid}:${o.vout} appears to have been spent (spendable=${o2.spendable}).`
|
|
248
235
|
)
|
|
249
236
|
}
|
|
250
237
|
await storage.updateOutput(
|
|
@@ -942,55 +929,3 @@ async function mergeAllocatedChangeBeefs(
|
|
|
942
929
|
}
|
|
943
930
|
return trimInputBeef(beef, vargs)
|
|
944
931
|
}
|
|
945
|
-
|
|
946
|
-
function keyOffsetToHashedSecret(pub: PublicKey, keyOffset?: string): { hashedSecret: BigNumber; keyOffset: string } {
|
|
947
|
-
let offset: PrivateKey
|
|
948
|
-
if (keyOffset !== undefined && typeof keyOffset === 'string') {
|
|
949
|
-
if (keyOffset.length === 64) offset = PrivateKey.fromString(keyOffset, 'hex')
|
|
950
|
-
else offset = PrivateKey.fromWif(keyOffset)
|
|
951
|
-
} else {
|
|
952
|
-
offset = PrivateKey.fromRandom()
|
|
953
|
-
keyOffset = offset.toWif()
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
const sharedSecret = pub.mul(offset).encode(true, undefined) as number[]
|
|
957
|
-
const hashedSecret = sha256Hash(sharedSecret)
|
|
958
|
-
|
|
959
|
-
return { hashedSecret: new BigNumber(hashedSecret), keyOffset }
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
export function offsetPubKey(pubKey: string, keyOffset?: string): { offsetPubKey: string; keyOffset: string } {
|
|
963
|
-
const pub = PublicKey.fromString(pubKey)
|
|
964
|
-
|
|
965
|
-
const r = keyOffsetToHashedSecret(pub, keyOffset)
|
|
966
|
-
|
|
967
|
-
// The hashed secret is multiplied by the generator point.
|
|
968
|
-
const point = new Curve().g.mul(r.hashedSecret)
|
|
969
|
-
|
|
970
|
-
// The resulting point is added to the recipient public key.
|
|
971
|
-
const offsetPubKey = new PublicKey(pub.add(point))
|
|
972
|
-
|
|
973
|
-
return { offsetPubKey: offsetPubKey.toString(), keyOffset: r.keyOffset }
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
export function lockScriptWithKeyOffsetFromPubKey(
|
|
977
|
-
pubKey: string,
|
|
978
|
-
keyOffset?: string
|
|
979
|
-
): { script: string; keyOffset: string } {
|
|
980
|
-
const r = offsetPubKey(pubKey, keyOffset)
|
|
981
|
-
|
|
982
|
-
const offsetPub = PublicKey.fromString(r.offsetPubKey)
|
|
983
|
-
|
|
984
|
-
const hash = offsetPub.toHash() as number[]
|
|
985
|
-
|
|
986
|
-
const script = new P2PKH().lock(hash).toHex()
|
|
987
|
-
|
|
988
|
-
return { script, keyOffset: r.keyOffset }
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
export function createStorageServiceChargeScript(pubKeyHex: PubKeyHex): {
|
|
992
|
-
script: string
|
|
993
|
-
keyOffset: string
|
|
994
|
-
} {
|
|
995
|
-
return lockScriptWithKeyOffsetFromPubKey(pubKeyHex)
|
|
996
|
-
}
|
|
@@ -2,7 +2,7 @@ import { Beef } from '@bsv/sdk'
|
|
|
2
2
|
import { StorageProvider } from '../StorageProvider'
|
|
3
3
|
import { ProvenOrRawTx, StorageGetBeefOptions } from '../../sdk/WalletStorage.interfaces'
|
|
4
4
|
import { EntityProvenTx } from '../schema/entities/EntityProvenTx'
|
|
5
|
-
import { WERR_INVALID_OPERATION, WERR_INVALID_PARAMETER } from '../../sdk/WERR_errors'
|
|
5
|
+
import { WERR_INVALID_MERKLE_ROOT, WERR_INVALID_OPERATION, WERR_INVALID_PARAMETER } from '../../sdk/WERR_errors'
|
|
6
6
|
import { asBsvSdkTx, verifyTruthy } from '../../utility/utilityHelpers'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -102,8 +102,16 @@ async function mergeBeefForTransactionRecurse(
|
|
|
102
102
|
if (r.proven) {
|
|
103
103
|
// storage has proven this txid,
|
|
104
104
|
// merge both the raw transaction and its merkle path
|
|
105
|
+
const mp = new EntityProvenTx(r.proven).getMerklePath()
|
|
106
|
+
if (options.chainTracker) {
|
|
107
|
+
const root = mp.computeRoot()
|
|
108
|
+
const isValid = await options.chainTracker.isValidRootForHeight(root, r.proven.height)
|
|
109
|
+
if (!isValid) {
|
|
110
|
+
throw new WERR_INVALID_MERKLE_ROOT(r.proven.blockHash, r.proven.height, root, txid)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
105
113
|
beef.mergeRawTx(r.proven.rawTx)
|
|
106
|
-
beef.mergeBump(
|
|
114
|
+
beef.mergeBump(mp)
|
|
107
115
|
return beef
|
|
108
116
|
}
|
|
109
117
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { PublicKey, BigNumber, PrivateKey, Curve, P2PKH, PubKeyHex, CreateActionInput } from '@bsv/sdk'
|
|
2
|
+
import { TableCommission } from '../schema/tables/TableCommission'
|
|
3
|
+
import { sha256Hash } from '../../utility/utilityHelpers'
|
|
4
|
+
|
|
5
|
+
export function keyOffsetToHashedSecret(
|
|
6
|
+
pub: PublicKey,
|
|
7
|
+
keyOffset?: string
|
|
8
|
+
): { hashedSecret: BigNumber; keyOffset: string } {
|
|
9
|
+
let offset: PrivateKey
|
|
10
|
+
if (keyOffset !== undefined && typeof keyOffset === 'string') {
|
|
11
|
+
if (keyOffset.length === 64) offset = PrivateKey.fromString(keyOffset, 'hex')
|
|
12
|
+
else offset = PrivateKey.fromWif(keyOffset)
|
|
13
|
+
} else {
|
|
14
|
+
offset = PrivateKey.fromRandom()
|
|
15
|
+
keyOffset = offset.toWif()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const sharedSecret = pub.mul(offset).encode(true, undefined) as number[]
|
|
19
|
+
const hashedSecret = sha256Hash(sharedSecret)
|
|
20
|
+
|
|
21
|
+
return { hashedSecret: new BigNumber(hashedSecret), keyOffset }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function offsetPrivKey(privKey: string, keyOffset?: string): { offsetPrivKey: string; keyOffset: string } {
|
|
25
|
+
const priv = PrivateKey.fromWif(privKey)
|
|
26
|
+
|
|
27
|
+
const pub = priv.toPublicKey()
|
|
28
|
+
|
|
29
|
+
const r = keyOffsetToHashedSecret(pub, keyOffset)
|
|
30
|
+
|
|
31
|
+
const bn = priv.add(r.hashedSecret).mod(new Curve().n)
|
|
32
|
+
|
|
33
|
+
const offsetPrivKey = new PrivateKey(bn).toWif()
|
|
34
|
+
|
|
35
|
+
return { offsetPrivKey, keyOffset: r.keyOffset }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function offsetPubKey(pubKey: string, keyOffset?: string): { offsetPubKey: string; keyOffset: string } {
|
|
39
|
+
const pub = PublicKey.fromString(pubKey)
|
|
40
|
+
|
|
41
|
+
const r = keyOffsetToHashedSecret(pub, keyOffset)
|
|
42
|
+
|
|
43
|
+
// The hashed secret is multiplied by the generator point.
|
|
44
|
+
const point = new Curve().g.mul(r.hashedSecret)
|
|
45
|
+
|
|
46
|
+
// The resulting point is added to the recipient public key.
|
|
47
|
+
const offsetPubKey = new PublicKey(pub.add(point))
|
|
48
|
+
|
|
49
|
+
return { offsetPubKey: offsetPubKey.toString(), keyOffset: r.keyOffset }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function lockScriptWithKeyOffsetFromPubKey(
|
|
53
|
+
pubKey: string,
|
|
54
|
+
keyOffset?: string
|
|
55
|
+
): { script: string; keyOffset: string } {
|
|
56
|
+
const r = offsetPubKey(pubKey, keyOffset)
|
|
57
|
+
|
|
58
|
+
const offsetPub = PublicKey.fromString(r.offsetPubKey)
|
|
59
|
+
|
|
60
|
+
const hash = offsetPub.toHash() as number[]
|
|
61
|
+
|
|
62
|
+
const script = new P2PKH().lock(hash).toHex()
|
|
63
|
+
|
|
64
|
+
return { script, keyOffset: r.keyOffset }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function createStorageServiceChargeScript(pubKeyHex: PubKeyHex): {
|
|
68
|
+
script: string
|
|
69
|
+
keyOffset: string
|
|
70
|
+
} {
|
|
71
|
+
return lockScriptWithKeyOffsetFromPubKey(pubKeyHex)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function redeemServiceCharges(privateKeyWif: string, charges: TableCommission[]): {}[] {
|
|
75
|
+
const priv = PrivateKey.fromWif(privateKeyWif)
|
|
76
|
+
const pub = priv.toPublicKey()
|
|
77
|
+
const p2pkh = new P2PKH()
|
|
78
|
+
|
|
79
|
+
const inputs: CreateActionInput[] = []
|
|
80
|
+
|
|
81
|
+
for (const c of charges) {
|
|
82
|
+
const { hashedSecret } = keyOffsetToHashedSecret(pub, c.keyOffset)
|
|
83
|
+
const bn = priv.add(hashedSecret).mod(new Curve().n)
|
|
84
|
+
const offsetPrivKey = new PrivateKey(bn)
|
|
85
|
+
//const unlock = p2pkh.unlock(offsetPrivKey, signOutputs, anyoneCanPay)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return []
|
|
89
|
+
}
|
|
@@ -49,7 +49,7 @@ describe('operations.man tests', () => {
|
|
|
49
49
|
|
|
50
50
|
test('1 review and unfail false doubleSpends', async () => {
|
|
51
51
|
const { env, storage, services } = await _tu.createMainReviewSetup()
|
|
52
|
-
let offset =
|
|
52
|
+
let offset = 400
|
|
53
53
|
const limit = 100
|
|
54
54
|
let allUnfails: number[] = []
|
|
55
55
|
let reviewed = 0
|
|
@@ -82,7 +82,7 @@ describe('operations.man tests', () => {
|
|
|
82
82
|
|
|
83
83
|
test('2 review and unfail false invalids', async () => {
|
|
84
84
|
const { env, storage, services } = await _tu.createMainReviewSetup()
|
|
85
|
-
let offset =
|
|
85
|
+
let offset = 500
|
|
86
86
|
const limit = 100
|
|
87
87
|
let allUnfails: number[] = []
|
|
88
88
|
let reviewed = 0
|
|
@@ -2,23 +2,34 @@ import { CreateActionArgs, WalletClient } from '@bsv/sdk'
|
|
|
2
2
|
import { specOpThrowReviewActions } from '../../src/sdk/types'
|
|
3
3
|
import { WalletError } from '../../src/sdk/WalletError'
|
|
4
4
|
import { WERR_REVIEW_ACTIONS } from '../../src/sdk/WERR_errors'
|
|
5
|
-
import { validateCreateActionArgs } from '../../src/sdk'
|
|
5
|
+
import { validateCreateActionArgs, WalletErrorFromJson } from '../../src/sdk'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
describe('WERR.man tests', () => {
|
|
8
|
+
jest.setTimeout(99999999)
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
description: 'must throw'
|
|
13
|
-
}
|
|
14
|
-
const vargs = validateCreateActionArgs(args)
|
|
10
|
+
test('0 WERR_REVIEW_ACTIONS via WalletClient', async () => {
|
|
11
|
+
const wallet = new WalletClient('auto', '0.WERR.man.test')
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
const args: CreateActionArgs = {
|
|
14
|
+
labels: [specOpThrowReviewActions],
|
|
15
|
+
description: 'must throw'
|
|
16
|
+
}
|
|
17
|
+
const vargs = validateCreateActionArgs(args)
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const r = await wallet.createAction(args)
|
|
21
|
+
expect(true).toBe(false)
|
|
22
|
+
} catch (eu: unknown) {
|
|
23
|
+
const e = WalletError.fromUnknown(eu) as WERR_REVIEW_ACTIONS
|
|
24
|
+
expect(e.code).toBe('WERR_REVIEW_ACTIONS')
|
|
25
|
+
expect(e.reviewActionResults).toBeTruthy()
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('1', async () => {
|
|
30
|
+
const s = `{\"isError\":true,\"name\":\"WERR_REVIEW_ACTIONS\",\"reviewActionResults\":[{\"txid\":\"344556f1c428367689e09e29aa4dc7cfe755db1fab5cf7c1cf8d1f99b507004b\",\"status\":\"doubleSpend\",\"competingTxs\":[\"344556f1c428367689e09e29aa4dc7cfe755db1fab5cf7c1cf8d1f99b507004b\"],\"competingBeef\":[1,0,190,239,1,254,12,52,25,0,3,2,2,2,13,153,15,202,45,179,254,102,34,161,222,144,207,214,224,219,57,76,176,248,213,137,238,7,63,67,204,253,45,62,70,190,3,0,206,69,142,120,152,200,85,221,140,68,16,34,144,39,29,181,67,66,245,76,24,46,209,253,246,204,133,193,175,188,98,241,2,0,0,119,165,81,236,153,173,143,252,69,138,209,229,97,189,36,123,84,160,234,127,63,185,82,5,26,106,157,73,26,107,32,100,1,0,143,243,215,201,227,2,63,39,103,57,216,42,131,190,76,56,216,43,104,59,7,4,174,137,191,49,49,128,249,252,45,42,2,0,0,25,6,223,99,50,23,119,231,67,155,160,205,224,45,74,194,190,202,18,106,135,17,234,165,66,245,89,135,90,255,10,227,1,0,35,96,209,29,146,83,58,174,231,36,40,57,137,94,136,75,149,86,89,160,195,121,92,180,37,191,31,187,23,71,219,209,2,1,0,0,0,2,1,247,147,92,34,59,244,55,220,70,138,231,75,160,174,137,68,202,34,151,142,102,170,47,246,106,0,25,152,90,245,197,0,0,0,0,106,71,48,68,2,32,23,143,242,5,200,252,85,12,167,137,194,54,96,107,40,141,240,219,145,62,182,133,119,224,94,146,94,249,214,213,212,121,2,32,15,130,24,137,152,12,86,54,141,67,39,178,80,29,110,48,77,114,212,69,237,139,89,152,246,124,138,91,19,32,71,43,65,33,3,16,229,154,223,195,210,19,58,106,26,124,66,99,139,137,43,164,213,109,60,35,235,32,30,122,36,252,12,131,190,69,63,255,255,255,255,1,247,147,92,34,59,244,55,220,70,138,231,75,160,174,137,68,202,34,151,142,102,170,47,246,106,0,25,152,90,245,197,2,0,0,0,107,72,48,69,2,33,0,154,55,50,224,237,75,147,58,95,164,173,104,149,13,24,125,198,35,126,194,134,91,150,238,179,25,192,213,136,196,51,66,2,32,98,84,153,139,248,106,241,122,65,180,241,124,30,233,140,74,172,74,217,165,129,143,127,156,49,230,34,46,188,15,28,52,65,33,2,146,89,63,53,57,196,48,37,118,17,182,193,201,75,44,105,67,181,136,23,25,104,127,48,146,231,88,99,197,53,56,239,255,255,255,255,2,225,3,0,0,0,0,0,0,25,118,169,20,255,161,196,19,38,201,6,21,136,26,207,151,137,162,75,232,58,201,53,88,136,172,1,0,0,0,0,0,0,0,25,118,169,20,39,140,42,205,54,197,3,247,165,173,16,224,138,193,127,34,191,29,126,7,136,172,0,0,0,0,1,0,1,0,0,0,1,13,153,15,202,45,179,254,102,34,161,222,144,207,214,224,219,57,76,176,248,213,137,238,7,63,67,204,253,45,62,70,190,0,0,0,0,106,71,48,68,2,32,113,14,233,125,141,249,154,234,138,195,178,164,149,171,255,63,165,28,128,191,230,247,66,128,150,223,65,199,233,39,23,251,2,32,80,77,229,88,242,236,59,27,87,164,79,120,131,240,100,247,182,28,231,200,43,86,4,88,118,214,123,86,89,234,15,220,65,33,2,126,31,155,113,109,251,248,50,61,159,13,216,133,12,125,72,157,20,95,38,54,244,202,14,140,141,176,184,127,210,62,36,255,255,255,255,3,42,0,0,0,0,0,0,0,25,118,169,20,56,12,202,72,139,24,243,136,130,254,20,130,110,109,96,207,112,30,168,123,136,172,1,0,0,0,0,0,0,0,25,118,169,20,70,66,47,177,97,74,57,246,237,66,211,206,113,253,228,175,14,128,182,53,136,172,181,3,0,0,0,0,0,0,25,118,169,20,168,166,193,185,78,43,31,133,215,58,172,227,98,32,56,171,116,85,185,171,136,172,0,0,0,0,0]}],\"sendWithResults\":[{\"txid\":\"344556f1c428367689e09e29aa4dc7cfe755db1fab5cf7c1cf8d1f99b507004b\",\"status\":\"failed\"}],\"txid\":\"344556f1c428367689e09e29aa4dc7cfe755db1fab5cf7c1cf8d1f99b507004b\",\"tx\":[1,1,1,1,75,0,7,181,153,31,141,207,193,247,92,171,31,219,85,231,207,199,77,170,41,158,224,137,118,54,40,196,241,86,69,52,1,0,190,239,1,254,12,52,25,0,3,2,2,2,13,153,15,202,45,179,254,102,34,161,222,144,207,214,224,219,57,76,176,248,213,137,238,7,63,67,204,253,45,62,70,190,3,0,206,69,142,120,152,200,85,221,140,68,16,34,144,39,29,181,67,66,245,76,24,46,209,253,246,204,133,193,175,188,98,241,2,0,0,119,165,81,236,153,173,143,252,69,138,209,229,97,189,36,123,84,160,234,127,63,185,82,5,26,106,157,73,26,107,32,100,1,0,143,243,215,201,227,2,63,39,103,57,216,42,131,190,76,56,216,43,104,59,7,4,174,137,191,49,49,128,249,252,45,42,2,0,0,25,6,223,99,50,23,119,231,67,155,160,205,224,45,74,194,190,202,18,106,135,17,234,165,66,245,89,135,90,255,10,227,1,0,35,96,209,29,146,83,58,174,231,36,40,57,137,94,136,75,149,86,89,160,195,121,92,180,37,191,31,187,23,71,219,209,2,1,0,0,0,2,1,247,147,92,34,59,244,55,220,70,138,231,75,160,174,137,68,202,34,151,142,102,170,47,246,106,0,25,152,90,245,197,0,0,0,0,106,71,48,68,2,32,23,143,242,5,200,252,85,12,167,137,194,54,96,107,40,141,240,219,145,62,182,133,119,224,94,146,94,249,214,213,212,121,2,32,15,130,24,137,152,12,86,54,141,67,39,178,80,29,110,48,77,114,212,69,237,139,89,152,246,124,138,91,19,32,71,43,65,33,3,16,229,154,223,195,210,19,58,106,26,124,66,99,139,137,43,164,213,109,60,35,235,32,30,122,36,252,12,131,190,69,63,255,255,255,255,1,247,147,92,34,59,244,55,220,70,138,231,75,160,174,137,68,202,34,151,142,102,170,47,246,106,0,25,152,90,245,197,2,0,0,0,107,72,48,69,2,33,0,154,55,50,224,237,75,147,58,95,164,173,104,149,13,24,125,198,35,126,194,134,91,150,238,179,25,192,213,136,196,51,66,2,32,98,84,153,139,248,106,241,122,65,180,241,124,30,233,140,74,172,74,217,165,129,143,127,156,49,230,34,46,188,15,28,52,65,33,2,146,89,63,53,57,196,48,37,118,17,182,193,201,75,44,105,67,181,136,23,25,104,127,48,146,231,88,99,197,53,56,239,255,255,255,255,2,225,3,0,0,0,0,0,0,25,118,169,20,255,161,196,19,38,201,6,21,136,26,207,151,137,162,75,232,58,201,53,88,136,172,1,0,0,0,0,0,0,0,25,118,169,20,39,140,42,205,54,197,3,247,165,173,16,224,138,193,127,34,191,29,126,7,136,172,0,0,0,0,1,0,1,0,0,0,1,13,153,15,202,45,179,254,102,34,161,222,144,207,214,224,219,57,76,176,248,213,137,238,7,63,67,204,253,45,62,70,190,0,0,0,0,106,71,48,68,2,32,113,14,233,125,141,249,154,234,138,195,178,164,149,171,255,63,165,28,128,191,230,247,66,128,150,223,65,199,233,39,23,251,2,32,80,77,229,88,242,236,59,27,87,164,79,120,131,240,100,247,182,28,231,200,43,86,4,88,118,214,123,86,89,234,15,220,65,33,2,126,31,155,113,109,251,248,50,61,159,13,216,133,12,125,72,157,20,95,38,54,244,202,14,140,141,176,184,127,210,62,36,255,255,255,255,3,42,0,0,0,0,0,0,0,25,118,169,20,56,12,202,72,139,24,243,136,130,254,20,130,110,109,96,207,112,30,168,123,136,172,1,0,0,0,0,0,0,0,25,118,169,20,70,66,47,177,97,74,57,246,237,66,211,206,113,253,228,175,14,128,182,53,136,172,181,3,0,0,0,0,0,0,25,118,169,20,168,166,193,185,78,43,31,133,215,58,172,227,98,32,56,171,116,85,185,171,136,172,0,0,0,0,0],\"noSendChange\":[\"344556f1c428367689e09e29aa4dc7cfe755db1fab5cf7c1cf8d1f99b507004b.0\"]}`
|
|
31
|
+
const o = JSON.parse(s)
|
|
32
|
+
const e = WalletErrorFromJson(o)
|
|
33
|
+
expect(e instanceof WERR_REVIEW_ACTIONS).toBe(true)
|
|
34
|
+
})
|
|
24
35
|
})
|
|
@@ -77,6 +77,7 @@ export interface TuEnv extends TuEnvFlags {
|
|
|
77
77
|
taalApiKey: string
|
|
78
78
|
bitailsApiKey: string
|
|
79
79
|
whatsonchainApiKey: string
|
|
80
|
+
commissionsIdentity: string
|
|
80
81
|
devKeys: Record<string, string>
|
|
81
82
|
/**
|
|
82
83
|
* file path to local sqlite file for identityKey
|
|
@@ -147,6 +148,8 @@ export abstract class TestUtilsWalletStorage {
|
|
|
147
148
|
const bitailsApiKey = (chain === 'main' ? process.env.MAIN_BITAILS_API_KEY : process.env.TEST_BITAILS_API_KEY) || ''
|
|
148
149
|
const whatsonchainApiKey =
|
|
149
150
|
(chain === 'main' ? process.env.MAIN_WHATSONCHAIN_API_KEY : process.env.TEST_WHATSONCHAIN_API_KEY) || ''
|
|
151
|
+
const commissionsIdentity =
|
|
152
|
+
(chain === 'main' ? process.env.MAIN_COMMISSIONS_IDENTITY : process.env.TEST_COMMISSIONS_IDENTITY) || ''
|
|
150
153
|
return {
|
|
151
154
|
...flagsEnv,
|
|
152
155
|
identityKey,
|
|
@@ -154,6 +157,7 @@ export abstract class TestUtilsWalletStorage {
|
|
|
154
157
|
taalApiKey,
|
|
155
158
|
bitailsApiKey,
|
|
156
159
|
whatsonchainApiKey,
|
|
160
|
+
commissionsIdentity,
|
|
157
161
|
devKeys: JSON.parse(DEV_KEYS) as Record<string, string>,
|
|
158
162
|
filePath,
|
|
159
163
|
testIdentityKey,
|