@bsv/sdk 1.0.32 → 1.0.34

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 (138) hide show
  1. package/README.md +1 -3
  2. package/dist/cjs/mod.js +1 -0
  3. package/dist/cjs/mod.js.map +1 -1
  4. package/dist/cjs/package.json +1 -1
  5. package/dist/cjs/src/primitives/PublicKey.js +36 -0
  6. package/dist/cjs/src/primitives/PublicKey.js.map +1 -1
  7. package/dist/cjs/src/primitives/Signature.js +6 -6
  8. package/dist/cjs/src/primitives/Signature.js.map +1 -1
  9. package/dist/cjs/src/script/Script.js.map +1 -1
  10. package/dist/cjs/src/transaction/MerklePath.js.map +1 -1
  11. package/dist/cjs/src/transaction/Transaction.js +5 -3
  12. package/dist/cjs/src/transaction/Transaction.js.map +1 -1
  13. package/dist/cjs/src/transaction/broadcasters/ARC.js +39 -57
  14. package/dist/cjs/src/transaction/broadcasters/ARC.js.map +1 -1
  15. package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js +12 -0
  16. package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -0
  17. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js +66 -0
  18. package/dist/cjs/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -0
  19. package/dist/cjs/src/transaction/broadcasters/index.js +5 -1
  20. package/dist/cjs/src/transaction/broadcasters/index.js.map +1 -1
  21. package/dist/cjs/src/transaction/chaintrackers/DefaultChainTracker.js +12 -0
  22. package/dist/cjs/src/transaction/chaintrackers/DefaultChainTracker.js.map +1 -0
  23. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js +49 -0
  24. package/dist/cjs/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -0
  25. package/dist/cjs/src/transaction/chaintrackers/index.js +11 -0
  26. package/dist/cjs/src/transaction/chaintrackers/index.js.map +1 -0
  27. package/dist/cjs/src/transaction/http/DefaultHttpClient.js +37 -0
  28. package/dist/cjs/src/transaction/http/DefaultHttpClient.js.map +1 -0
  29. package/dist/cjs/src/transaction/http/FetchHttpClient.js +29 -0
  30. package/dist/cjs/src/transaction/http/FetchHttpClient.js.map +1 -0
  31. package/dist/cjs/src/transaction/http/HttpClient.js +3 -0
  32. package/dist/cjs/src/transaction/http/HttpClient.js.map +1 -0
  33. package/dist/cjs/src/transaction/http/NodejsHttpClient.js +41 -0
  34. package/dist/cjs/src/transaction/http/NodejsHttpClient.js.map +1 -0
  35. package/dist/cjs/src/transaction/http/index.js +10 -0
  36. package/dist/cjs/src/transaction/http/index.js.map +1 -0
  37. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  38. package/dist/esm/mod.js +1 -0
  39. package/dist/esm/mod.js.map +1 -1
  40. package/dist/esm/src/primitives/PublicKey.js +36 -0
  41. package/dist/esm/src/primitives/PublicKey.js.map +1 -1
  42. package/dist/esm/src/primitives/Signature.js +6 -6
  43. package/dist/esm/src/primitives/Signature.js.map +1 -1
  44. package/dist/esm/src/script/Script.js.map +1 -1
  45. package/dist/esm/src/transaction/MerklePath.js.map +1 -1
  46. package/dist/esm/src/transaction/Transaction.js +5 -3
  47. package/dist/esm/src/transaction/Transaction.js.map +1 -1
  48. package/dist/esm/src/transaction/broadcasters/ARC.js +37 -57
  49. package/dist/esm/src/transaction/broadcasters/ARC.js.map +1 -1
  50. package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js +5 -0
  51. package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -0
  52. package/dist/esm/src/transaction/broadcasters/WhatsOnChainBroadcaster.js +65 -0
  53. package/dist/esm/src/transaction/broadcasters/WhatsOnChainBroadcaster.js.map +1 -0
  54. package/dist/esm/src/transaction/broadcasters/index.js +2 -0
  55. package/dist/esm/src/transaction/broadcasters/index.js.map +1 -1
  56. package/dist/esm/src/transaction/chaintrackers/DefaultChainTracker.js +5 -0
  57. package/dist/esm/src/transaction/chaintrackers/DefaultChainTracker.js.map +1 -0
  58. package/dist/esm/src/transaction/chaintrackers/WhatsOnChain.js +50 -0
  59. package/dist/esm/src/transaction/chaintrackers/WhatsOnChain.js.map +1 -0
  60. package/dist/esm/src/transaction/chaintrackers/index.js +3 -0
  61. package/dist/esm/src/transaction/chaintrackers/index.js.map +1 -0
  62. package/dist/esm/src/transaction/http/DefaultHttpClient.js +33 -0
  63. package/dist/esm/src/transaction/http/DefaultHttpClient.js.map +1 -0
  64. package/dist/esm/src/transaction/http/FetchHttpClient.js +26 -0
  65. package/dist/esm/src/transaction/http/FetchHttpClient.js.map +1 -0
  66. package/dist/esm/src/transaction/http/HttpClient.js +2 -0
  67. package/dist/esm/src/transaction/http/HttpClient.js.map +1 -0
  68. package/dist/esm/src/transaction/http/NodejsHttpClient.js +38 -0
  69. package/dist/esm/src/transaction/http/NodejsHttpClient.js.map +1 -0
  70. package/dist/esm/src/transaction/http/index.js +4 -0
  71. package/dist/esm/src/transaction/http/index.js.map +1 -0
  72. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  73. package/dist/types/mod.d.ts +1 -0
  74. package/dist/types/mod.d.ts.map +1 -1
  75. package/dist/types/src/primitives/PublicKey.d.ts +18 -0
  76. package/dist/types/src/primitives/PublicKey.d.ts.map +1 -1
  77. package/dist/types/src/primitives/Signature.d.ts +3 -3
  78. package/dist/types/src/script/Script.d.ts.map +1 -1
  79. package/dist/types/src/transaction/MerklePath.d.ts.map +1 -1
  80. package/dist/types/src/transaction/Transaction.d.ts +7 -7
  81. package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
  82. package/dist/types/src/transaction/broadcasters/ARC.d.ts +23 -7
  83. package/dist/types/src/transaction/broadcasters/ARC.d.ts.map +1 -1
  84. package/dist/types/src/transaction/broadcasters/DefaultBroadcaster.d.ts +3 -0
  85. package/dist/types/src/transaction/broadcasters/DefaultBroadcaster.d.ts.map +1 -0
  86. package/dist/types/src/transaction/broadcasters/WhatsOnChainBroadcaster.d.ts +26 -0
  87. package/dist/types/src/transaction/broadcasters/WhatsOnChainBroadcaster.d.ts.map +1 -0
  88. package/dist/types/src/transaction/broadcasters/index.d.ts +3 -0
  89. package/dist/types/src/transaction/broadcasters/index.d.ts.map +1 -1
  90. package/dist/types/src/transaction/chaintrackers/DefaultChainTracker.d.ts +3 -0
  91. package/dist/types/src/transaction/chaintrackers/DefaultChainTracker.d.ts.map +1 -0
  92. package/dist/types/src/transaction/chaintrackers/WhatsOnChain.d.ts +28 -0
  93. package/dist/types/src/transaction/chaintrackers/WhatsOnChain.d.ts.map +1 -0
  94. package/dist/types/src/transaction/chaintrackers/index.d.ts +4 -0
  95. package/dist/types/src/transaction/chaintrackers/index.d.ts.map +1 -0
  96. package/dist/types/src/transaction/http/DefaultHttpClient.d.ts +8 -0
  97. package/dist/types/src/transaction/http/DefaultHttpClient.d.ts.map +1 -0
  98. package/dist/types/src/transaction/http/FetchHttpClient.d.ts +31 -0
  99. package/dist/types/src/transaction/http/FetchHttpClient.d.ts.map +1 -0
  100. package/dist/types/src/transaction/http/HttpClient.d.ts +43 -0
  101. package/dist/types/src/transaction/http/HttpClient.d.ts.map +1 -0
  102. package/dist/types/src/transaction/http/NodejsHttpClient.d.ts +21 -0
  103. package/dist/types/src/transaction/http/NodejsHttpClient.d.ts.map +1 -0
  104. package/dist/types/src/transaction/http/index.d.ts +7 -0
  105. package/dist/types/src/transaction/http/index.d.ts.map +1 -0
  106. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  107. package/docs/examples/EXAMPLE_BUILDING_CUSTOM_TX_BROADCASTER.md +2 -0
  108. package/docs/examples/EXAMPLE_COMPLEX_TX.md +2 -4
  109. package/docs/examples/EXAMPLE_SIMPLE_TX.md +83 -2
  110. package/docs/examples/EXAMPLE_VERIFYING_BEEF.md +29 -22
  111. package/docs/examples/EXAMPLE_VERIFYING_ROOTS.md +18 -63
  112. package/docs/examples/GETTING_STARTED_NODE_CJS.md +2 -4
  113. package/docs/examples/GETTING_STARTED_REACT.md +2 -4
  114. package/docs/primitives.md +36 -3
  115. package/docs/transaction.md +48 -0
  116. package/mod.ts +2 -1
  117. package/package.json +21 -1
  118. package/src/primitives/PublicKey.ts +39 -0
  119. package/src/primitives/Signature.ts +6 -6
  120. package/src/script/Script.ts +19 -19
  121. package/src/transaction/MerklePath.ts +9 -9
  122. package/src/transaction/Transaction.ts +13 -13
  123. package/src/transaction/__tests/Transaction.test.ts +62 -0
  124. package/src/transaction/broadcasters/ARC.ts +71 -57
  125. package/src/transaction/broadcasters/DefaultBroadcaster.ts +6 -0
  126. package/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts +70 -0
  127. package/src/transaction/broadcasters/__tests/ARC.test.ts +152 -41
  128. package/src/transaction/broadcasters/__tests/WhatsOnChainBroadcaster.test.ts +165 -0
  129. package/src/transaction/broadcasters/index.ts +3 -0
  130. package/src/transaction/chaintrackers/DefaultChainTracker.ts +6 -0
  131. package/src/transaction/chaintrackers/WhatsOnChain.ts +70 -0
  132. package/src/transaction/chaintrackers/__tests/WhatsOnChainChainTracker.test.ts +135 -0
  133. package/src/transaction/chaintrackers/index.ts +3 -0
  134. package/src/transaction/http/DefaultHttpClient.ts +32 -0
  135. package/src/transaction/http/FetchHttpClient.ts +50 -0
  136. package/src/transaction/http/HttpClient.ts +45 -0
  137. package/src/transaction/http/NodejsHttpClient.ts +55 -0
  138. package/src/transaction/http/index.ts +6 -0
@@ -45,7 +45,7 @@ await tx.sign()
45
45
  // Finally, we broadcast it with ARC.
46
46
  // get your api key from https://console.taal.com
47
47
  const apiKey = 'mainnet_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' // replace
48
- await tx.broadcast(new ARC('https://api.taal.com/arc', apiKey))
48
+ await tx.broadcast()
49
49
  ```
50
50
 
51
51
  This code snippet demonstrates creating a transaction, adding an input and an output, setting a change script, configuring the fee, signing the transaction, and broadcasting with the ARC broadcaster. It uses the P2PKH Template, which is a specific type of Bitcoin locking program. To learn more about templates, check out this example (link to be provided once cmpplete).
@@ -61,4 +61,85 @@ transaction.addOutput({
61
61
  })
62
62
  ```
63
63
 
64
- The `Transaction` class abstracts the complexity of Bitcoin's transaction structure. It handles inputs, outputs, scripts, and serialization, offering methods to easily modify and interrogate the transaction. Check out the full code-level documentation, refer to other examples, or reach out to the community to learn more.
64
+ The `Transaction` class abstracts the complexity of Bitcoin's transaction structure. It handles inputs, outputs, scripts, and serialization, offering methods to easily modify and interrogate the transaction. Check out the full code-level documentation, refer to other examples, or reach out to the community to learn more.
65
+
66
+ ## Choosing broadcasting target (ARC or WhatsOnChain)
67
+
68
+ ### ARC
69
+
70
+ You can broadcast via selected ARC by providing ARC instance to the `broadcast` method.
71
+
72
+ ```typescript
73
+ await tx.broadcast(new ARC('https://api.taal.com/arc', apiKey))
74
+ ```
75
+
76
+ ### WhatsOnChain
77
+
78
+ You can broadcast via What's On Chain by providing WhatsOnChainBroadcaster instance to the `broadcast` method.
79
+
80
+ ```typescript
81
+ const network = 'main' // or 'test'
82
+ await tx.broadcast(new WhatsOnChainBroadcaster(network))
83
+ ```
84
+
85
+ ## Use custom http client for broadcasting
86
+
87
+ The ARC broadcaster requires an HTTP client to broadcast transactions. By default, the SDK will try to search for `window.fetch` in browser or `https` module on Node.js.
88
+ If you want to use a custom (or preconfigured) HTTP client, you can pass it with use of the adapter the ARC constructor:
89
+
90
+ ### fetch
91
+
92
+ ```typescript
93
+ // In this example we're assuming you have variable fetch holding the fetch function`
94
+
95
+ const arc = new ARC('https://api.taal.com/arc', apiKey, new FetchHttpClient(mockFetch))
96
+ ```
97
+
98
+ ### https
99
+
100
+ Because ARC is assuming concrete interface of the http client, we're providing an adapter for https module.
101
+ You can use it as follows:
102
+
103
+ ```typescript
104
+ // In this example we're assuming you have variable https holding the https module loaded for example with `require('https')`
105
+
106
+ const arc = new ARC('https://api.taal.com/arc', apiKey, new NodejsHttpClient(https))
107
+
108
+ ```
109
+
110
+ ### axios
111
+
112
+ Although the SDK is not providing adapters for axios, it can be easily used with the ARC broadcaster.
113
+ You can make your own "adapter" for axios as follows:
114
+
115
+ ```typescript
116
+ const axiosHttpClient = const httpClient: HttpClient = {
117
+ request: async (...args) => {
118
+ let res;
119
+ try {
120
+ res = await axios(...args);
121
+ } catch (e: unknown) {
122
+ if (axios.isAxiosError(e)) {
123
+ res = e.response;
124
+ } else {
125
+ throw e;
126
+ }
127
+ }
128
+ if (!res) {
129
+ throw new Error('No response');
130
+ }
131
+ return {
132
+ ok: res.status >= 200 && res.status <= 299,
133
+ ...res
134
+ };
135
+ },
136
+ };
137
+
138
+ new ARC('https://api.taal.com/arc', apiKey, axiosHttpClient)
139
+ ```
140
+
141
+ ### other libraries
142
+
143
+ Although the SDK is not providing adapters for other libraries,
144
+ you can easily create your own adapter by implementing the `HttpClient` interface.
145
+ Please look at the example for axios above to see how easy it can be done.
@@ -12,26 +12,6 @@ Merkle proofs are simply a way for someone to prove the existence of a given tra
12
12
 
13
13
  The process for SPV is detailed in [BRC-67](https://github.com/bitcoin-sv/BRCs/blob/master/transactions/0067.md), but the main idea is that when a sender sends a transaction, they include merkle proofs on all of the input transactions. This allows anyone with a copy of the Bitcoin block headers to check that the input transactions are included in the blockchain. Verifiers then check that all the input and output scripts correctly transfer value from one party to the next, ensuring an unbroken chain of spends. The [BEEF data structure](https://github.com/bitcoin-sv/BRCs/blob/master/transactions/0062.md) provides a compact and efficient way for people to represent the data required to perform SPV.
14
14
 
15
- ## Block Headers Client
16
-
17
- To verify BEEF structures with the BSV SDK, you'll need to provide a block headers client that, given a merkle root, will indicate to the library whether the merkle root is correct for the block that's in the active chain at the given block height.
18
-
19
- For simplicity in this example, we are going to use a mock headers client that always indicates every merkle root as valid no matter what. However, in any real project, **you MUST always use an actual block headers client or attackers will be able to easily fool you with fraudulent transactions!**
20
-
21
- The TypeScript BSV SDK does not ship with a block headers client, but check out this example (link to be provided once complete) for setting up Pulse.
22
-
23
- Here is the gullible block headers client we will be using:
24
-
25
- ```typescript
26
- const gullibleHeadersClient = {
27
- // DO NOT USE IN A REAL PROJECT due to security risks of accepting any merkle root as valid without verification
28
- isValidRootForHeight: async (merkleRoot, height) => {
29
- console.log({ merkleRoot, height })
30
- return true
31
- }
32
- }
33
- ```
34
-
35
15
  ## Verifying a BEEF Structure
36
16
 
37
17
  Now that you have access to a block headers client (either Pulse on a real project or the above code for a toy example), we can proceed to verifying the BEEF structure with the following code:
@@ -46,10 +26,37 @@ const BEEFHex = '0100beef01fe636d0c0007021400fe507c0c7aa754cef1f7889d5fd395cf1f7
46
26
  const tx = Transaction.fromHexBEEF(BEEFHex)
47
27
 
48
28
  // This ensures the BEEF structure is legitimate
49
- const verified = await tx.verify(gullibleHeadersClient)
29
+ const verified = await tx.verify()
50
30
 
51
31
  // Print the results
52
32
  console.log(verified)
53
33
  ```
54
34
 
55
- The above code allows you to ensure that a given BEEF structure is valid according to the rules of SPV.
35
+ The above code allows you to ensure that a given BEEF structure is valid according to the rules of SPV.
36
+
37
+ ## Chain tracker
38
+
39
+ To verify BEEF structures with the BSV SDK, you'll need to provide a block headers client that, given a merkle root, will indicate to the library whether the merkle root is correct for the block that's in the active chain at the given block height.
40
+
41
+ The TypeScript BSV SDK does provides default implementation of the chain tracker that use What's On Chain API.
42
+
43
+ ### What's On Chain configuration
44
+
45
+ #### BSV network
46
+
47
+ The default network for the chain tracker is `main`. You can change it to other network by providing the instance of WhatsOnChain ChainTracker configured for other network to `.verify()` method.
48
+
49
+ ```typescript
50
+ tx.verify(new WhatsOnChain())
51
+ ```
52
+
53
+ #### Api Key
54
+
55
+ It is possible to use WhatsOnChain ChainTracker with obtained API KEY of [WhatsOnChain](https://docs.taal.com/core-products/whatsonchain).
56
+ To do so, you need to provide to `.verify()` method the custom instance of WhatsOnChain ChainTracker with the API KEY.
57
+
58
+ ```typescript
59
+ import { Transaction, WhatsOnChain } from '@bsv/sdk'
60
+
61
+ tx.verify(new WhatsOnChain('main', {apiKey: 'YOUR_API_KEY'}))
62
+ ```
@@ -1,6 +1,6 @@
1
1
  # Example: Building a Pulse Block Headers Client
2
2
 
3
- When [verifying BEEF structures](EXAMPLE_VERIFYING_BEEF.md), it's necessary to ensure that all transactions are well-anchored: this is to say, that they come from inputs in the honest chain. The SDK doesn't ship with a headers client, but this guide shows an example of how to use it with [Pulse](https://github.com/bitcoin-sv/block-headers-service): a popular client suitable for a wide range of use-cases.
3
+ When [verifying BEEF structures](EXAMPLE_VERIFYING_BEEF.md), it's necessary to ensure that all transactions are well-anchored: this is to say, that they come from inputs in the honest chain. The SDK doesn't ship with a headers client, but this guide shows an example of how to use it with [block-headers-service](https://github.com/bitcoin-sv/block-headers-service): a popular client suitable for a wide range of use-cases.
4
4
 
5
5
  ## Pre-requisites
6
6
 
@@ -41,59 +41,13 @@ export default interface ChainTracker {
41
41
 
42
42
  ```
43
43
 
44
- We will hide the complexities of making an https request from browsers/node.js in an separate function, which you could then import into the files you need otherwise.
45
-
46
- ```typescript
47
- // httpsClient.ts
48
- async function nodeFetch (https, url, requestOptions): Promise<any> {
49
- return await new Promise((resolve, reject) => {
50
- const req = https.request(url, requestOptions, res => {
51
- let data = ''
52
- res.on('data', (chunk: string) => {
53
- data += chunk
54
- })
55
- res.on('end', () => {
56
- resolve(data)
57
- })
58
- })
59
-
60
- req.on('error', error => {
61
- reject(error)
62
- })
63
-
64
- if (requestOptions.body as boolean) {
65
- req.write(requestOptions.body)
66
- }
67
- req.end()
68
- })
69
- }
70
- }
71
-
72
- export async function httpsClient (url: string, options: any) : Promise<any> {
73
- let response
74
- let data: any = {}
75
- if (typeof window !== 'undefined' && typeof window.fetch === 'function') {
76
- // Use fetch in a browser environment
77
- response = await window.fetch(url, options)
78
- data = await response.json()
79
- return data
80
- }
81
- if (typeof require === 'undefined') throw new Error('No method available to perform HTTP request')
82
- // Use Node.js https module
83
- // eslint-disable-next-line
84
- const https = require('https')
85
- response = await nodeFetch(https, url, requestOptions)
86
- data = JSON.parse(response)
87
- return data
88
- }
89
- ```
90
-
91
-
92
44
  Given an array of merkle roots and corresponding block heights, we return a boolean indicating whether they're all valid.
93
45
 
94
46
  We can plug in the Block Header Service API with appropriate HTTP handling logic as follows:
95
47
 
96
48
  ```typescript
49
+ import {defaultHttpClient} from "@bsv/sdk";
50
+
97
51
  /**
98
52
  * Represents a Block Headers Client.
99
53
  */
@@ -107,9 +61,10 @@ export default class BlockHeadersClient implements ChainTracker {
107
61
  * @param {string} URL - The URL endpoint for the Pulse API.
108
62
  * @param {string} apiKey - The API key used for authorization with the Pulse API.
109
63
  */
110
- constructor (URL: string, apiKey: string) {
64
+ constructor(URL: string, apiKey: string) {
111
65
  this.URL = URL
112
66
  this.apiKey = apiKey
67
+ this.httpClient = defaultHttpClient()
113
68
  }
114
69
 
115
70
  /**
@@ -119,19 +74,19 @@ export default class BlockHeadersClient implements ChainTracker {
119
74
  * @param height: number - The corresponding height
120
75
  * @returns {Promise<boolean>} A promise that resolves to either a success or failure response (true or false).
121
76
  */
122
- async isValidRootForHeight (root: string, height: number): Promise<boolean> {
123
- try {
124
- const data = await httpsClient(`${this.URL}/api/v1/chain/merkleroot/verify`, {
125
- method: 'POST',
126
- body: JSON.stringify([{ merkleRoot: root, blockHeight: height }]),
127
- headers: {
128
- 'Content-Type': 'application/json',
129
- Authorization: `Bearer ${this.apiKey}`
130
- }
131
- })
132
- return data?.confirmationState === 'CONFIRMED'
133
- } catch (error) {
134
- return false
77
+ async isValidRootForHeight(root: string, height: number): Promise<boolean> {
78
+ const response = await httpsClient(`${this.URL}/api/v1/chain/merkleroot/verify`, {
79
+ method: 'POST',
80
+ body: [{merkleRoot: root, blockHeight: height}],
81
+ headers: {
82
+ 'Content-Type': 'application/json',
83
+ Authorization: `Bearer ${this.apiKey}`
84
+ }
85
+ })
86
+ if (response.ok) {
87
+ return response.data?.confirmationState === 'CONFIRMED'
88
+ } else {
89
+ throw new Error(`Failed to verify root at height ${height} with response ${response.status}`)
135
90
  }
136
91
  }
137
92
  }
@@ -53,9 +53,7 @@ const tx = new Transaction(version, [input], [output])
53
53
  await tx.fee()
54
54
  await tx.sign()
55
55
 
56
- // get your api key from https://console.taal.com
57
- const apiKey = 'mainnet_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' // replace
58
- await tx.broadcast(new ARC('https://api.taal.com/arc', apiKey))
56
+ await tx.broadcast()
59
57
  ```
60
58
 
61
59
  This script demonstrates the entire process of creating a transaction, from initializing keys to signing and broadcast. When you run this script using Node.js (replacing the source transaction, private key, and ARC credentials), the spend will be signed and broadcast to the BSV network.
@@ -70,4 +68,4 @@ node index.js
70
68
 
71
69
  ## Conclusion
72
70
 
73
- Congratulations! You've successfully installed the BSV SDK in your NodeJS project and created a signed transaction. This guide covered the basics to get you started, but the BSV SDK is capable of much more. Explore the SDK documentation for detailed information on all the features and functionalities available to build scalable applications with the BSV blockchain.
71
+ Congratulations! You've successfully installed the BSV SDK in your NodeJS project and created a signed transaction. This guide covered the basics to get you started, but the BSV SDK is capable of much more. Explore the SDK documentation for detailed information on all the features and functionalities available to build scalable applications with the BSV blockchain.
@@ -60,9 +60,7 @@ const BsvButton: React.FC = () => {
60
60
  await tx.fee()
61
61
  await tx.sign()
62
62
 
63
- // grab your api key from https://console.taal.com
64
- const apiKey = 'mainnet_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' // replace
65
- await tx.broadcast(new ARC('https://api.taal.com/arc', apiKey))
63
+ await tx.broadcast()
66
64
  }
67
65
 
68
66
  return (
@@ -118,4 +116,4 @@ Now when you click the button, a transaction will be created, signed, and broadc
118
116
  Conclusion
119
117
  ----------
120
118
 
121
- Congratulations! You've successfully integrated the BSV SDK into your TypeScript & React application and created a button which broadcasts a bitcoin transaction on click. This guide covered the basic steps needed to get you started, but the BSV SDK can do a lot more. Explore the SDK documentation to dive deep into all the features and functionalities available to build scalable applications on the BSV blockchain.
119
+ Congratulations! You've successfully integrated the BSV SDK into your TypeScript & React application and created a button which broadcasts a bitcoin transaction on click. This guide covered the basic steps needed to get you started, but the BSV SDK can do a lot more. Explore the SDK documentation to dive deep into all the features and functionalities available to build scalable applications on the BSV blockchain.
@@ -6178,9 +6178,9 @@ const publicKey = signature.RecoverPublicKey(0, msgHash);
6178
6178
  Takes an array of numbers or a string and returns a new Signature instance.
6179
6179
  This method will throw an error if the Compact encoding is invalid.
6180
6180
  If a string is provided, it is assumed to represent a hexadecimal sequence.
6181
- compactByte value 27-31 means compressed public key.
6182
- 32-35 means uncompressed public key.
6183
- The range represents the recovery param which can be 0,1,2,3,4.
6181
+ compactByte value 27-30 means uncompressed public key.
6182
+ 31-34 means compressed public key.
6183
+ The range represents the recovery param which can be 0,1,2,3.
6184
6184
  We could support recovery functions in future if there's demand.
6185
6185
 
6186
6186
  ```ts
@@ -6704,6 +6704,7 @@ export default class PublicKey extends Point {
6704
6704
  toHash(enc?: "hex"): number[] | string
6705
6705
  toAddress(prefix: number[] = [0]): string
6706
6706
  deriveChild(privateKey: PrivateKey, invoiceNumber: string): PublicKey
6707
+ static fromMsgHashAndCompactSignature(msgHash: BigNumber, signature: number[] | string, enc?: "hex" | "base64"): PublicKey
6707
6708
  }
6708
6709
  ```
6709
6710
 
@@ -6781,6 +6782,38 @@ const myPrivKey = new PrivateKey(...)
6781
6782
  const sharedSecret = myPubKey.deriveSharedSecret(myPrivKey)
6782
6783
  ```
6783
6784
 
6785
+ #### Method fromMsgHashAndCompactSignature
6786
+
6787
+ Takes an array of numbers or a string and returns a new PublicKey instance.
6788
+ This method will throw an error if the Compact encoding is invalid.
6789
+ If a string is provided, it is assumed to represent a hexadecimal sequence.
6790
+ compactByte value 27-30 means uncompressed public key.
6791
+ 31-34 means compressed public key.
6792
+ The range represents the recovery param which can be 0,1,2,3.
6793
+
6794
+ ```ts
6795
+ static fromMsgHashAndCompactSignature(msgHash: BigNumber, signature: number[] | string, enc?: "hex" | "base64"): PublicKey
6796
+ ```
6797
+
6798
+ Returns
6799
+
6800
+ A PublicKey instance derived from the message hash and compact signature.
6801
+
6802
+ Argument Details
6803
+
6804
+ + **msgHash**
6805
+ + The message hash which was signed.
6806
+ + **signature**
6807
+ + The signature in compact format.
6808
+ + **enc**
6809
+ + The encoding of the signature string.
6810
+
6811
+ Example
6812
+
6813
+ ```ts
6814
+ const publicKey = Signature.fromMsgHashAndCompactSignature(msgHash, 'IMOl2mVKfDgsSsHT4uIYBNN4e...', 'base64');
6815
+ ```
6816
+
6784
6817
  #### Method fromPrivateKey
6785
6818
 
6786
6819
  Static factory method to derive a public key from a private key.
@@ -426,6 +426,18 @@ export default class Transaction {
426
426
  metadata: Record<string, any>;
427
427
  merklePath?: MerklePath;
428
428
  static fromBEEF(beef: number[]): Transaction
429
+ static parseScriptOffsets(bin: number[]): {
430
+ inputs: {
431
+ vin: number;
432
+ offset: number;
433
+ length: number;
434
+ }[];
435
+ outputs: {
436
+ vout: number;
437
+ offset: number;
438
+ length: number;
439
+ }[];
440
+ }
429
441
  static fromBinary(bin: number[]): Transaction
430
442
  static fromHex(hex: string): Transaction
431
443
  static fromHexBEEF(hex: string): Transaction
@@ -651,6 +663,42 @@ Argument Details
651
663
  + **enc**
652
664
  + The encoding to use for the ID. If 'hex', returns a hexadecimal string; otherwise returns a binary array.
653
665
 
666
+ #### Method parseScriptOffsets
667
+
668
+ Since the validation of blockchain data is atomically transaction data validation,
669
+ any application seeking to validate data in output scripts must store the entire transaction as well.
670
+ Since the transaction data includes the output script data, saving a second copy of potentially
671
+ large scripts can bloat application storage requirements.
672
+
673
+ This function efficiently parses binary transaction data to determine the offsets and lengths of each script.
674
+ This supports the efficient retreival of script data from transaction data.
675
+
676
+ ```ts
677
+ static parseScriptOffsets(bin: number[]): {
678
+ inputs: {
679
+ vin: number;
680
+ offset: number;
681
+ length: number;
682
+ }[];
683
+ outputs: {
684
+ vout: number;
685
+ offset: number;
686
+ length: number;
687
+ }[];
688
+ }
689
+ ```
690
+
691
+ Returns
692
+
693
+ inputs: { vin: number, offset: number, length: number }[]
694
+ outputs: { vout: number, offset: number, length: number }[]
695
+ }
696
+
697
+ Argument Details
698
+
699
+ + **bin**
700
+ + binary transaction data
701
+
654
702
  #### Method sign
655
703
 
656
704
  Signs a transaction, hydrating all its unlocking scripts based on the provided script templates where they are available.
package/mod.ts CHANGED
@@ -4,5 +4,6 @@ export * from "./src/script/templates/index.js"
4
4
  export * from "./src/transaction/index.js"
5
5
  export * from "./src/transaction/fee-models/index.js"
6
6
  export * from "./src/transaction/broadcasters/index.js"
7
+ export * from "./src/transaction/http/index.js"
7
8
  export * from "./src/messages/index.js"
8
- export * from "./src/compat/index.js"
9
+ export * from "./src/compat/index.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.0.32",
3
+ "version": "1.0.34",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -74,6 +74,26 @@
74
74
  "require": "./dist/cjs/src/transaction/broadcaster/*.js",
75
75
  "types": "./dist/types/src/transaction/broadcaster/*.d.ts"
76
76
  },
77
+ "./transaction/chaintrackers": {
78
+ "import": "./dist/esm/src/transaction/chaintrackers/index.js",
79
+ "require": "./dist/cjs/src/transaction/chaintrackers/index.js",
80
+ "types": "./dist/types/src/transaction/chaintrackers/index.d.ts"
81
+ },
82
+ "./transaction/chaintrackers/*": {
83
+ "import": "./dist/esm/src/transaction/chaintrackers/*.js",
84
+ "require": "./dist/cjs/src/transaction/chaintrackers/*.js",
85
+ "types": "./dist/types/src/transaction/chaintrackers/*.d.ts"
86
+ },
87
+ "./transaction/http": {
88
+ "import": "./dist/esm/src/transaction/http/index.js",
89
+ "require": "./dist/cjs/src/transaction/http/index.js",
90
+ "types": "./dist/types/src/transaction/http/index.d.ts"
91
+ },
92
+ "./transaction/http/*": {
93
+ "import": "./dist/esm/src/transaction/http/*.js",
94
+ "require": "./dist/cjs/src/transaction/http/*.js",
95
+ "types": "./dist/types/src/transaction/http/*.d.ts"
96
+ },
77
97
  "./transaction/fee-model": {
78
98
  "import": "./dist/esm/src/transaction/fee-model/index.js",
79
99
  "require": "./dist/cjs/src/transaction/fee-model/index.js",
@@ -172,4 +172,43 @@ export default class PublicKey extends Point {
172
172
  const finalPoint = this.add(point)
173
173
  return new PublicKey(finalPoint.x, finalPoint.y)
174
174
  }
175
+
176
+ /**
177
+ * Takes an array of numbers or a string and returns a new PublicKey instance.
178
+ * This method will throw an error if the Compact encoding is invalid.
179
+ * If a string is provided, it is assumed to represent a hexadecimal sequence.
180
+ * compactByte value 27-30 means uncompressed public key.
181
+ * 31-34 means compressed public key.
182
+ * The range represents the recovery param which can be 0,1,2,3.
183
+ *
184
+ * @static
185
+ * @method fromMsgHashAndCompactSignature
186
+ * @param msgHash - The message hash which was signed.
187
+ * @param signature - The signature in compact format.
188
+ * @param enc - The encoding of the signature string.
189
+ * @returns A PublicKey instance derived from the message hash and compact signature.
190
+ * @example
191
+ * const publicKey = Signature.fromMsgHashAndCompactSignature(msgHash, 'IMOl2mVKfDgsSsHT4uIYBNN4e...', 'base64');
192
+ */
193
+ static fromMsgHashAndCompactSignature (msgHash: BigNumber, signature: number[] | string, enc?: 'hex' | 'base64'): PublicKey {
194
+ const data = toArray(signature, enc)
195
+ if (data.length !== 65) {
196
+ throw new Error('Invalid Compact Signature')
197
+ }
198
+ const compactByte = data[0]
199
+ if (compactByte < 27 || compactByte >= 35) {
200
+ throw new Error('Invalid Compact Byte')
201
+ }
202
+ let r = data[0] - 27
203
+ let compressed = false // we don't really use this in the modern era, always use compressed.
204
+ if (r > 3) {
205
+ compressed = true
206
+ r -= 4
207
+ }
208
+ const s = new Signature(
209
+ new BigNumber(data.slice(1, 33)),
210
+ new BigNumber(data.slice(33, 65))
211
+ )
212
+ return s.RecoverPublicKey(r, msgHash)
213
+ }
175
214
  }
@@ -106,9 +106,9 @@ export default class Signature {
106
106
  * Takes an array of numbers or a string and returns a new Signature instance.
107
107
  * This method will throw an error if the Compact encoding is invalid.
108
108
  * If a string is provided, it is assumed to represent a hexadecimal sequence.
109
- * compactByte value 27-31 means compressed public key.
110
- * 32-35 means uncompressed public key.
111
- * The range represents the recovery param which can be 0,1,2,3,4.
109
+ * compactByte value 27-30 means uncompressed public key.
110
+ * 31-34 means compressed public key.
111
+ * The range represents the recovery param which can be 0,1,2,3.
112
112
  * We could support recovery functions in future if there's demand.
113
113
  *
114
114
  * @static
@@ -339,9 +339,9 @@ export default class Signature {
339
339
  const rInv = r.invm(n)
340
340
 
341
341
  // const Q = R.multiplyTwo(s, G, eNeg).mul(rInv)
342
- const Q = R.mul(s)
343
- .add(G.mul(eNeg))
344
- .mul(rInv)
342
+ const srInv = rInv.mul(s).umod(n)
343
+ const eInvrInv = rInv.mul(eNeg).umod(n)
344
+ const Q = G.mul(eInvrInv).add(R.mul(srInv))
345
345
 
346
346
  const pubKey = new PublicKey(Q)
347
347
  pubKey.validate()