@bsv/sdk 2.0.7 → 2.0.8
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/dist/cjs/package.json +1 -1
- package/dist/cjs/src/script/templates/P2PKH.js +9 -43
- package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
- package/dist/cjs/src/script/templates/PushDrop.js +10 -40
- package/dist/cjs/src/script/templates/PushDrop.js.map +1 -1
- package/dist/cjs/src/script/templates/SignatureUtils.js +77 -0
- package/dist/cjs/src/script/templates/SignatureUtils.js.map +1 -0
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/src/transaction/http/BinaryFetchClient.js +2 -28
- package/dist/cjs/src/transaction/http/BinaryFetchClient.js.map +1 -1
- package/dist/cjs/src/transaction/http/NodejsHttpClient.js +2 -28
- package/dist/cjs/src/transaction/http/NodejsHttpClient.js.map +1 -1
- package/dist/cjs/src/transaction/http/NodejsHttpRequestUtils.js +43 -0
- package/dist/cjs/src/transaction/http/NodejsHttpRequestUtils.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/InvokableWalletBase.js +98 -0
- package/dist/cjs/src/wallet/substrates/InvokableWalletBase.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/ReactNativeWebView.js +3 -85
- package/dist/cjs/src/wallet/substrates/ReactNativeWebView.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/XDM.js +3 -85
- package/dist/cjs/src/wallet/substrates/XDM.js.map +1 -1
- package/dist/cjs/src/wallet/substrates/index.js +3 -1
- package/dist/cjs/src/wallet/substrates/index.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/script/templates/P2PKH.js +10 -46
- package/dist/esm/src/script/templates/P2PKH.js.map +1 -1
- package/dist/esm/src/script/templates/PushDrop.js +10 -42
- package/dist/esm/src/script/templates/PushDrop.js.map +1 -1
- package/dist/esm/src/script/templates/SignatureUtils.js +69 -0
- package/dist/esm/src/script/templates/SignatureUtils.js.map +1 -0
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/src/transaction/http/BinaryFetchClient.js +2 -28
- package/dist/esm/src/transaction/http/BinaryFetchClient.js.map +1 -1
- package/dist/esm/src/transaction/http/NodejsHttpClient.js +2 -28
- package/dist/esm/src/transaction/http/NodejsHttpClient.js.map +1 -1
- package/dist/esm/src/transaction/http/NodejsHttpRequestUtils.js +40 -0
- package/dist/esm/src/transaction/http/NodejsHttpRequestUtils.js.map +1 -0
- package/dist/esm/src/wallet/substrates/InvokableWalletBase.js +94 -0
- package/dist/esm/src/wallet/substrates/InvokableWalletBase.js.map +1 -0
- package/dist/esm/src/wallet/substrates/ReactNativeWebView.js +3 -85
- package/dist/esm/src/wallet/substrates/ReactNativeWebView.js.map +1 -1
- package/dist/esm/src/wallet/substrates/XDM.js +3 -85
- package/dist/esm/src/wallet/substrates/XDM.js.map +1 -1
- package/dist/esm/src/wallet/substrates/index.js +1 -0
- package/dist/esm/src/wallet/substrates/index.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/script/templates/P2PKH.d.ts.map +1 -1
- package/dist/types/src/script/templates/PushDrop.d.ts.map +1 -1
- package/dist/types/src/script/templates/SignatureUtils.d.ts +32 -0
- package/dist/types/src/script/templates/SignatureUtils.d.ts.map +1 -0
- package/dist/types/src/transaction/Transaction.d.ts +1 -0
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/src/transaction/http/BinaryFetchClient.d.ts +1 -1
- package/dist/types/src/transaction/http/BinaryFetchClient.d.ts.map +1 -1
- package/dist/types/src/transaction/http/NodejsHttpClient.d.ts +1 -1
- package/dist/types/src/transaction/http/NodejsHttpClient.d.ts.map +1 -1
- package/dist/types/src/transaction/http/NodejsHttpRequestUtils.d.ts +22 -0
- package/dist/types/src/transaction/http/NodejsHttpRequestUtils.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/InvokableWalletBase.d.ts +41 -0
- package/dist/types/src/wallet/substrates/InvokableWalletBase.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/ReactNativeWebView.d.ts +2 -403
- package/dist/types/src/wallet/substrates/ReactNativeWebView.d.ts.map +1 -1
- package/dist/types/src/wallet/substrates/XDM.d.ts +2 -403
- package/dist/types/src/wallet/substrates/XDM.d.ts.map +1 -1
- package/dist/types/src/wallet/substrates/index.d.ts +1 -0
- package/dist/types/src/wallet/substrates/index.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +3 -3
- package/dist/umd/bundle.js.map +1 -1
- package/package.json +1 -1
- package/src/script/templates/P2PKH.ts +10 -59
- package/src/script/templates/PushDrop.ts +11 -54
- package/src/script/templates/SignatureUtils.ts +111 -0
- package/src/transaction/Transaction.ts +1 -0
- package/src/transaction/__tests/Transaction.test.ts +9 -9
- package/src/transaction/http/BinaryFetchClient.ts +8 -32
- package/src/transaction/http/NodejsHttpClient.ts +8 -32
- package/src/transaction/http/NodejsHttpRequestUtils.ts +68 -0
- package/src/wallet/substrates/InvokableWalletBase.ts +176 -0
- package/src/wallet/substrates/ReactNativeWebView.ts +3 -491
- package/src/wallet/substrates/XDM.ts +3 -491
- package/src/wallet/substrates/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import OP from '../OP.js'
|
|
2
2
|
import ScriptTemplate from '../ScriptTemplate.js'
|
|
3
|
-
import { fromBase58Check
|
|
3
|
+
import { fromBase58Check } from '../../primitives/utils.js'
|
|
4
4
|
import LockingScript from '../LockingScript.js'
|
|
5
5
|
import UnlockingScript from '../UnlockingScript.js'
|
|
6
6
|
import Transaction from '../../transaction/Transaction.js'
|
|
@@ -8,6 +8,7 @@ import PrivateKey from '../../primitives/PrivateKey.js'
|
|
|
8
8
|
import TransactionSignature from '../../primitives/TransactionSignature.js'
|
|
9
9
|
import { sha256 } from '../../primitives/Hash.js'
|
|
10
10
|
import Script from '../Script.js'
|
|
11
|
+
import { computeSignatureScope, resolveSourceDetails, formatPreimage } from './SignatureUtils.js'
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* P2PKH (Pay To Public Key Hash) class implementing ScriptTemplate.
|
|
@@ -71,65 +72,15 @@ export default class P2PKH implements ScriptTemplate {
|
|
|
71
72
|
} {
|
|
72
73
|
return {
|
|
73
74
|
sign: async (tx: Transaction, inputIndex: number) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (signOutputs === 'none') {
|
|
79
|
-
signatureScope |= TransactionSignature.SIGHASH_NONE
|
|
80
|
-
}
|
|
81
|
-
if (signOutputs === 'single') {
|
|
82
|
-
signatureScope |= TransactionSignature.SIGHASH_SINGLE
|
|
83
|
-
}
|
|
84
|
-
if (anyoneCanPay) {
|
|
85
|
-
signatureScope |= TransactionSignature.SIGHASH_ANYONECANPAY
|
|
86
|
-
}
|
|
75
|
+
const signatureScope = computeSignatureScope(signOutputs, anyoneCanPay)
|
|
76
|
+
const resolved = resolveSourceDetails(tx, inputIndex, sourceSatoshis, lockingScript)
|
|
77
|
+
sourceSatoshis = resolved.sourceSatoshis
|
|
78
|
+
lockingScript = resolved.lockingScript
|
|
87
79
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
const sourceTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex')
|
|
95
|
-
if (sourceTXID == null || sourceTXID === undefined) {
|
|
96
|
-
throw new Error(
|
|
97
|
-
'The input sourceTXID or sourceTransaction is required for transaction signing.'
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
if (sourceTXID === '') {
|
|
101
|
-
throw new Error(
|
|
102
|
-
'The input sourceTXID or sourceTransaction is required for transaction signing.'
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
sourceSatoshis ||=
|
|
106
|
-
input.sourceTransaction?.outputs[input.sourceOutputIndex].satoshis
|
|
107
|
-
if (sourceSatoshis == null || sourceSatoshis === undefined) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
'The sourceSatoshis or input sourceTransaction is required for transaction signing.'
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
lockingScript ||=
|
|
113
|
-
input.sourceTransaction?.outputs[input.sourceOutputIndex]
|
|
114
|
-
.lockingScript
|
|
115
|
-
if (lockingScript == null) {
|
|
116
|
-
throw new Error(
|
|
117
|
-
'The lockingScript or input sourceTransaction is required for transaction signing.'
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const preimage = TransactionSignature.format({
|
|
122
|
-
sourceTXID,
|
|
123
|
-
sourceOutputIndex: verifyNotNull(input.sourceOutputIndex, 'input.sourceOutputIndex must have value'),
|
|
124
|
-
sourceSatoshis,
|
|
125
|
-
transactionVersion: tx.version,
|
|
126
|
-
otherInputs,
|
|
127
|
-
inputIndex,
|
|
128
|
-
outputs: tx.outputs,
|
|
129
|
-
inputSequence: verifyNotNull(input.sequence, 'input.sequence must have value'),
|
|
130
|
-
subscript: lockingScript,
|
|
131
|
-
lockTime: tx.lockTime,
|
|
132
|
-
scope: signatureScope
|
|
80
|
+
const preimage = formatPreimage({
|
|
81
|
+
tx, inputIndex, signatureScope,
|
|
82
|
+
sourceTXID: resolved.sourceTXID, sourceSatoshis: resolved.sourceSatoshis,
|
|
83
|
+
lockingScript: resolved.lockingScript, otherInputs: resolved.otherInputs
|
|
133
84
|
})
|
|
134
85
|
|
|
135
86
|
const rawSignature = privateKey.sign(sha256(preimage))
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import { WalletInterface, WalletProtocol } from '../../wallet/Wallet.interfaces.js'
|
|
10
10
|
import { Transaction } from '../../transaction/index.js'
|
|
11
11
|
import { verifyNotNull } from '../../primitives/utils.js'
|
|
12
|
+
import { computeSignatureScope, resolveSourceDetails, formatPreimage } from './SignatureUtils.js'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* For a given piece of data to push onto the stack in script, creates the correct minimally-encoded script chunk,
|
|
@@ -216,60 +217,16 @@ export default class PushDrop implements ScriptTemplate {
|
|
|
216
217
|
tx: Transaction,
|
|
217
218
|
inputIndex: number
|
|
218
219
|
): Promise<UnlockingScript> => {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (anyoneCanPay) {
|
|
230
|
-
signatureScope |= TransactionSignature.SIGHASH_ANYONECANPAY
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const input = tx.inputs[inputIndex]
|
|
234
|
-
|
|
235
|
-
const otherInputs = tx.inputs.filter(
|
|
236
|
-
(_, index) => index !== inputIndex
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
const sourceTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex')
|
|
240
|
-
if (sourceTXID == null || sourceTXID === undefined) {
|
|
241
|
-
throw new Error(
|
|
242
|
-
'The input sourceTXID or sourceTransaction is required for transaction signing.'
|
|
243
|
-
)
|
|
244
|
-
}
|
|
245
|
-
sourceSatoshis ||=
|
|
246
|
-
input.sourceTransaction?.outputs[input.sourceOutputIndex].satoshis
|
|
247
|
-
if (sourceSatoshis == null || sourceSatoshis === undefined) {
|
|
248
|
-
throw new Error(
|
|
249
|
-
'The sourceSatoshis or input sourceTransaction is required for transaction signing.'
|
|
250
|
-
)
|
|
251
|
-
}
|
|
252
|
-
lockingScript ||=
|
|
253
|
-
input.sourceTransaction?.outputs[input.sourceOutputIndex]
|
|
254
|
-
.lockingScript
|
|
255
|
-
if (lockingScript == null) {
|
|
256
|
-
throw new Error(
|
|
257
|
-
'The lockingScript or input sourceTransaction is required for transaction signing.'
|
|
258
|
-
)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const preimage = TransactionSignature.format({
|
|
262
|
-
sourceTXID,
|
|
263
|
-
sourceOutputIndex: verifyNotNull(input.sourceOutputIndex, 'input.sourceOutputIndex must have value'),
|
|
264
|
-
sourceSatoshis,
|
|
265
|
-
transactionVersion: tx.version,
|
|
266
|
-
otherInputs,
|
|
267
|
-
inputIndex,
|
|
268
|
-
outputs: tx.outputs,
|
|
269
|
-
inputSequence: input.sequence ?? 0xffffffff,
|
|
270
|
-
subscript: lockingScript,
|
|
271
|
-
lockTime: tx.lockTime,
|
|
272
|
-
scope: signatureScope
|
|
220
|
+
const signatureScope = computeSignatureScope(signOutputs, anyoneCanPay)
|
|
221
|
+
const resolved = resolveSourceDetails(tx, inputIndex, sourceSatoshis, lockingScript)
|
|
222
|
+
sourceSatoshis = resolved.sourceSatoshis
|
|
223
|
+
lockingScript = resolved.lockingScript as LockingScript
|
|
224
|
+
|
|
225
|
+
const preimage = formatPreimage({
|
|
226
|
+
tx, inputIndex, signatureScope,
|
|
227
|
+
sourceTXID: resolved.sourceTXID, sourceSatoshis: resolved.sourceSatoshis,
|
|
228
|
+
lockingScript: resolved.lockingScript, otherInputs: resolved.otherInputs,
|
|
229
|
+
inputSequence: tx.inputs[inputIndex].sequence ?? 0xffffffff
|
|
273
230
|
})
|
|
274
231
|
|
|
275
232
|
const preimageHash = Hash.sha256(preimage)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import TransactionSignature from '../../primitives/TransactionSignature.js'
|
|
2
|
+
import Transaction from '../../transaction/Transaction.js'
|
|
3
|
+
import Script from '../Script.js'
|
|
4
|
+
import { verifyNotNull } from '../../primitives/utils.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Computes the signature scope flags from the given signing parameters.
|
|
8
|
+
*/
|
|
9
|
+
export function computeSignatureScope(
|
|
10
|
+
signOutputs: 'all' | 'none' | 'single',
|
|
11
|
+
anyoneCanPay: boolean
|
|
12
|
+
): number {
|
|
13
|
+
let signatureScope = TransactionSignature.SIGHASH_FORKID
|
|
14
|
+
if (signOutputs === 'all') {
|
|
15
|
+
signatureScope |= TransactionSignature.SIGHASH_ALL
|
|
16
|
+
}
|
|
17
|
+
if (signOutputs === 'none') {
|
|
18
|
+
signatureScope |= TransactionSignature.SIGHASH_NONE
|
|
19
|
+
}
|
|
20
|
+
if (signOutputs === 'single') {
|
|
21
|
+
signatureScope |= TransactionSignature.SIGHASH_SINGLE
|
|
22
|
+
}
|
|
23
|
+
if (anyoneCanPay) {
|
|
24
|
+
signatureScope |= TransactionSignature.SIGHASH_ANYONECANPAY
|
|
25
|
+
}
|
|
26
|
+
return signatureScope
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolves and validates the source transaction details needed for signing.
|
|
31
|
+
* Returns the resolved sourceTXID, sourceSatoshis, lockingScript, and otherInputs.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveSourceDetails(
|
|
34
|
+
tx: Transaction,
|
|
35
|
+
inputIndex: number,
|
|
36
|
+
providedSourceSatoshis?: number,
|
|
37
|
+
providedLockingScript?: Script
|
|
38
|
+
): {
|
|
39
|
+
sourceTXID: string
|
|
40
|
+
sourceSatoshis: number
|
|
41
|
+
lockingScript: Script
|
|
42
|
+
otherInputs: typeof tx.inputs
|
|
43
|
+
} {
|
|
44
|
+
const input = tx.inputs[inputIndex]
|
|
45
|
+
|
|
46
|
+
const otherInputs = tx.inputs.filter(
|
|
47
|
+
(_, index) => index !== inputIndex
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
const sourceTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex')
|
|
51
|
+
if (sourceTXID == null || sourceTXID === undefined) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
'The input sourceTXID or sourceTransaction is required for transaction signing.'
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
if (sourceTXID === '') {
|
|
57
|
+
throw new Error(
|
|
58
|
+
'The input sourceTXID or sourceTransaction is required for transaction signing.'
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
const sourceSatoshis = providedSourceSatoshis ??
|
|
62
|
+
input.sourceTransaction?.outputs[input.sourceOutputIndex].satoshis
|
|
63
|
+
if (sourceSatoshis == null || sourceSatoshis === undefined) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
'The sourceSatoshis or input sourceTransaction is required for transaction signing.'
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
const lockingScript = providedLockingScript ??
|
|
69
|
+
input.sourceTransaction?.outputs[input.sourceOutputIndex]
|
|
70
|
+
.lockingScript
|
|
71
|
+
if (lockingScript == null) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
'The lockingScript or input sourceTransaction is required for transaction signing.'
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return { sourceTXID, sourceSatoshis, lockingScript, otherInputs }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Parameters for formatting the transaction preimage */
|
|
81
|
+
export interface FormatPreimageParams {
|
|
82
|
+
tx: Transaction
|
|
83
|
+
inputIndex: number
|
|
84
|
+
signatureScope: number
|
|
85
|
+
sourceTXID: string
|
|
86
|
+
sourceSatoshis: number
|
|
87
|
+
lockingScript: Script
|
|
88
|
+
otherInputs: Transaction['inputs']
|
|
89
|
+
inputSequence?: number
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Formats the transaction preimage for signing.
|
|
94
|
+
*/
|
|
95
|
+
export function formatPreimage(params: FormatPreimageParams): number[] {
|
|
96
|
+
const { tx, inputIndex, signatureScope, sourceTXID, sourceSatoshis, lockingScript, otherInputs, inputSequence } = params
|
|
97
|
+
const input = tx.inputs[inputIndex]
|
|
98
|
+
return TransactionSignature.format({
|
|
99
|
+
sourceTXID,
|
|
100
|
+
sourceOutputIndex: verifyNotNull(input.sourceOutputIndex, 'input.sourceOutputIndex must have value'),
|
|
101
|
+
sourceSatoshis,
|
|
102
|
+
transactionVersion: tx.version,
|
|
103
|
+
otherInputs,
|
|
104
|
+
inputIndex,
|
|
105
|
+
outputs: tx.outputs,
|
|
106
|
+
inputSequence: inputSequence ?? verifyNotNull(input.sequence, 'input.sequence must have value'),
|
|
107
|
+
subscript: lockingScript,
|
|
108
|
+
lockTime: tx.lockTime,
|
|
109
|
+
scope: signatureScope
|
|
110
|
+
})
|
|
111
|
+
}
|
|
@@ -15,6 +15,7 @@ import { defaultBroadcaster } from './broadcasters/DefaultBroadcaster.js'
|
|
|
15
15
|
import { defaultChainTracker } from './chaintrackers/DefaultChainTracker.js'
|
|
16
16
|
import { Beef, BEEF_V1 } from './Beef.js'
|
|
17
17
|
import P2PKH from '../script/templates/P2PKH.js'
|
|
18
|
+
import type { WalletInterface, DescriptionString5to50Bytes, CreateActionOptions } from '../wallet/Wallet.interfaces.js'
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Represents a complete Bitcoin transaction. This class encapsulates all the details
|
|
@@ -1462,7 +1462,7 @@ describe('Transaction', () => {
|
|
|
1462
1462
|
|
|
1463
1463
|
describe('completeWithWallet', () => {
|
|
1464
1464
|
// Mock implementation of WalletInterface for testing
|
|
1465
|
-
class MockWallet
|
|
1465
|
+
class MockWallet {
|
|
1466
1466
|
public lastCreateActionArgs: CreateActionArgs | null = null
|
|
1467
1467
|
public lastSignActionArgs: any = null
|
|
1468
1468
|
public signActionCalled: boolean = false
|
|
@@ -1624,7 +1624,7 @@ describe('Transaction', () => {
|
|
|
1624
1624
|
const mockWallet = new MockWallet()
|
|
1625
1625
|
|
|
1626
1626
|
// Complete the transaction with the wallet
|
|
1627
|
-
await tx.completeWithWallet(mockWallet,
|
|
1627
|
+
await tx.completeWithWallet(mockWallet as unknown as WalletInterface,'Test transaction completion')
|
|
1628
1628
|
|
|
1629
1629
|
// Verify that the wallet's createAction was called with correct arguments
|
|
1630
1630
|
expect(mockWallet.lastCreateActionArgs).not.toBeNull()
|
|
@@ -1665,7 +1665,7 @@ describe('Transaction', () => {
|
|
|
1665
1665
|
const mockWallet = new MockWallet()
|
|
1666
1666
|
|
|
1667
1667
|
// Expect completeWithWallet to throw an error
|
|
1668
|
-
await expect(tx.completeWithWallet(mockWallet))
|
|
1668
|
+
await expect(tx.completeWithWallet(mockWallet as unknown as WalletInterface))
|
|
1669
1669
|
.rejects
|
|
1670
1670
|
.toThrow('All inputs must have a sourceTransaction when using completeWithWallet')
|
|
1671
1671
|
})
|
|
@@ -1710,7 +1710,7 @@ describe('Transaction', () => {
|
|
|
1710
1710
|
const mockWallet = new MockWallet()
|
|
1711
1711
|
|
|
1712
1712
|
// Expect completeWithWallet to throw an error
|
|
1713
|
-
await expect(tx.completeWithWallet(mockWallet))
|
|
1713
|
+
await expect(tx.completeWithWallet(mockWallet as unknown as WalletInterface))
|
|
1714
1714
|
.rejects
|
|
1715
1715
|
.toThrow('All inputs must have an unlockingScript when using completeWithWallet')
|
|
1716
1716
|
})
|
|
@@ -1766,7 +1766,7 @@ describe('Transaction', () => {
|
|
|
1766
1766
|
const mockWallet = new MockWallet()
|
|
1767
1767
|
|
|
1768
1768
|
// Complete the transaction with the wallet
|
|
1769
|
-
await tx.completeWithWallet(mockWallet,
|
|
1769
|
+
await tx.completeWithWallet(mockWallet as unknown as WalletInterface,'Test with template')
|
|
1770
1770
|
|
|
1771
1771
|
// Verify that signAction was called
|
|
1772
1772
|
expect(mockWallet.signActionCalled).toBe(true)
|
|
@@ -1850,7 +1850,7 @@ describe('Transaction', () => {
|
|
|
1850
1850
|
const mockWallet = new MockWallet()
|
|
1851
1851
|
|
|
1852
1852
|
// Complete the transaction with the wallet
|
|
1853
|
-
await tx.completeWithWallet(mockWallet,
|
|
1853
|
+
await tx.completeWithWallet(mockWallet as unknown as WalletInterface,'Test with mixed inputs')
|
|
1854
1854
|
|
|
1855
1855
|
// Verify that signAction was called (because at least one template exists)
|
|
1856
1856
|
expect(mockWallet.signActionCalled).toBe(true)
|
|
@@ -1937,7 +1937,7 @@ describe('Transaction', () => {
|
|
|
1937
1937
|
const mockWallet = new MockWallet()
|
|
1938
1938
|
|
|
1939
1939
|
// Should throw error about missing script/template on input 1
|
|
1940
|
-
await expect(tx.completeWithWallet(mockWallet))
|
|
1940
|
+
await expect(tx.completeWithWallet(mockWallet as unknown as WalletInterface))
|
|
1941
1941
|
.rejects
|
|
1942
1942
|
.toThrow('Input 1 must have either an unlockingScript or unlockingScriptTemplate')
|
|
1943
1943
|
})
|
|
@@ -1964,7 +1964,7 @@ describe('Transaction', () => {
|
|
|
1964
1964
|
returnTXIDOnly: true
|
|
1965
1965
|
}
|
|
1966
1966
|
|
|
1967
|
-
await tx.completeWithWallet(mockWallet,
|
|
1967
|
+
await tx.completeWithWallet(mockWallet as unknown as WalletInterface,'Test with options', undefined, options)
|
|
1968
1968
|
|
|
1969
1969
|
// Verify options were passed to createAction
|
|
1970
1970
|
expect(mockWallet.lastCreateActionArgs?.options).toEqual(options)
|
|
@@ -1997,7 +1997,7 @@ describe('Transaction', () => {
|
|
|
1997
1997
|
randomizeOutputs: false
|
|
1998
1998
|
}
|
|
1999
1999
|
|
|
2000
|
-
await tx.completeWithWallet(mockWallet,
|
|
2000
|
+
await tx.completeWithWallet(mockWallet as unknown as WalletInterface,'Test template with options', undefined, options)
|
|
2001
2001
|
|
|
2002
2002
|
// Verify signAndProcess: false was set for createAction (required for template flow)
|
|
2003
2003
|
expect(mockWallet.lastCreateActionArgs?.options?.signAndProcess).toBe(false)
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
HttpClientRequestOptions,
|
|
4
4
|
HttpClientResponse
|
|
5
5
|
} from './HttpClient.js'
|
|
6
|
+
import { HttpsModuleLike, executeNodejsRequest } from './NodejsHttpRequestUtils.js'
|
|
6
7
|
|
|
7
8
|
/** Node Https module interface limited to options needed by ts-sdk */
|
|
8
9
|
export interface BinaryHttpsNodejs {
|
|
@@ -19,7 +20,7 @@ export interface BinaryNodejsHttpClientRequest {
|
|
|
19
20
|
|
|
20
21
|
on: (event: string, callback: (data: any) => void) => void
|
|
21
22
|
|
|
22
|
-
end: (
|
|
23
|
+
end: () => void
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -32,37 +33,12 @@ export class BinaryNodejsHttpClient implements HttpClient {
|
|
|
32
33
|
url: string,
|
|
33
34
|
requestOptions: HttpClientRequestOptions
|
|
34
35
|
): Promise<HttpClientResponse> {
|
|
35
|
-
return await
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
res.on('end', () => {
|
|
42
|
-
const ok = res.statusCode >= 200 && res.statusCode <= 299
|
|
43
|
-
const mediaType = res.headers['content-type']
|
|
44
|
-
const data =
|
|
45
|
-
body !== '' && typeof mediaType === 'string' && mediaType.startsWith('application/json')
|
|
46
|
-
? JSON.parse(body)
|
|
47
|
-
: body
|
|
48
|
-
resolve({
|
|
49
|
-
status: res.statusCode,
|
|
50
|
-
statusText: res.statusMessage,
|
|
51
|
-
ok,
|
|
52
|
-
data
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
req.on('error', (error: Error) => {
|
|
58
|
-
reject(error)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
if (requestOptions.data !== null && requestOptions.data !== undefined) {
|
|
62
|
-
req.write(Buffer.from(requestOptions.data))
|
|
63
|
-
}
|
|
64
|
-
req.end()
|
|
65
|
-
})
|
|
36
|
+
return await executeNodejsRequest(
|
|
37
|
+
this.https as unknown as HttpsModuleLike,
|
|
38
|
+
url,
|
|
39
|
+
requestOptions,
|
|
40
|
+
(data) => Buffer.from(data)
|
|
41
|
+
)
|
|
66
42
|
}
|
|
67
43
|
}
|
|
68
44
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
HttpClientRequestOptions,
|
|
4
4
|
HttpClientResponse
|
|
5
5
|
} from './HttpClient.js'
|
|
6
|
+
import { HttpsModuleLike, executeNodejsRequest } from './NodejsHttpRequestUtils.js'
|
|
6
7
|
|
|
7
8
|
/** Node Https module interface limited to options needed by ts-sdk */
|
|
8
9
|
export interface HttpsNodejs {
|
|
@@ -19,7 +20,7 @@ export interface NodejsHttpClientRequest {
|
|
|
19
20
|
|
|
20
21
|
on: (event: string, callback: (data: any) => void) => void
|
|
21
22
|
|
|
22
|
-
end: (
|
|
23
|
+
end: () => void
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -32,36 +33,11 @@ export class NodejsHttpClient implements HttpClient {
|
|
|
32
33
|
url: string,
|
|
33
34
|
requestOptions: HttpClientRequestOptions
|
|
34
35
|
): Promise<HttpClientResponse> {
|
|
35
|
-
return await
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
res.on('end', () => {
|
|
42
|
-
const ok = res.statusCode >= 200 && res.statusCode <= 299
|
|
43
|
-
const mediaType = res.headers['content-type']
|
|
44
|
-
const data =
|
|
45
|
-
body !== '' && typeof mediaType === 'string' && mediaType.startsWith('application/json')
|
|
46
|
-
? JSON.parse(body)
|
|
47
|
-
: body
|
|
48
|
-
resolve({
|
|
49
|
-
status: res.statusCode,
|
|
50
|
-
statusText: res.statusMessage,
|
|
51
|
-
ok,
|
|
52
|
-
data
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
req.on('error', (error: Error) => {
|
|
58
|
-
reject(error)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
if (requestOptions.data !== null && requestOptions.data !== undefined) {
|
|
62
|
-
req.write(JSON.stringify(requestOptions.data))
|
|
63
|
-
}
|
|
64
|
-
req.end()
|
|
65
|
-
})
|
|
36
|
+
return await executeNodejsRequest(
|
|
37
|
+
this.https as unknown as HttpsModuleLike,
|
|
38
|
+
url,
|
|
39
|
+
requestOptions,
|
|
40
|
+
(data) => JSON.stringify(data)
|
|
41
|
+
)
|
|
66
42
|
}
|
|
67
43
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HttpClientRequestOptions,
|
|
3
|
+
HttpClientResponse
|
|
4
|
+
} from './HttpClient.js'
|
|
5
|
+
|
|
6
|
+
/** Common interface for Node.js https module request objects */
|
|
7
|
+
export interface NodejsRequestLike {
|
|
8
|
+
write: (chunk: any) => void
|
|
9
|
+
on: (event: string, callback: (data: any) => void) => void
|
|
10
|
+
end: () => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Common interface for Node.js https modules */
|
|
14
|
+
export interface HttpsModuleLike {
|
|
15
|
+
request: (
|
|
16
|
+
url: string,
|
|
17
|
+
options: HttpClientRequestOptions,
|
|
18
|
+
callback: (res: any) => void
|
|
19
|
+
) => NodejsRequestLike
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Shared implementation for handling Node.js HTTP requests.
|
|
24
|
+
* Used by both NodejsHttpClient and BinaryNodejsHttpClient.
|
|
25
|
+
*
|
|
26
|
+
* @param https The Node.js https module (or compatible)
|
|
27
|
+
* @param url The URL to make the request to
|
|
28
|
+
* @param requestOptions The request configuration
|
|
29
|
+
* @param serializeData Function to serialize the request data for writing
|
|
30
|
+
*/
|
|
31
|
+
export function executeNodejsRequest(
|
|
32
|
+
https: HttpsModuleLike,
|
|
33
|
+
url: string,
|
|
34
|
+
requestOptions: HttpClientRequestOptions,
|
|
35
|
+
serializeData: (data: any) => any
|
|
36
|
+
): Promise<HttpClientResponse> {
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
const req = https.request(url, requestOptions, (res) => {
|
|
39
|
+
let body = ''
|
|
40
|
+
res.on('data', (chunk: string) => {
|
|
41
|
+
body += chunk
|
|
42
|
+
})
|
|
43
|
+
res.on('end', () => {
|
|
44
|
+
const ok = res.statusCode >= 200 && res.statusCode <= 299
|
|
45
|
+
const mediaType = res.headers['content-type']
|
|
46
|
+
const data =
|
|
47
|
+
body !== '' && typeof mediaType === 'string' && mediaType.startsWith('application/json')
|
|
48
|
+
? JSON.parse(body)
|
|
49
|
+
: body
|
|
50
|
+
resolve({
|
|
51
|
+
status: res.statusCode,
|
|
52
|
+
statusText: res.statusMessage,
|
|
53
|
+
ok,
|
|
54
|
+
data
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
req.on('error', (error: Error) => {
|
|
60
|
+
reject(error)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
if (requestOptions.data !== null && requestOptions.data !== undefined) {
|
|
64
|
+
req.write(serializeData(requestOptions.data))
|
|
65
|
+
}
|
|
66
|
+
req.end()
|
|
67
|
+
})
|
|
68
|
+
}
|