@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.
Files changed (132) hide show
  1. package/docs/README.md +8 -2
  2. package/docs/client.md +453 -346
  3. package/docs/open-rpc/index.html +46 -0
  4. package/docs/services.md +236 -211
  5. package/docs/setup.md +20 -4
  6. package/docs/storage.md +30 -5
  7. package/docs/wallet.md +453 -346
  8. package/out/src/Setup.d.ts.map +1 -1
  9. package/out/src/Setup.js.map +1 -1
  10. package/out/src/SetupClient.d.ts +9 -0
  11. package/out/src/SetupClient.d.ts.map +1 -1
  12. package/out/src/SetupClient.js +19 -3
  13. package/out/src/SetupClient.js.map +1 -1
  14. package/out/src/Wallet.d.ts +6 -0
  15. package/out/src/Wallet.d.ts.map +1 -1
  16. package/out/src/Wallet.js +57 -0
  17. package/out/src/Wallet.js.map +1 -1
  18. package/out/src/sdk/WalletServices.interfaces.d.ts +18 -13
  19. package/out/src/sdk/WalletServices.interfaces.d.ts.map +1 -1
  20. package/out/src/services/Services.d.ts +4 -11
  21. package/out/src/services/Services.d.ts.map +1 -1
  22. package/out/src/services/Services.js +19 -37
  23. package/out/src/services/Services.js.map +1 -1
  24. package/out/src/services/__tests/ARC.test.d.ts +2 -0
  25. package/out/src/services/__tests/ARC.test.d.ts.map +1 -0
  26. package/out/src/services/__tests/ARC.test.js +98 -0
  27. package/out/src/services/__tests/ARC.test.js.map +1 -0
  28. package/out/src/services/__tests/arcServices.test.d.ts +2 -0
  29. package/out/src/services/__tests/arcServices.test.d.ts.map +1 -0
  30. package/out/src/services/__tests/arcServices.test.js +7 -0
  31. package/out/src/services/__tests/arcServices.test.js.map +1 -0
  32. package/out/src/services/__tests/postBeef.test.js +45 -7
  33. package/out/src/services/__tests/postBeef.test.js.map +1 -1
  34. package/out/src/services/createDefaultWalletServicesOptions.d.ts +1 -0
  35. package/out/src/services/createDefaultWalletServicesOptions.d.ts.map +1 -1
  36. package/out/src/services/createDefaultWalletServicesOptions.js +16 -4
  37. package/out/src/services/createDefaultWalletServicesOptions.js.map +1 -1
  38. package/out/src/services/providers/ARC.d.ts +91 -0
  39. package/out/src/services/providers/ARC.d.ts.map +1 -0
  40. package/out/src/services/providers/ARC.js +192 -0
  41. package/out/src/services/providers/ARC.js.map +1 -0
  42. package/out/src/services/providers/SdkWhatsOnChain.d.ts +21 -0
  43. package/out/src/services/providers/SdkWhatsOnChain.d.ts.map +1 -0
  44. package/out/src/services/providers/SdkWhatsOnChain.js +67 -0
  45. package/out/src/services/providers/SdkWhatsOnChain.js.map +1 -0
  46. package/out/src/services/providers/WhatsOnChain.d.ts +35 -0
  47. package/out/src/services/providers/WhatsOnChain.d.ts.map +1 -0
  48. package/out/src/services/providers/WhatsOnChain.js +266 -0
  49. package/out/src/services/providers/WhatsOnChain.js.map +1 -0
  50. package/out/src/services/providers/__tests/WhatsOnChain.test.d.ts +2 -0
  51. package/out/src/services/providers/__tests/WhatsOnChain.test.d.ts.map +1 -0
  52. package/out/src/services/providers/__tests/WhatsOnChain.test.js +176 -0
  53. package/out/src/services/providers/__tests/WhatsOnChain.test.js.map +1 -0
  54. package/out/src/storage/methods/createAction.d.ts.map +1 -1
  55. package/out/src/storage/methods/createAction.js +9 -2
  56. package/out/src/storage/methods/createAction.js.map +1 -1
  57. package/out/src/storage/methods/generateChange.d.ts +12 -1
  58. package/out/src/storage/methods/generateChange.d.ts.map +1 -1
  59. package/out/src/storage/methods/generateChange.js +24 -1
  60. package/out/src/storage/methods/generateChange.js.map +1 -1
  61. package/out/src/storage/methods/processAction.d.ts.map +1 -1
  62. package/out/src/storage/methods/processAction.js +1 -1
  63. package/out/src/storage/methods/processAction.js.map +1 -1
  64. package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js +0 -1
  65. package/out/src/storage/schema/entities/__tests/ProvenTxTests.test.js.map +1 -1
  66. package/out/src/storage/sync/StorageMySQLDojoReader.js +1 -1
  67. package/out/src/storage/sync/StorageMySQLDojoReader.js.map +1 -1
  68. package/out/src/utility/utilityHelpers.js +1 -1
  69. package/out/src/utility/utilityHelpers.js.map +1 -1
  70. package/out/test/Wallet/StorageClient/storageClient.man.test.js +22 -3
  71. package/out/test/Wallet/StorageClient/storageClient.man.test.js.map +1 -1
  72. package/out/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.js +40 -0
  73. package/out/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.js.map +1 -1
  74. package/out/test/services/Services.test.js +0 -31
  75. package/out/test/services/Services.test.js.map +1 -1
  76. package/out/test/utils/TestUtilsWalletStorage.d.ts +26 -18
  77. package/out/test/utils/TestUtilsWalletStorage.d.ts.map +1 -1
  78. package/out/test/utils/TestUtilsWalletStorage.js +135 -27
  79. package/out/test/utils/TestUtilsWalletStorage.js.map +1 -1
  80. package/out/test/wallet/list/listActions2.test.js +36 -2
  81. package/out/test/wallet/list/listActions2.test.js.map +1 -1
  82. package/out/tsconfig.all.tsbuildinfo +1 -1
  83. package/package.json +5 -7
  84. package/src/Setup.ts +0 -1
  85. package/src/SetupClient.ts +26 -6
  86. package/src/Wallet.ts +66 -2
  87. package/src/sdk/WalletServices.interfaces.ts +19 -14
  88. package/src/services/Services.ts +23 -62
  89. package/src/services/__tests/ARC.test.ts +110 -0
  90. package/src/services/__tests/arcServices.test.ts +8 -0
  91. package/src/services/__tests/postBeef.test.ts +47 -9
  92. package/src/services/createDefaultWalletServicesOptions.ts +19 -6
  93. package/src/services/providers/ARC.ts +289 -0
  94. package/src/services/providers/SdkWhatsOnChain.ts +96 -0
  95. package/src/services/providers/WhatsOnChain.ts +369 -0
  96. package/src/services/providers/__tests/WhatsOnChain.test.ts +227 -0
  97. package/src/storage/methods/createAction.ts +26 -4
  98. package/src/storage/methods/generateChange.ts +42 -2
  99. package/src/storage/methods/processAction.ts +2 -1
  100. package/src/storage/schema/entities/__tests/ProvenTxTests.test.ts +0 -1
  101. package/src/storage/sync/StorageMySQLDojoReader.ts +1 -1
  102. package/src/utility/utilityHelpers.ts +1 -1
  103. package/test/Wallet/StorageClient/storageClient.man.test.ts +30 -4
  104. package/test/Wallet/sync/Wallet.updateWalletLegacyTestData.man.test.ts +54 -0
  105. package/test/services/Services.test.ts +0 -30
  106. package/test/utils/TestUtilsWalletStorage.ts +175 -45
  107. package/test/wallet/list/listActions2.test.ts +4 -7
  108. package/out/src/services/__tests/postBeefToArcTaal.test.d.ts +0 -2
  109. package/out/src/services/__tests/postBeefToArcTaal.test.d.ts.map +0 -1
  110. package/out/src/services/__tests/postBeefToArcTaal.test.js +0 -479
  111. package/out/src/services/__tests/postBeefToArcTaal.test.js.map +0 -1
  112. package/out/src/services/__tests/postTxs.test.d.ts +0 -2
  113. package/out/src/services/__tests/postTxs.test.d.ts.map +0 -1
  114. package/out/src/services/__tests/postTxs.test.js +0 -28
  115. package/out/src/services/__tests/postTxs.test.js.map +0 -1
  116. package/out/src/services/providers/arcServices.d.ts +0 -62
  117. package/out/src/services/providers/arcServices.d.ts.map +0 -1
  118. package/out/src/services/providers/arcServices.js +0 -375
  119. package/out/src/services/providers/arcServices.js.map +0 -1
  120. package/out/src/services/providers/whatsonchain.d.ts +0 -17
  121. package/out/src/services/providers/whatsonchain.d.ts.map +0 -1
  122. package/out/src/services/providers/whatsonchain.js +0 -130
  123. package/out/src/services/providers/whatsonchain.js.map +0 -1
  124. package/out/test/examples/README.man.test.d.ts +0 -2
  125. package/out/test/examples/README.man.test.d.ts.map +0 -1
  126. package/out/test/examples/README.man.test.js +0 -47
  127. package/out/test/examples/README.man.test.js.map +0 -1
  128. package/src/services/__tests/postBeefToArcTaal.test.ts +0 -487
  129. package/src/services/__tests/postTxs.test.ts +0 -28
  130. package/src/services/providers/arcServices.ts +0 -578
  131. package/src/services/providers/whatsonchain.ts +0 -170
  132. 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.13",
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' --loglevel silent",
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.16",
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
- "mysql2": "^3.12.0",
40
- "whatsonchain": "^0.2.0"
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
@@ -21,7 +21,6 @@ import { SetupWallet, SetupWalletArgs, StorageKnex } from './index.all'
21
21
  *
22
22
  */
23
23
  export abstract class Setup extends SetupClient {
24
-
25
24
  /**
26
25
  * Adds `Knex` based storage to a `Wallet` configured by `Setup.createWalletOnly`
27
26
  *
@@ -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 || 'https://staging-dojo.babbage.systems'
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 { ValidAcquireDirectCertificateArgs } from './sdk'
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
- data?: object
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 = (
@@ -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: 'WhatsOnChainTsc',
63
- service: getMerklePathFromWhatsOnChainTsc
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: getRawTxFromWhatsOnChain
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: makePostBeefToTaalARC(
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: getUtxoStatusFromWhatsOnChain
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 = await updateBsvExchangeRate(
112
- this.options.bsvExchangeRate,
113
- this.options.bsvUpdateMsecs
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, this.chain, outputFormat)
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, this)
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.chain, 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
+ }
@@ -0,0 +1,8 @@
1
+ import { Beef } from '@bsv/sdk'
2
+ import { Services } from '../../index.all'
3
+
4
+ describe.skip('arcServices tests', () => {
5
+ jest.setTimeout(99999999)
6
+
7
+ test('0 ', async () => {})
8
+ })
@@ -1,19 +1,57 @@
1
- import { Beef } from '@bsv/sdk'
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
- const txid =
12
- '9cce99686bc8621db439b7150dd5b3b269e4b0628fd75160222c417d6f2b95e4'
13
- const rawTx = await services.getRawTx(txid)
14
- const beef = new Beef()
15
- beef.mergeRawTx(rawTx.rawTx!)
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
+ }