@bsv/sdk 1.6.12 → 1.6.15
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/README.md +4 -4
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js +1 -1
- package/dist/cjs/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js +1 -1
- package/dist/esm/src/transaction/broadcasters/DefaultBroadcaster.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/transaction/http/HttpClient.d.ts +2 -0
- package/dist/types/src/transaction/http/HttpClient.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/MARKDOWN_VALIDATION_GUIDE.md +175 -0
- package/docs/concepts/beef.md +8 -0
- package/docs/concepts/chain-tracking.md +12 -0
- package/docs/concepts/decentralized-identity.md +37 -0
- package/docs/concepts/fees.md +32 -0
- package/docs/concepts/identity-certificates.md +53 -1
- package/docs/concepts/index.md +15 -0
- package/docs/concepts/key-management.md +9 -0
- package/docs/concepts/script-templates.md +13 -0
- package/docs/concepts/sdk-philosophy.md +8 -0
- package/docs/concepts/signatures.md +15 -0
- package/docs/concepts/spv-verification.md +12 -0
- package/docs/concepts/transaction-encoding.md +19 -0
- package/docs/concepts/transaction-structure.md +4 -0
- package/docs/concepts/trust-model.md +16 -0
- package/docs/concepts/verification.md +31 -0
- package/docs/concepts/wallet-integration.md +6 -0
- package/docs/guides/development-wallet-setup.md +374 -0
- package/docs/guides/direct-transaction-creation.md +12 -2
- package/docs/guides/http-client-configuration.md +122 -48
- package/docs/guides/index.md +117 -9
- package/docs/guides/large-transactions.md +448 -0
- package/docs/guides/multisig-transactions.md +792 -0
- package/docs/guides/security-best-practices.md +494 -0
- package/docs/guides/transaction-batching.md +132 -0
- package/docs/guides/transaction-signing-methods.md +230 -79
- package/docs/index.md +0 -2
- package/docs/reference/configuration.md +6 -0
- package/docs/reference/debugging.md +5 -0
- package/docs/reference/errors.md +50 -0
- package/docs/reference/index.md +14 -1
- package/docs/reference/op-codes.md +20 -1
- package/docs/reference/transaction-signatures.md +2 -1
- package/docs/reference/transaction.md +9 -0
- package/docs/tutorials/advanced-transaction.md +1 -4
- package/docs/tutorials/aes-encryption.md +3 -1
- package/docs/tutorials/authfetch-tutorial.md +29 -0
- package/docs/tutorials/ecdh-key-exchange.md +2 -0
- package/docs/tutorials/elliptic-curve-fundamentals.md +3 -0
- package/docs/tutorials/error-handling.md +1 -0
- package/docs/tutorials/first-transaction-low-level.md +1 -0
- package/docs/tutorials/first-transaction.md +5 -8
- package/docs/tutorials/hashes-and-hmacs.md +5 -31
- package/docs/tutorials/identity-management.md +27 -0
- package/docs/tutorials/index.md +114 -77
- package/docs/tutorials/key-management.md +5 -3
- package/docs/tutorials/protowallet-development.md +27 -0
- package/docs/tutorials/spv-merkle-proofs.md +9 -6
- package/docs/tutorials/testnet-transactions-low-level.md +25 -18
- package/docs/tutorials/transaction-broadcasting.md +10 -7
- package/docs/tutorials/transaction-types.md +5 -4
- package/docs/tutorials/type-42.md +0 -14
- package/docs/tutorials/uhrp-storage.md +23 -3
- package/package.json +1 -1
- package/src/identity/README.md +0 -1
- package/src/primitives/__tests/SymmetricKey.test.ts +45 -0
- package/src/primitives/__tests/SymmetricKeyCompatibility.test.ts +150 -0
- package/src/transaction/__tests/Transaction.test.ts +1 -1
- package/src/transaction/broadcasters/DefaultBroadcaster.ts +1 -1
- package/src/transaction/broadcasters/__tests/ARC.test.ts +1 -1
- package/src/transaction/http/HttpClient.ts +2 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import SymmetricKey from '../SymmetricKey'
|
|
2
|
+
import PrivateKey from '../PrivateKey'
|
|
3
|
+
|
|
4
|
+
describe('Cross-SDK Compatibility Tests', () => {
|
|
5
|
+
describe('31-byte key cross-decryption', () => {
|
|
6
|
+
it('can decrypt Go SDK ciphertext with TypeScript SDK', () => {
|
|
7
|
+
// Use the same 31-byte key as Go SDK
|
|
8
|
+
const privKey = PrivateKey.fromWif('L4B2postXdaP7TiUrUBYs53Fqzheu7WhSoQVPuY8qBdoBeEwbmZx')
|
|
9
|
+
const pubKey = privKey.toPublicKey()
|
|
10
|
+
|
|
11
|
+
expect(pubKey.x).toBeTruthy()
|
|
12
|
+
const keyBytes = pubKey.x!.toArray()
|
|
13
|
+
|
|
14
|
+
// Verify this is a 31-byte key
|
|
15
|
+
expect(keyBytes.length).toBe(31)
|
|
16
|
+
|
|
17
|
+
const symKey = new SymmetricKey(keyBytes)
|
|
18
|
+
const expectedPlaintext = 'cross-sdk test message'
|
|
19
|
+
|
|
20
|
+
// Test cases: Go-generated ciphertext that TypeScript should be able to decrypt
|
|
21
|
+
const testCases = [
|
|
22
|
+
{
|
|
23
|
+
name: 'Go 31-byte ciphertext 1',
|
|
24
|
+
ciphertextHex: '7604d5bdb0eb843051d21873c871c9b1507c3de7ba222e1b407c163c2c166277df95de73be9534a2caf9d4b72157f78e5e2e69d97bc25b18ff4cfbd61a1306c02c0b8b2d165e'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Go 31-byte ciphertext 2',
|
|
28
|
+
ciphertextHex: 'ab74fa03d7b2d308f007e21fbae056cfde6e3e5fbea7032880e0482b0b5fbe8583d5221b985a8cdfdff1f70c2bb28c9a3149a34dde3b56f54ecd4728d2dd70c1212642b18bc4'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Go 31-byte ciphertext 3',
|
|
32
|
+
ciphertextHex: '6c64ae72a1371084347983568d25515ca75599f747236be6971267fa4b48e518855ce4f8380cc479bb75835641f2173b7932b93be5cd40f54cd84aaff053dbc94c3748e427af'
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
testCases.forEach(({name, ciphertextHex}) => {
|
|
37
|
+
// Convert hex to byte array
|
|
38
|
+
const ciphertext: number[] = []
|
|
39
|
+
for (let i = 0; i < ciphertextHex.length; i += 2) {
|
|
40
|
+
ciphertext.push(parseInt(ciphertextHex.slice(i, i + 2), 16))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Decrypt using TypeScript SDK
|
|
44
|
+
const decrypted = symKey.decrypt(ciphertext, 'utf8')
|
|
45
|
+
|
|
46
|
+
expect(decrypted).toBe(expectedPlaintext)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
describe('32-byte key cross-decryption', () => {
|
|
52
|
+
it('can decrypt Go SDK ciphertext with TypeScript SDK', () => {
|
|
53
|
+
// Use the same 32-byte key as Go SDK
|
|
54
|
+
const privKey = PrivateKey.fromWif('KyLGEhYicSoGchHKmVC2fUx2MRrHzWqvwBFLLT4DZB93Nv5DxVR9')
|
|
55
|
+
const pubKey = privKey.toPublicKey()
|
|
56
|
+
|
|
57
|
+
expect(pubKey.x).toBeTruthy()
|
|
58
|
+
const keyBytes = pubKey.x!.toArray()
|
|
59
|
+
|
|
60
|
+
// Verify this is a 32-byte key
|
|
61
|
+
expect(keyBytes.length).toBe(32)
|
|
62
|
+
|
|
63
|
+
const symKey = new SymmetricKey(keyBytes)
|
|
64
|
+
const expectedPlaintext = 'cross-sdk test message'
|
|
65
|
+
|
|
66
|
+
// Test cases: Go-generated ciphertext that TypeScript should be able to decrypt
|
|
67
|
+
const testCases = [
|
|
68
|
+
{
|
|
69
|
+
name: 'Go 32-byte ciphertext 1',
|
|
70
|
+
ciphertextHex: 'd7744c85ad3dafcb9fc5752ab0d04c40f87084e8a466f6b6013ebe0fc5170daab8184aaef66ab2c2733f01c0dc3de322ba3ddeea976499548bc6ec166581181f919c69aa2de5'
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'Go 32-byte ciphertext 2',
|
|
74
|
+
ciphertextHex: 'bed1fc660bb7219d05a0115bc3c8dfb063fceb07c6571e0a21af1a052988dfd8911f625ae747ae6dad4cadb872dbd1d1bdc4b78bf7817e90bc5df718d77b247805eb06773d13'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Go 32-byte ciphertext 3',
|
|
78
|
+
ciphertextHex: '7411f0e9ff2b6ebbb804614fcf11db548a92baeea9cd769e8ee11bd7853a2d055799df476655b7d30f11be17f9513a16b72b6c73f85edd4b6e7548fae68fb47252ff72ace4cf'
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
testCases.forEach(({name, ciphertextHex}) => {
|
|
83
|
+
// Convert hex to byte array
|
|
84
|
+
const ciphertext: number[] = []
|
|
85
|
+
for (let i = 0; i < ciphertextHex.length; i += 2) {
|
|
86
|
+
ciphertext.push(parseInt(ciphertextHex.slice(i, i + 2), 16))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Decrypt using TypeScript SDK
|
|
90
|
+
const decrypted = symKey.decrypt(ciphertext, 'utf8')
|
|
91
|
+
expect(decrypted).toBe(expectedPlaintext)
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('Bidirectional cross-decryption', () => {
|
|
97
|
+
it('verifies both SDKs can decrypt each others ciphertext', () => {
|
|
98
|
+
const testCases = [
|
|
99
|
+
{
|
|
100
|
+
name: '31-byte key bidirectional',
|
|
101
|
+
wif: 'L4B2postXdaP7TiUrUBYs53Fqzheu7WhSoQVPuY8qBdoBeEwbmZx',
|
|
102
|
+
expectedKeyLength: 31,
|
|
103
|
+
goCiphertext: '7604d5bdb0eb843051d21873c871c9b1507c3de7ba222e1b407c163c2c166277df95de73be9534a2caf9d4b72157f78e5e2e69d97bc25b18ff4cfbd61a1306c02c0b8b2d165e',
|
|
104
|
+
tsCiphertext: 'c374d70a4623036f1dd7b971dbeeea375630dc1da40e7068f4c4aa03487d3b19de3afb26a29173deccfbb1ece4fee6c92406b25948e6fe9cb53383057cb826d0a20269e290bd'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: '32-byte key bidirectional',
|
|
108
|
+
wif: 'KyLGEhYicSoGchHKmVC2fUx2MRrHzWqvwBFLLT4DZB93Nv5DxVR9',
|
|
109
|
+
expectedKeyLength: 32,
|
|
110
|
+
goCiphertext: 'd7744c85ad3dafcb9fc5752ab0d04c40f87084e8a466f6b6013ebe0fc5170daab8184aaef66ab2c2733f01c0dc3de322ba3ddeea976499548bc6ec166581181f919c69aa2de5',
|
|
111
|
+
tsCiphertext: '2059fc32910bef280d89c4c7edbbc587b31be22339e609fdcc23319bf458840a91ad1b2da87aea13a5dc5cb3469b41c52001070b8003863843978acbdf57755b24491581a059'
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
testCases.forEach(({name, wif, expectedKeyLength, goCiphertext, tsCiphertext}) => {
|
|
116
|
+
// Create symmetric key
|
|
117
|
+
const privKey = PrivateKey.fromWif(wif)
|
|
118
|
+
const pubKey = privKey.toPublicKey()
|
|
119
|
+
|
|
120
|
+
expect(pubKey.x).toBeTruthy()
|
|
121
|
+
const keyBytes = pubKey.x!.toArray()
|
|
122
|
+
expect(keyBytes.length).toBe(expectedKeyLength)
|
|
123
|
+
|
|
124
|
+
const symKey = new SymmetricKey(keyBytes)
|
|
125
|
+
const expectedPlaintext = 'cross-sdk test message'
|
|
126
|
+
|
|
127
|
+
// Test TypeScript decrypting Go ciphertext
|
|
128
|
+
const goCiphertextBytes: number[] = []
|
|
129
|
+
for (let i = 0; i < goCiphertext.length; i += 2) {
|
|
130
|
+
goCiphertextBytes.push(parseInt(goCiphertext.substr(i, 2), 16))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const goDecrypted = symKey.decrypt(goCiphertextBytes, 'utf8')
|
|
134
|
+
expect(goDecrypted).toBe(expectedPlaintext)
|
|
135
|
+
|
|
136
|
+
// Test TypeScript decrypting TypeScript ciphertext (sanity check)
|
|
137
|
+
const tsCiphertextBytes: number[] = []
|
|
138
|
+
for (let i = 0; i < tsCiphertext.length; i += 2) {
|
|
139
|
+
tsCiphertextBytes.push(parseInt(tsCiphertext.substr(i, 2), 16))
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const tsDecrypted = symKey.decrypt(tsCiphertextBytes, 'utf8')
|
|
143
|
+
expect(tsDecrypted).toBe(expectedPlaintext)
|
|
144
|
+
|
|
145
|
+
expect(goDecrypted).toBe(expectedPlaintext)
|
|
146
|
+
expect(tsDecrypted).toBe(expectedPlaintext)
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
})
|
|
@@ -763,7 +763,7 @@ describe('Transaction', () => {
|
|
|
763
763
|
|
|
764
764
|
expect(mockedFetch).toHaveBeenCalled()
|
|
765
765
|
const url = (mockedFetch as jest.Mock).mock.calls[0][0] as string
|
|
766
|
-
expect(url).toEqual('https://arc.
|
|
766
|
+
expect(url).toEqual('https://arc.gorillapool.io/v1/tx')
|
|
767
767
|
expect(rv).toEqual({
|
|
768
768
|
status: 'success',
|
|
769
769
|
txid: 'mocked_txid',
|
|
@@ -6,7 +6,7 @@ export function defaultBroadcaster(
|
|
|
6
6
|
config: ArcConfig = {}
|
|
7
7
|
): Broadcaster {
|
|
8
8
|
return new ARC(
|
|
9
|
-
isTestnet ? 'https://arc
|
|
9
|
+
isTestnet ? 'https://testnet.arc.gorillapool.io' : 'https://arc.gorillapool.io',
|
|
10
10
|
config
|
|
11
11
|
)
|
|
12
12
|
}
|
|
@@ -222,7 +222,7 @@ describe('ARC Broadcaster', () => {
|
|
|
222
222
|
})
|
|
223
223
|
|
|
224
224
|
// Initialize the ARC broadcaster with the mocked fetch client
|
|
225
|
-
const URL = 'https://arc.
|
|
225
|
+
const URL = 'https://arc.gorillapool.io'
|
|
226
226
|
const apiKey = 'mock_api_key' // Example API key
|
|
227
227
|
const broadcaster = new ARC(URL, {
|
|
228
228
|
apiKey,
|
|
@@ -23,6 +23,8 @@ export interface HttpClientRequestOptions<Data = any> {
|
|
|
23
23
|
headers?: Record<string, string>
|
|
24
24
|
/** An object or null to set request's body. */
|
|
25
25
|
data?: Data
|
|
26
|
+
/** An optional AbortSignal to cancel the request, including by explicit timeout. */
|
|
27
|
+
signal?: AbortSignal
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
/**
|