@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsv/wallet-toolbox",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.14",
|
|
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",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"test": "npm run build && jest --testPathIgnorePatterns=man.test.ts",
|
|
21
21
|
"test:watch": "npm run build && jest --testPathIgnorePatterns=man.test.ts --watch",
|
|
22
22
|
"test:coverage": "npm run build && jest --testPathIgnorePatterns=man.test.ts --coverage",
|
|
23
|
-
"lint": "prettier --write 'src/**/*.ts' --write 'test/**/*.ts' --
|
|
23
|
+
"lint": "prettier --write 'src/**/*.ts' --write 'test/**/*.ts' --log-level silent",
|
|
24
24
|
"build": "tsc --build",
|
|
25
25
|
"prepublish": "npm run lint && npm run build && npm run doc",
|
|
26
26
|
"doc": "ts2md"
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@bsv/auth-express-middleware": "^1.0.1",
|
|
34
34
|
"@bsv/payment-express-middleware": "^1.0.1",
|
|
35
|
-
"@bsv/sdk": "^1.3.
|
|
35
|
+
"@bsv/sdk": "^1.3.18",
|
|
36
36
|
"axios": "^0.29.0",
|
|
37
37
|
"express": "^4.21.2",
|
|
38
38
|
"knex": "^3.1.0",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
39
|
+
"sqlite3": "^5.1.7",
|
|
40
|
+
"mysql2": "^3.12.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/diff": "^6.0.0",
|
|
@@ -53,8 +53,6 @@
|
|
|
53
53
|
"jest-diff": "^29.7.0",
|
|
54
54
|
"jest-simple-summary": "^1.0.2",
|
|
55
55
|
"prettier": "^3.4.2",
|
|
56
|
-
"sqlite3": "^5.1.7",
|
|
57
|
-
"standard": "^17.1.0",
|
|
58
56
|
"ts-jest": "^29.0.5",
|
|
59
57
|
"ts-node": "^10.9.1",
|
|
60
58
|
"ts2md": "^0.2.8",
|
package/src/Setup.ts
CHANGED
package/src/SetupClient.ts
CHANGED
|
@@ -35,6 +35,20 @@ dotenv.config()
|
|
|
35
35
|
*
|
|
36
36
|
*/
|
|
37
37
|
export abstract class SetupClient {
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param chain
|
|
41
|
+
* @returns true if .env is not valid for chain
|
|
42
|
+
*/
|
|
43
|
+
static noEnv(chain: sdk.Chain): boolean {
|
|
44
|
+
try {
|
|
45
|
+
SetupClient.getEnv(chain)
|
|
46
|
+
return false
|
|
47
|
+
} catch {
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
38
52
|
/**
|
|
39
53
|
* Creates content for .env file with some private keys, identity keys, sample API keys, and sample MySQL connection string.
|
|
40
54
|
*
|
|
@@ -98,6 +112,10 @@ DEV_KEYS = '{
|
|
|
98
112
|
chain === 'main'
|
|
99
113
|
? process.env.MY_MAIN_IDENTITY2
|
|
100
114
|
: process.env.MY_TEST_IDENTITY2
|
|
115
|
+
const filePath =
|
|
116
|
+
chain === 'main'
|
|
117
|
+
? process.env.MY_MAIN_FILEPATH
|
|
118
|
+
: process.env.MY_TEST_FILEPATH
|
|
101
119
|
const DEV_KEYS = process.env.DEV_KEYS || '{}'
|
|
102
120
|
const mySQLConnection = process.env.MYSQL_CONNECTION || '{}'
|
|
103
121
|
const taalApiKey = verifyTruthy(
|
|
@@ -116,6 +134,7 @@ DEV_KEYS = '{
|
|
|
116
134
|
chain,
|
|
117
135
|
identityKey,
|
|
118
136
|
identityKey2,
|
|
137
|
+
filePath,
|
|
119
138
|
taalApiKey,
|
|
120
139
|
devKeys: JSON.parse(DEV_KEYS) as Record<string, string>,
|
|
121
140
|
mySQLConnection
|
|
@@ -185,14 +204,11 @@ DEV_KEYS = '{
|
|
|
185
204
|
args: SetupWalletClientArgs
|
|
186
205
|
): Promise<SetupWalletClient> {
|
|
187
206
|
const wo = await SetupClient.createWallet(args)
|
|
188
|
-
if (wo.chain === 'main')
|
|
189
|
-
throw new sdk.WERR_INVALID_PARAMETER(
|
|
190
|
-
'chain',
|
|
191
|
-
`'test' for now, 'main' is not yet supported.`
|
|
192
|
-
)
|
|
193
207
|
|
|
194
208
|
const endpointUrl =
|
|
195
|
-
args.endpointUrl ||
|
|
209
|
+
args.endpointUrl ||
|
|
210
|
+
`https://${args.env.chain !== 'main' ? 'staging-' : ''}storage.babbage.systems`
|
|
211
|
+
|
|
196
212
|
const client = new StorageClient(wo.wallet, endpointUrl)
|
|
197
213
|
await wo.storage.addWalletStorageProvider(client)
|
|
198
214
|
await wo.storage.makeAvailable()
|
|
@@ -350,6 +366,10 @@ export interface SetupEnv {
|
|
|
350
366
|
* A secondary identity key (public key), used to test exchanges with other users.
|
|
351
367
|
*/
|
|
352
368
|
identityKey2: string
|
|
369
|
+
/**
|
|
370
|
+
* Filepath to sqlite file to be used for identityKey wallet.
|
|
371
|
+
*/
|
|
372
|
+
filePath: string | undefined
|
|
353
373
|
/**
|
|
354
374
|
* A vaild TAAL API key for use by `Services`
|
|
355
375
|
*/
|
package/src/Wallet.ts
CHANGED
|
@@ -69,14 +69,16 @@ import {
|
|
|
69
69
|
toWalletNetwork,
|
|
70
70
|
Monitor,
|
|
71
71
|
WalletStorageManager,
|
|
72
|
-
WalletSigner
|
|
72
|
+
WalletSigner,
|
|
73
|
+
randomBytesBase64,
|
|
74
|
+
ScriptTemplateBRC29
|
|
73
75
|
} from './index.client'
|
|
74
76
|
import { acquireDirectCertificate } from './signer/methods/acquireDirectCertificate'
|
|
75
77
|
import { proveCertificate } from './signer/methods/proveCertificate'
|
|
76
78
|
import { createAction } from './signer/methods/createAction'
|
|
77
79
|
import { signAction } from './signer/methods/signAction'
|
|
78
80
|
import { internalizeAction } from './signer/methods/internalizeAction'
|
|
79
|
-
import {
|
|
81
|
+
import { maxPossibleSatoshis } from './storage/methods/generateChange'
|
|
80
82
|
|
|
81
83
|
export interface WalletArgs {
|
|
82
84
|
chain: sdk.Chain
|
|
@@ -769,6 +771,68 @@ export class Wallet implements WalletInterface, ProtoWallet {
|
|
|
769
771
|
sdk.validateOriginator(originator)
|
|
770
772
|
return { version: 'wallet-brc100-1.0.0' }
|
|
771
773
|
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Transfer all possible satoshis held by this wallet to `toWallet`.
|
|
777
|
+
*
|
|
778
|
+
* @param toWallet wallet which will receive this wallet's satoshis.
|
|
779
|
+
*/
|
|
780
|
+
async sweepTo(toWallet: Wallet): Promise<void> {
|
|
781
|
+
const derivationPrefix = randomBytesBase64(8)
|
|
782
|
+
const derivationSuffix = randomBytesBase64(8)
|
|
783
|
+
const keyDeriver = this.keyDeriver
|
|
784
|
+
|
|
785
|
+
const t = new ScriptTemplateBRC29({
|
|
786
|
+
derivationPrefix,
|
|
787
|
+
derivationSuffix,
|
|
788
|
+
keyDeriver
|
|
789
|
+
})
|
|
790
|
+
|
|
791
|
+
const label = 'sweep'
|
|
792
|
+
|
|
793
|
+
const satoshis = maxPossibleSatoshis
|
|
794
|
+
|
|
795
|
+
const car = await this.createAction({
|
|
796
|
+
outputs: [
|
|
797
|
+
{
|
|
798
|
+
lockingScript: t
|
|
799
|
+
.lock(keyDeriver.rootKey.toString(), toWallet.identityKey)
|
|
800
|
+
.toHex(),
|
|
801
|
+
satoshis,
|
|
802
|
+
outputDescription: label,
|
|
803
|
+
tags: ['relinquish'],
|
|
804
|
+
customInstructions: JSON.stringify({
|
|
805
|
+
derivationPrefix,
|
|
806
|
+
derivationSuffix,
|
|
807
|
+
type: 'BRC29'
|
|
808
|
+
})
|
|
809
|
+
}
|
|
810
|
+
],
|
|
811
|
+
options: {
|
|
812
|
+
randomizeOutputs: false,
|
|
813
|
+
acceptDelayedBroadcast: false
|
|
814
|
+
},
|
|
815
|
+
labels: [label],
|
|
816
|
+
description: label
|
|
817
|
+
})
|
|
818
|
+
|
|
819
|
+
const iar = await toWallet.internalizeAction({
|
|
820
|
+
tx: car.tx!,
|
|
821
|
+
outputs: [
|
|
822
|
+
{
|
|
823
|
+
outputIndex: 0,
|
|
824
|
+
protocol: 'wallet payment',
|
|
825
|
+
paymentRemittance: {
|
|
826
|
+
derivationPrefix,
|
|
827
|
+
derivationSuffix,
|
|
828
|
+
senderIdentityKey: this.identityKey
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
],
|
|
832
|
+
description: label,
|
|
833
|
+
labels: [label]
|
|
834
|
+
})
|
|
835
|
+
}
|
|
772
836
|
}
|
|
773
837
|
|
|
774
838
|
export interface PendingStorageInput {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ArcConfig,
|
|
2
3
|
Beef,
|
|
3
4
|
Transaction as BsvTransaction,
|
|
4
5
|
ChainTracker,
|
|
@@ -90,15 +91,6 @@ export interface WalletServices {
|
|
|
90
91
|
*/
|
|
91
92
|
getMerklePath(txid: string, useNext?: boolean): Promise<GetMerklePathResult>
|
|
92
93
|
|
|
93
|
-
/**
|
|
94
|
-
*
|
|
95
|
-
* @param beef
|
|
96
|
-
* @param txids
|
|
97
|
-
* @param chain
|
|
98
|
-
* @returns
|
|
99
|
-
*/
|
|
100
|
-
postTxs(beef: Beef, txids: string[]): Promise<PostTxsResult[]>
|
|
101
|
-
|
|
102
94
|
/**
|
|
103
95
|
*
|
|
104
96
|
* @param beef
|
|
@@ -168,6 +160,8 @@ export interface WalletServicesOptions {
|
|
|
168
160
|
exchangeratesapiKey?: string
|
|
169
161
|
chaintracksFiatExchangeRatesUrl?: string
|
|
170
162
|
chaintracks?: ChaintracksServiceClient
|
|
163
|
+
arcUrl: string
|
|
164
|
+
arcConfig: ArcConfig
|
|
171
165
|
}
|
|
172
166
|
|
|
173
167
|
/**
|
|
@@ -230,11 +224,25 @@ export interface PostTxResultForTxid {
|
|
|
230
224
|
*/
|
|
231
225
|
alreadyKnown?: boolean
|
|
232
226
|
|
|
227
|
+
/**
|
|
228
|
+
* service indicated this broadcast double spends at least one input
|
|
229
|
+
* `competingTxs` may be an array of txids that were first seen spends of at least one input.
|
|
230
|
+
*/
|
|
231
|
+
doubleSpend?: boolean
|
|
232
|
+
|
|
233
233
|
blockHash?: string
|
|
234
234
|
blockHeight?: number
|
|
235
235
|
merklePath?: MerklePath
|
|
236
236
|
|
|
237
|
-
|
|
237
|
+
competingTxs?: string[]
|
|
238
|
+
|
|
239
|
+
data?: object | string | PostTxResultForTxidError
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface PostTxResultForTxidError {
|
|
243
|
+
status?: string
|
|
244
|
+
detail?: string
|
|
245
|
+
more?: object
|
|
238
246
|
}
|
|
239
247
|
|
|
240
248
|
export interface PostBeefResult extends PostTxsResult {}
|
|
@@ -366,13 +374,11 @@ export interface BlockHeader extends BaseBlockHeader {
|
|
|
366
374
|
|
|
367
375
|
export type GetUtxoStatusService = (
|
|
368
376
|
output: string,
|
|
369
|
-
chain: sdk.Chain,
|
|
370
377
|
outputFormat?: GetUtxoStatusOutputFormat
|
|
371
378
|
) => Promise<GetUtxoStatusResult>
|
|
372
379
|
|
|
373
380
|
export type GetMerklePathService = (
|
|
374
381
|
txid: string,
|
|
375
|
-
chain: sdk.Chain,
|
|
376
382
|
services: WalletServices
|
|
377
383
|
) => Promise<GetMerklePathResult>
|
|
378
384
|
|
|
@@ -389,8 +395,7 @@ export type PostTxsService = (
|
|
|
389
395
|
|
|
390
396
|
export type PostBeefService = (
|
|
391
397
|
beef: Beef,
|
|
392
|
-
txids: string[]
|
|
393
|
-
services: WalletServices
|
|
398
|
+
txids: string[]
|
|
394
399
|
) => Promise<PostBeefResult>
|
|
395
400
|
|
|
396
401
|
export type UpdateFiatExchangeRateService = (
|
package/src/services/Services.ts
CHANGED
|
@@ -13,24 +13,14 @@ import {
|
|
|
13
13
|
wait
|
|
14
14
|
} from '../index.client'
|
|
15
15
|
import { ServiceCollection } from './ServiceCollection'
|
|
16
|
-
|
|
17
16
|
import { createDefaultWalletServicesOptions } from './createDefaultWalletServicesOptions'
|
|
18
17
|
import { ChaintracksChainTracker } from './chaintracker'
|
|
19
|
-
import {
|
|
20
|
-
getTaalArcServiceConfig,
|
|
21
|
-
makePostBeefToTaalARC,
|
|
22
|
-
makePostTxsToTaalARC
|
|
23
|
-
} from './providers/arcServices'
|
|
24
|
-
import {
|
|
25
|
-
getMerklePathFromWhatsOnChainTsc,
|
|
26
|
-
getRawTxFromWhatsOnChain,
|
|
27
|
-
getUtxoStatusFromWhatsOnChain,
|
|
28
|
-
updateBsvExchangeRate
|
|
29
|
-
} from './providers/whatsonchain'
|
|
18
|
+
import { WhatsOnChain } from './providers/WhatsOnChain'
|
|
30
19
|
import {
|
|
31
20
|
updateChaintracksFiatExchangeRates,
|
|
32
21
|
updateExchangeratesapi
|
|
33
22
|
} from './providers/echangeRates'
|
|
23
|
+
import ARC from './providers/ARC'
|
|
34
24
|
|
|
35
25
|
export class Services implements sdk.WalletServices {
|
|
36
26
|
static createDefaultOptions(chain: sdk.Chain): sdk.WalletServicesOptions {
|
|
@@ -38,10 +28,11 @@ export class Services implements sdk.WalletServices {
|
|
|
38
28
|
}
|
|
39
29
|
|
|
40
30
|
options: sdk.WalletServicesOptions
|
|
31
|
+
whatsonchain: WhatsOnChain
|
|
32
|
+
arc: ARC
|
|
41
33
|
|
|
42
34
|
getMerklePathServices: ServiceCollection<sdk.GetMerklePathService>
|
|
43
35
|
getRawTxServices: ServiceCollection<sdk.GetRawTxService>
|
|
44
|
-
postTxsServices: ServiceCollection<sdk.PostTxsService>
|
|
45
36
|
postBeefServices: ServiceCollection<sdk.PostBeefService>
|
|
46
37
|
getUtxoStatusServices: ServiceCollection<sdk.GetUtxoStatusService>
|
|
47
38
|
updateFiatExchangeRateServices: ServiceCollection<sdk.UpdateFiatExchangeRateService>
|
|
@@ -57,36 +48,32 @@ export class Services implements sdk.WalletServices {
|
|
|
57
48
|
? Services.createDefaultOptions(this.chain)
|
|
58
49
|
: optionsOrChain
|
|
59
50
|
|
|
51
|
+
this.whatsonchain = new WhatsOnChain(this.chain, {
|
|
52
|
+
apiKey: this.options.taalApiKey
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
this.arc = new ARC(this.options.arcUrl, this.options.arcConfig)
|
|
56
|
+
|
|
60
57
|
this.getMerklePathServices =
|
|
61
58
|
new ServiceCollection<sdk.GetMerklePathService>().add({
|
|
62
|
-
name: '
|
|
63
|
-
service:
|
|
59
|
+
name: 'WhatsOnChain',
|
|
60
|
+
service: this.whatsonchain.getMerklePath.bind(this.whatsonchain)
|
|
64
61
|
})
|
|
65
|
-
//.add({ name: 'Taal', service: makeGetMerklePathFromTaalARC(getTaalArcServiceConfig(this.chain, this.options.taalApiKey!)) })
|
|
66
62
|
|
|
67
63
|
this.getRawTxServices = new ServiceCollection<sdk.GetRawTxService>().add({
|
|
68
64
|
name: 'WhatsOnChain',
|
|
69
|
-
service:
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
this.postTxsServices = new ServiceCollection<sdk.PostTxsService>().add({
|
|
73
|
-
name: 'TaalArcTxs',
|
|
74
|
-
service: makePostTxsToTaalARC(
|
|
75
|
-
getTaalArcServiceConfig(this.chain, this.options.taalApiKey!)
|
|
76
|
-
)
|
|
65
|
+
service: this.whatsonchain.getRawTxResult.bind(this.whatsonchain)
|
|
77
66
|
})
|
|
78
67
|
|
|
79
68
|
this.postBeefServices = new ServiceCollection<sdk.PostBeefService>().add({
|
|
80
69
|
name: 'TaalArcBeef',
|
|
81
|
-
service:
|
|
82
|
-
getTaalArcServiceConfig(this.chain, this.options.taalApiKey!)
|
|
83
|
-
)
|
|
70
|
+
service: this.arc.postBeef.bind(this.arc)
|
|
84
71
|
})
|
|
85
72
|
|
|
86
73
|
this.getUtxoStatusServices =
|
|
87
74
|
new ServiceCollection<sdk.GetUtxoStatusService>().add({
|
|
88
75
|
name: 'WhatsOnChain',
|
|
89
|
-
service:
|
|
76
|
+
service: this.whatsonchain.getUtxoStatus.bind(this.whatsonchain)
|
|
90
77
|
})
|
|
91
78
|
|
|
92
79
|
this.updateFiatExchangeRateServices =
|
|
@@ -108,10 +95,11 @@ export class Services implements sdk.WalletServices {
|
|
|
108
95
|
}
|
|
109
96
|
|
|
110
97
|
async getBsvExchangeRate(): Promise<number> {
|
|
111
|
-
this.options.bsvExchangeRate =
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
|
|
98
|
+
this.options.bsvExchangeRate =
|
|
99
|
+
await this.whatsonchain.updateBsvExchangeRate(
|
|
100
|
+
this.options.bsvExchangeRate,
|
|
101
|
+
this.options.bsvUpdateMsecs
|
|
102
|
+
)
|
|
115
103
|
return this.options.bsvExchangeRate.rate
|
|
116
104
|
}
|
|
117
105
|
|
|
@@ -138,9 +126,6 @@ export class Services implements sdk.WalletServices {
|
|
|
138
126
|
get getRawTxsCount() {
|
|
139
127
|
return this.getRawTxServices.count
|
|
140
128
|
}
|
|
141
|
-
get postTxsServicesCount() {
|
|
142
|
-
return this.postTxsServices.count
|
|
143
|
-
}
|
|
144
129
|
get postBeefServicesCount() {
|
|
145
130
|
return this.postBeefServices.count
|
|
146
131
|
}
|
|
@@ -166,7 +151,7 @@ export class Services implements sdk.WalletServices {
|
|
|
166
151
|
for (let retry = 0; retry < 2; retry++) {
|
|
167
152
|
for (let tries = 0; tries < services.count; tries++) {
|
|
168
153
|
const service = services.service
|
|
169
|
-
const r = await service(output,
|
|
154
|
+
const r = await service(output, outputFormat)
|
|
170
155
|
if (r.status === 'success') {
|
|
171
156
|
r0 = r
|
|
172
157
|
break
|
|
@@ -179,25 +164,6 @@ export class Services implements sdk.WalletServices {
|
|
|
179
164
|
return r0
|
|
180
165
|
}
|
|
181
166
|
|
|
182
|
-
/**
|
|
183
|
-
* The beef must contain at least each rawTx for each txid.
|
|
184
|
-
* Some services may require input transactions as well.
|
|
185
|
-
* These will be fetched if missing, greatly extending the service response time.
|
|
186
|
-
* @param beef
|
|
187
|
-
* @param txids
|
|
188
|
-
* @returns
|
|
189
|
-
*/
|
|
190
|
-
async postTxs(beef: Beef, txids: string[]): Promise<sdk.PostTxsResult[]> {
|
|
191
|
-
const rs = await Promise.all(
|
|
192
|
-
this.postTxsServices.allServices.map(async service => {
|
|
193
|
-
const r = await service(beef, txids, this)
|
|
194
|
-
return r
|
|
195
|
-
})
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
return rs
|
|
199
|
-
}
|
|
200
|
-
|
|
201
167
|
/**
|
|
202
168
|
*
|
|
203
169
|
* @param beef
|
|
@@ -207,15 +173,10 @@ export class Services implements sdk.WalletServices {
|
|
|
207
173
|
async postBeef(beef: Beef, txids: string[]): Promise<sdk.PostBeefResult[]> {
|
|
208
174
|
let rs = await Promise.all(
|
|
209
175
|
this.postBeefServices.allServices.map(async service => {
|
|
210
|
-
const r = await service(beef, txids
|
|
176
|
+
const r = await service(beef, txids)
|
|
211
177
|
return r
|
|
212
178
|
})
|
|
213
179
|
)
|
|
214
|
-
|
|
215
|
-
if (rs.every(r => r.status !== 'success')) {
|
|
216
|
-
rs = await this.postTxs(beef, txids)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
180
|
return rs
|
|
220
181
|
}
|
|
221
182
|
|
|
@@ -313,7 +274,7 @@ export class Services implements sdk.WalletServices {
|
|
|
313
274
|
|
|
314
275
|
for (let tries = 0; tries < this.getMerklePathServices.count; tries++) {
|
|
315
276
|
const service = this.getMerklePathServices.service
|
|
316
|
-
const r = await service(txid, this
|
|
277
|
+
const r = await service(txid, this)
|
|
317
278
|
if (r.merklePath) {
|
|
318
279
|
// If we have a proof, call it done.
|
|
319
280
|
r0.merklePath = r.merklePath
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { _tu } from '../../../test/utils/TestUtilsWalletStorage'
|
|
2
|
+
import { sdk, wait } from '../../index.client'
|
|
3
|
+
import ARC from '../providers/ARC'
|
|
4
|
+
import { BeefTx } from '@bsv/sdk'
|
|
5
|
+
import { arcDefaultUrl } from '../createDefaultWalletServicesOptions'
|
|
6
|
+
import { Setup } from '../../index.all'
|
|
7
|
+
|
|
8
|
+
describe('ARC tests', () => {
|
|
9
|
+
jest.setTimeout(99999999)
|
|
10
|
+
|
|
11
|
+
const envTest = _tu.getEnv('test')
|
|
12
|
+
const arcTest = new ARC(arcDefaultUrl(envTest.chain), {
|
|
13
|
+
apiKey: envTest.taalApiKey
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const envMain = _tu.getEnv('main')
|
|
17
|
+
const arcMain = new ARC(arcDefaultUrl(envMain.chain), {
|
|
18
|
+
apiKey: envMain.taalApiKey
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test.skip('7 postRawTx testnet', async () => {
|
|
22
|
+
await postRawTxTest('test', arcTest)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test.skip('8 postRawTx mainnet', async () => {
|
|
26
|
+
await postRawTxTest('main', arcMain)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test.skip('9 postBeef testnet', async () => {
|
|
30
|
+
const r = await postBeefTest('test', arcTest)
|
|
31
|
+
console.log(`9 postBeef testnet done ${r}`)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test.skip('10 postBeef mainnet', async () => {
|
|
35
|
+
const r = await postBeefTest('main', arcMain)
|
|
36
|
+
console.log(`10 postBeef mainnet done ${r}`)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
async function postBeefTest(chain: sdk.Chain, arc: ARC): Promise<string> {
|
|
41
|
+
if (Setup.noEnv(chain)) return 'skipped'
|
|
42
|
+
const c = await _tu.createNoSendTxPair(chain)
|
|
43
|
+
|
|
44
|
+
const txids = [c.txidDo, c.txidUndo]
|
|
45
|
+
|
|
46
|
+
const r = await arc.postBeef(c.beef, txids)
|
|
47
|
+
expect(r.status).toBe('success')
|
|
48
|
+
for (const txid of txids) {
|
|
49
|
+
const tr = r.txidResults.find(tx => tx.txid === txid)
|
|
50
|
+
expect(tr).not.toBeUndefined()
|
|
51
|
+
expect(tr!.status).toBe('success')
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// replace Undo transaction with double spend transaction and send again.
|
|
55
|
+
const beef2 = c.beef.clone()
|
|
56
|
+
beef2.txs[beef2.txs.length - 1] = BeefTx.fromTx(c.doubleSpendTx)
|
|
57
|
+
const txids2 = [c.txidDo, c.doubleSpendTx.id('hex')]
|
|
58
|
+
|
|
59
|
+
const r2 = await arc.postBeef(beef2, txids2)
|
|
60
|
+
expect(r2.status).toBe('error')
|
|
61
|
+
for (const txid of txids2) {
|
|
62
|
+
const tr = r2.txidResults.find(tx => tx.txid === txid)
|
|
63
|
+
expect(tr).not.toBeUndefined()
|
|
64
|
+
if (txid === c.txidDo) {
|
|
65
|
+
expect(tr!.status).toBe('success')
|
|
66
|
+
} else {
|
|
67
|
+
expect(tr!.status).toBe('error')
|
|
68
|
+
expect(tr!.doubleSpend).toBe(true)
|
|
69
|
+
expect(tr!.competingTxs).toEqual([c.txidUndo])
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return 'passed'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function postRawTxTest(chain: sdk.Chain, arc: ARC): Promise<void> {
|
|
76
|
+
if (Setup.noEnv(chain)) return
|
|
77
|
+
const c = await _tu.createNoSendTxPair(chain)
|
|
78
|
+
|
|
79
|
+
const rawTxDo = c.beef.findTxid(c.txidDo)!.tx!.toHex()
|
|
80
|
+
const rawTxUndo = c.beef.findTxid(c.txidUndo)!.tx!.toHex()
|
|
81
|
+
|
|
82
|
+
const rDo = await arc.postRawTx(rawTxDo)
|
|
83
|
+
expect(rDo.status).toBe('success')
|
|
84
|
+
expect(rDo.txid).toBe(c.txidDo)
|
|
85
|
+
|
|
86
|
+
await wait(1000)
|
|
87
|
+
|
|
88
|
+
const rUndo = await arc.postRawTx(rawTxUndo)
|
|
89
|
+
expect(rUndo.status).toBe('success')
|
|
90
|
+
expect(rUndo.txid).toBe(c.txidUndo)
|
|
91
|
+
expect(rUndo.doubleSpend).not.toBe(true)
|
|
92
|
+
|
|
93
|
+
await wait(1000)
|
|
94
|
+
|
|
95
|
+
{
|
|
96
|
+
// Send same transaction again...
|
|
97
|
+
const rUndo = await arc.postRawTx(rawTxUndo)
|
|
98
|
+
expect(rUndo.status).toBe('success')
|
|
99
|
+
expect(rUndo.txid).toBe(c.txidUndo)
|
|
100
|
+
expect(rUndo.doubleSpend).not.toBe(true)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
await wait(1000)
|
|
104
|
+
|
|
105
|
+
// Confirm double spend detection.
|
|
106
|
+
const rDouble = await arc.postRawTx(c.doubleSpendTx.toHex())
|
|
107
|
+
expect(rDouble.status).toBe('error')
|
|
108
|
+
expect(rDouble.doubleSpend).toBe(true)
|
|
109
|
+
expect(rDouble.competingTxs![0]).toBe(c.txidUndo)
|
|
110
|
+
}
|
|
@@ -1,19 +1,57 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BeefTx } from '@bsv/sdk'
|
|
2
2
|
import { Services } from '../../index.client'
|
|
3
|
+
import { _tu } from '../../../test/utils/TestUtilsWalletStorage'
|
|
4
|
+
import { Setup } from '../../index.all'
|
|
3
5
|
|
|
4
6
|
describe('postBeef service tests', () => {
|
|
5
7
|
jest.setTimeout(99999999)
|
|
6
8
|
|
|
7
|
-
test('0', async () => {
|
|
9
|
+
test('0 postBeef mainnet', async () => {
|
|
10
|
+
if (Setup.noEnv('main')) return
|
|
8
11
|
const options = Services.createDefaultOptions('main')
|
|
9
12
|
const services = new Services(options)
|
|
13
|
+
await postBeefTest(services)
|
|
14
|
+
})
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const r = await services.postTxs(beef, [txid])
|
|
17
|
-
expect(r).toBeTruthy()
|
|
16
|
+
test('1 postBeef testnet', async () => {
|
|
17
|
+
if (Setup.noEnv('test')) return
|
|
18
|
+
const options = Services.createDefaultOptions('test')
|
|
19
|
+
const services = new Services(options)
|
|
20
|
+
await postBeefTest(services)
|
|
18
21
|
})
|
|
19
22
|
})
|
|
23
|
+
|
|
24
|
+
async function postBeefTest(services: Services) {
|
|
25
|
+
const chain = services.chain
|
|
26
|
+
if (Setup.noEnv(chain)) return
|
|
27
|
+
const c = await _tu.createNoSendTxPair(chain)
|
|
28
|
+
|
|
29
|
+
const txids = [c.txidDo, c.txidUndo]
|
|
30
|
+
|
|
31
|
+
const [r] = await services.postBeef(c.beef, txids)
|
|
32
|
+
expect(r.status).toBe('success')
|
|
33
|
+
for (const txid of txids) {
|
|
34
|
+
const tr = r.txidResults.find(tx => tx.txid === txid)
|
|
35
|
+
expect(tr).not.toBeUndefined()
|
|
36
|
+
expect(tr!.status).toBe('success')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// replace Undo transaction with double spend transaction and send again.
|
|
40
|
+
const beef2 = c.beef.clone()
|
|
41
|
+
beef2.txs[beef2.txs.length - 1] = BeefTx.fromTx(c.doubleSpendTx)
|
|
42
|
+
const txids2 = [c.txidDo, c.doubleSpendTx.id('hex')]
|
|
43
|
+
|
|
44
|
+
const [r2] = await services.postBeef(beef2, txids2)
|
|
45
|
+
expect(r2.status).toBe('error')
|
|
46
|
+
for (const txid of txids2) {
|
|
47
|
+
const tr = r2.txidResults.find(tx => tx.txid === txid)
|
|
48
|
+
expect(tr).not.toBeUndefined()
|
|
49
|
+
if (txid === c.txidDo) {
|
|
50
|
+
expect(tr!.status).toBe('success')
|
|
51
|
+
} else {
|
|
52
|
+
expect(tr!.status).toBe('error')
|
|
53
|
+
expect(tr!.doubleSpend).toBe(true)
|
|
54
|
+
expect(tr!.competingTxs).toEqual([c.txidUndo])
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { sdk } from '../index.client'
|
|
1
|
+
import { randomBytesHex, sdk } from '../index.client'
|
|
2
2
|
import { ChaintracksServiceClient } from './chaintracker'
|
|
3
3
|
|
|
4
4
|
export function createDefaultWalletServicesOptions(
|
|
5
5
|
chain: sdk.Chain
|
|
6
6
|
): sdk.WalletServicesOptions {
|
|
7
|
+
const taalApiKey =
|
|
8
|
+
chain === 'main'
|
|
9
|
+
? 'mainnet_9596de07e92300c6287e4393594ae39c' // no plan
|
|
10
|
+
: 'testnet_0e6cf72133b43ea2d7861da2a38684e3' // personal "starter" key
|
|
11
|
+
|
|
7
12
|
const o: sdk.WalletServicesOptions = {
|
|
8
13
|
chain,
|
|
9
|
-
taalApiKey
|
|
10
|
-
chain === 'main'
|
|
11
|
-
? 'mainnet_9596de07e92300c6287e4393594ae39c' // Tone's key, no plan
|
|
12
|
-
: 'testnet_0e6cf72133b43ea2d7861da2a38684e3', // Tone's personal "starter" key
|
|
14
|
+
taalApiKey,
|
|
13
15
|
bsvExchangeRate: {
|
|
14
16
|
timestamp: new Date('2023-12-13'),
|
|
15
17
|
base: 'USD',
|
|
@@ -32,7 +34,18 @@ export function createDefaultWalletServicesOptions(
|
|
|
32
34
|
chaintracks: new ChaintracksServiceClient(
|
|
33
35
|
chain,
|
|
34
36
|
`https://npm-registry.babbage.systems:${chain === 'main' ? 8084 : 8083}`
|
|
35
|
-
)
|
|
37
|
+
),
|
|
38
|
+
arcUrl: arcDefaultUrl(chain),
|
|
39
|
+
arcConfig: {
|
|
40
|
+
apiKey: taalApiKey,
|
|
41
|
+
deploymentId: `wallet-toolbox-${randomBytesHex(16)}`
|
|
42
|
+
}
|
|
36
43
|
}
|
|
37
44
|
return o
|
|
38
45
|
}
|
|
46
|
+
|
|
47
|
+
export function arcDefaultUrl(chain: sdk.Chain): string {
|
|
48
|
+
const url =
|
|
49
|
+
chain === 'main' ? 'https://api.taal.com/arc' : 'https://arc-test.taal.com'
|
|
50
|
+
return url
|
|
51
|
+
}
|