@bsv/sdk 1.8.1 → 1.8.3

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.
@@ -4,8 +4,434 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
4
4
 
5
5
  ## Interfaces
6
6
 
7
+ | |
8
+ | --- |
9
+ | [KVContext](#interface-kvcontext) |
10
+ | [KVStoreConfig](#interface-kvstoreconfig) |
11
+ | [KVStoreEntry](#interface-kvstoreentry) |
12
+ | [KVStoreGetOptions](#interface-kvstoregetoptions) |
13
+ | [KVStoreLookupResult](#interface-kvstorelookupresult) |
14
+ | [KVStoreQuery](#interface-kvstorequery) |
15
+ | [KVStoreRemoveOptions](#interface-kvstoreremoveoptions) |
16
+ | [KVStoreSetOptions](#interface-kvstoresetoptions) |
17
+ | [KVStoreToken](#interface-kvstoretoken) |
18
+
19
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
20
+
21
+ ---
22
+
23
+ ### Interface: KVContext
24
+
25
+ ```ts
26
+ export interface KVContext {
27
+ key: string;
28
+ protocolID: WalletProtocol;
29
+ }
30
+ ```
31
+
32
+ See also: [WalletProtocol](./wallet.md#type-walletprotocol)
33
+
34
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
35
+
36
+ ---
37
+ ### Interface: KVStoreConfig
38
+
39
+ Configuration interface for GlobalKVStore operations.
40
+ Defines all options for connecting to overlay services and managing KVStore behavior.
41
+
42
+ ```ts
43
+ export interface KVStoreConfig {
44
+ overlayHost?: string;
45
+ protocolID?: WalletProtocol;
46
+ serviceName?: string;
47
+ tokenAmount?: number;
48
+ topics?: string[];
49
+ originator?: string;
50
+ wallet?: WalletInterface;
51
+ networkPreset?: "mainnet" | "testnet" | "local";
52
+ acceptDelayedBroadcast?: boolean;
53
+ tokenSetDescription?: string;
54
+ tokenUpdateDescription?: string;
55
+ tokenRemovalDescription?: string;
56
+ }
57
+ ```
58
+
59
+ See also: [WalletInterface](./wallet.md#interface-walletinterface), [WalletProtocol](./wallet.md#type-walletprotocol)
60
+
61
+ #### Property acceptDelayedBroadcast
62
+
63
+ Whether to accept delayed broadcast
64
+
65
+ ```ts
66
+ acceptDelayedBroadcast?: boolean
67
+ ```
68
+
69
+ #### Property networkPreset
70
+
71
+ Network preset for overlay services
72
+
73
+ ```ts
74
+ networkPreset?: "mainnet" | "testnet" | "local"
75
+ ```
76
+
77
+ #### Property originator
78
+
79
+ Originator
80
+
81
+ ```ts
82
+ originator?: string
83
+ ```
84
+
85
+ #### Property overlayHost
86
+
87
+ The overlay service host URL
88
+
89
+ ```ts
90
+ overlayHost?: string
91
+ ```
92
+
93
+ #### Property protocolID
94
+
95
+ Protocol ID for the KVStore protocol
96
+
97
+ ```ts
98
+ protocolID?: WalletProtocol
99
+ ```
100
+ See also: [WalletProtocol](./wallet.md#type-walletprotocol)
101
+
102
+ #### Property serviceName
103
+
104
+ Service name for overlay submission
105
+
106
+ ```ts
107
+ serviceName?: string
108
+ ```
109
+
110
+ #### Property tokenAmount
111
+
112
+ Amount of satoshis for each token
113
+
114
+ ```ts
115
+ tokenAmount?: number
116
+ ```
117
+
118
+ #### Property tokenRemovalDescription
119
+
120
+ Description for token removal
121
+
122
+ ```ts
123
+ tokenRemovalDescription?: string
124
+ ```
125
+
126
+ #### Property tokenSetDescription
127
+
128
+ Description for token set
129
+
130
+ ```ts
131
+ tokenSetDescription?: string
132
+ ```
133
+
134
+ #### Property tokenUpdateDescription
135
+
136
+ Description for token update
137
+
138
+ ```ts
139
+ tokenUpdateDescription?: string
140
+ ```
141
+
142
+ #### Property topics
143
+
144
+ Topics for overlay submission
145
+
146
+ ```ts
147
+ topics?: string[]
148
+ ```
149
+
150
+ #### Property wallet
151
+
152
+ Wallet interface for operations
153
+
154
+ ```ts
155
+ wallet?: WalletInterface
156
+ ```
157
+ See also: [WalletInterface](./wallet.md#interface-walletinterface)
158
+
159
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
160
+
161
+ ---
162
+ ### Interface: KVStoreEntry
163
+
164
+ KVStore entry returned from queries
165
+
166
+ ```ts
167
+ export interface KVStoreEntry {
168
+ key: string;
169
+ value: string;
170
+ controller: PubKeyHex;
171
+ protocolID: WalletProtocol;
172
+ token?: KVStoreToken;
173
+ history?: string[];
174
+ }
175
+ ```
176
+
177
+ See also: [KVStoreToken](./kvstore.md#interface-kvstoretoken), [PubKeyHex](./wallet.md#type-pubkeyhex), [WalletProtocol](./wallet.md#type-walletprotocol)
178
+
179
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
180
+
181
+ ---
182
+ ### Interface: KVStoreGetOptions
183
+
184
+ Options for configuring KVStore get operations (local processing)
185
+
186
+ ```ts
187
+ export interface KVStoreGetOptions {
188
+ history?: boolean;
189
+ includeToken?: boolean;
190
+ serviceName?: string;
191
+ }
192
+ ```
193
+
194
+ #### Property history
195
+
196
+ Whether to build and include history for each entry
197
+
198
+ ```ts
199
+ history?: boolean
200
+ ```
201
+
202
+ #### Property includeToken
203
+
204
+ Whether to include token transaction data in results
205
+
206
+ ```ts
207
+ includeToken?: boolean
208
+ ```
209
+
210
+ #### Property serviceName
211
+
212
+ Service name for overlay retrieval
213
+
214
+ ```ts
215
+ serviceName?: string
216
+ ```
217
+
218
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
219
+
220
+ ---
221
+ ### Interface: KVStoreLookupResult
222
+
223
+ Result structure for KVStore lookups from overlay services.
224
+ Contains the transaction output information for a found key-value pair.
225
+
226
+ ```ts
227
+ export interface KVStoreLookupResult {
228
+ txid: string;
229
+ outputIndex: number;
230
+ outputScript: string;
231
+ satoshis: number;
232
+ history?: (output: any, currentDepth: number) => Promise<boolean>;
233
+ }
234
+ ```
235
+
236
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
237
+
238
+ ---
239
+ ### Interface: KVStoreQuery
240
+
241
+ Query parameters for KVStore lookups from overlay services.
242
+ Used when searching for existing key-value pairs in the network.
243
+
244
+ ```ts
245
+ export interface KVStoreQuery {
246
+ key?: string;
247
+ controller?: PubKeyHex;
248
+ protocolID?: WalletProtocol;
249
+ limit?: number;
250
+ skip?: number;
251
+ sortOrder?: "asc" | "desc";
252
+ }
253
+ ```
254
+
255
+ See also: [PubKeyHex](./wallet.md#type-pubkeyhex), [WalletProtocol](./wallet.md#type-walletprotocol)
256
+
257
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
258
+
259
+ ---
260
+ ### Interface: KVStoreRemoveOptions
261
+
262
+ ```ts
263
+ export interface KVStoreRemoveOptions {
264
+ protocolID?: WalletProtocol;
265
+ tokenRemovalDescription?: string;
266
+ }
267
+ ```
268
+
269
+ See also: [WalletProtocol](./wallet.md#type-walletprotocol)
270
+
271
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
272
+
273
+ ---
274
+ ### Interface: KVStoreSetOptions
275
+
276
+ ```ts
277
+ export interface KVStoreSetOptions {
278
+ protocolID?: WalletProtocol;
279
+ tokenSetDescription?: string;
280
+ tokenUpdateDescription?: string;
281
+ tokenAmount?: number;
282
+ }
283
+ ```
284
+
285
+ See also: [WalletProtocol](./wallet.md#type-walletprotocol)
286
+
287
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
288
+
289
+ ---
290
+ ### Interface: KVStoreToken
291
+
292
+ Token structure containing a KVStore token from overlay services.
293
+ Wraps the transaction data and metadata for a key-value pair.
294
+
295
+ ```ts
296
+ export interface KVStoreToken {
297
+ txid: string;
298
+ outputIndex: number;
299
+ satoshis: number;
300
+ beef: Beef;
301
+ }
302
+ ```
303
+
304
+ See also: [Beef](./transaction.md#class-beef)
305
+
306
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
307
+
308
+ ---
7
309
  ## Classes
8
310
 
311
+ | |
312
+ | --- |
313
+ | [GlobalKVStore](#class-globalkvstore) |
314
+ | [LocalKVStore](#class-localkvstore) |
315
+
316
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
317
+
318
+ ---
319
+
320
+ ### Class: GlobalKVStore
321
+
322
+ Implements a global key-value storage system which uses an overlay service to track key-value pairs.
323
+ Each key-value pair is represented by a PushDrop token output.
324
+ Allows getting, setting, and removing key-value pairs with optional fetching by protocolID and history tracking.
325
+
326
+ ```ts
327
+ export class GlobalKVStore {
328
+ constructor(config: KVStoreConfig = {})
329
+ async get(query: KVStoreQuery, options: KVStoreGetOptions = {}): Promise<KVStoreEntry | KVStoreEntry[] | undefined>
330
+ async set(key: string, value: string, options: KVStoreSetOptions = {}): Promise<OutpointString>
331
+ async remove(key: string, outputs?: CreateActionOutput[], options: KVStoreRemoveOptions = {}): Promise<HexString>
332
+ }
333
+ ```
334
+
335
+ See also: [CreateActionOutput](./wallet.md#interface-createactionoutput), [HexString](./wallet.md#type-hexstring), [KVStoreConfig](./kvstore.md#interface-kvstoreconfig), [KVStoreEntry](./kvstore.md#interface-kvstoreentry), [KVStoreGetOptions](./kvstore.md#interface-kvstoregetoptions), [KVStoreQuery](./kvstore.md#interface-kvstorequery), [KVStoreRemoveOptions](./kvstore.md#interface-kvstoreremoveoptions), [KVStoreSetOptions](./kvstore.md#interface-kvstoresetoptions), [OutpointString](./wallet.md#type-outpointstring)
336
+
337
+ #### Constructor
338
+
339
+ Creates an instance of the GlobalKVStore.
340
+
341
+ ```ts
342
+ constructor(config: KVStoreConfig = {})
343
+ ```
344
+ See also: [KVStoreConfig](./kvstore.md#interface-kvstoreconfig)
345
+
346
+ Argument Details
347
+
348
+ + **config**
349
+ + Configuration options for the KVStore. Defaults to empty object.
350
+ + **config.wallet**
351
+ + Wallet to use for operations. Defaults to WalletClient.
352
+
353
+ Throws
354
+
355
+ If the configuration contains invalid parameters.
356
+
357
+ #### Method get
358
+
359
+ Retrieves data from the KVStore.
360
+ Can query by key+controller (single result), protocolID, controller, or key (multiple results).
361
+
362
+ ```ts
363
+ async get(query: KVStoreQuery, options: KVStoreGetOptions = {}): Promise<KVStoreEntry | KVStoreEntry[] | undefined>
364
+ ```
365
+ See also: [KVStoreEntry](./kvstore.md#interface-kvstoreentry), [KVStoreGetOptions](./kvstore.md#interface-kvstoregetoptions), [KVStoreQuery](./kvstore.md#interface-kvstorequery)
366
+
367
+ Returns
368
+
369
+ Single entry for key+controller queries, array for all other queries
370
+
371
+ Argument Details
372
+
373
+ + **query**
374
+ + Query parameters sent to overlay
375
+ + **options**
376
+ + Configuration options for the get operation
377
+
378
+ #### Method remove
379
+
380
+ Removes the key-value pair associated with the given key from the overlay service.
381
+
382
+ ```ts
383
+ async remove(key: string, outputs?: CreateActionOutput[], options: KVStoreRemoveOptions = {}): Promise<HexString>
384
+ ```
385
+ See also: [CreateActionOutput](./wallet.md#interface-createactionoutput), [HexString](./wallet.md#type-hexstring), [KVStoreRemoveOptions](./kvstore.md#interface-kvstoreremoveoptions)
386
+
387
+ Returns
388
+
389
+ A promise that resolves to the txid of the removal transaction if successful.
390
+
391
+ Argument Details
392
+
393
+ + **key**
394
+ + The key to remove.
395
+ + **outputs**
396
+ + Additional outputs to include in the removal transaction.
397
+ + **options**
398
+ + Optional parameters for the removal operation.
399
+
400
+ Throws
401
+
402
+ If the key is invalid.
403
+
404
+ If the key does not exist in the store.
405
+
406
+ If the overlay service is unreachable or the transaction fails.
407
+
408
+ If there are existing tokens that cannot be unlocked.
409
+
410
+ #### Method set
411
+
412
+ Sets a key-value pair. The current user (wallet identity) becomes the controller.
413
+
414
+ ```ts
415
+ async set(key: string, value: string, options: KVStoreSetOptions = {}): Promise<OutpointString>
416
+ ```
417
+ See also: [KVStoreSetOptions](./kvstore.md#interface-kvstoresetoptions), [OutpointString](./wallet.md#type-outpointstring)
418
+
419
+ Returns
420
+
421
+ The outpoint of the created token
422
+
423
+ Argument Details
424
+
425
+ + **key**
426
+ + The key to set (user computes this however they want)
427
+ + **value**
428
+ + The value to store
429
+ + **options**
430
+ + Configuration options for the set operation
431
+
432
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
433
+
434
+ ---
9
435
  ### Class: LocalKVStore
10
436
 
11
437
  Implements a key-value storage system backed by transaction outputs managed by a wallet.
@@ -134,3 +560,62 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
134
560
 
135
561
  ## Variables
136
562
 
563
+ | |
564
+ | --- |
565
+ | [kvProtocol](#variable-kvprotocol) |
566
+ | [kvStoreInterpreter](#variable-kvstoreinterpreter) |
567
+
568
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
569
+
570
+ ---
571
+
572
+ ### Variable: kvProtocol
573
+
574
+ ```ts
575
+ kvProtocol = {
576
+ protocolID: 0,
577
+ key: 1,
578
+ value: 2,
579
+ controller: 3,
580
+ signature: 4
581
+ }
582
+ ```
583
+
584
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
585
+
586
+ ---
587
+ ### Variable: kvStoreInterpreter
588
+
589
+ ```ts
590
+ kvStoreInterpreter: InterpreterFunction<string, KVContext> = async (transaction: Transaction, outputIndex: number, ctx?: KVContext): Promise<string | undefined> => {
591
+ try {
592
+ const output = transaction.outputs[outputIndex];
593
+ if (output == null || output.lockingScript == null)
594
+ return undefined;
595
+ if (ctx == null || ctx.key == null)
596
+ return undefined;
597
+ const decoded = PushDrop.decode(output.lockingScript);
598
+ if (decoded.fields.length !== Object.keys(kvProtocol).length)
599
+ return undefined;
600
+ const key = Utils.toUTF8(decoded.fields[kvProtocol.key]);
601
+ const protocolID = Utils.toUTF8(decoded.fields[kvProtocol.protocolID]);
602
+ if (key !== ctx.key || protocolID !== JSON.stringify(ctx.protocolID))
603
+ return undefined;
604
+ try {
605
+ return Utils.toUTF8(decoded.fields[kvProtocol.value]);
606
+ }
607
+ catch {
608
+ return undefined;
609
+ }
610
+ }
611
+ catch {
612
+ return undefined;
613
+ }
614
+ }
615
+ ```
616
+
617
+ See also: [KVContext](./kvstore.md#interface-kvcontext), [PushDrop](./script.md#class-pushdrop), [Transaction](./transaction.md#class-transaction), [kvProtocol](./kvstore.md#variable-kvprotocol), [toUTF8](./primitives.md#variable-toutf8)
618
+
619
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
620
+
621
+ ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.8.1",
3
+ "version": "1.8.3",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -1 +1,2 @@
1
1
  export { default as LocalKVStore } from './LocalKVStore.js'
2
+ export { default as GlobalKVStore } from './GlobalKVStore.js'
@@ -1,6 +1,25 @@
1
+ /**
2
+ * Random number generator that works across modern JavaScript environments.
3
+ *
4
+ * This implementation uses the Web Crypto API which is available in:
5
+ * - Node.js 6+ via require('crypto').randomBytes()
6
+ * - Node.js 18+ via globalThis.crypto
7
+ * - Modern browsers via globalThis.crypto, self.crypto, or window.crypto
8
+ * - Web Workers and Service Workers via self.crypto
9
+ * - Deno and Bun via globalThis.crypto
10
+ * - React Native (requires react-native-get-random-values polyfill)
11
+ *
12
+ * @throws {Error} If no secure random number generator is available
13
+ */
1
14
  class Rand {
2
15
  _rand: (n: number) => number[] // ✅ Explicit function type
3
16
 
17
+ getRandomValues (obj: any, n: number): number[] {
18
+ const arr = new Uint8Array(n)
19
+ obj.crypto.getRandomValues(arr)
20
+ return Array.from(arr)
21
+ }
22
+
4
23
  constructor () {
5
24
  const noRand = (): never => {
6
25
  throw new Error(
@@ -10,29 +29,79 @@ class Rand {
10
29
 
11
30
  this._rand = noRand // Assign the function
12
31
 
13
- if (typeof self === 'object') {
14
- /* eslint-disable-next-line */
15
- if (self.crypto?.getRandomValues) {
16
- this._rand = (n) => {
17
- const arr = new Uint8Array(n)
18
- /* eslint-disable-next-line */
19
- self.crypto.getRandomValues(arr);
20
- return [...arr]
21
- }
22
- } /* if (typeof window === 'object') */ else {
23
- this._rand = noRand
32
+ // Try globalThis.crypto (works in Node.js 18+, modern browsers, and Deno)
33
+ if (typeof globalThis !== 'undefined' && typeof (globalThis as any).crypto?.getRandomValues === 'function') {
34
+ this._rand = (n) => {
35
+ /* eslint-disable-next-line */
36
+ return this.getRandomValues(globalThis as any, n)
24
37
  }
25
- } else {
38
+ return
39
+ }
40
+
41
+ // Node.js fallback for versions < 18
42
+ if (typeof process !== 'undefined' && process.release?.name === 'node') {
26
43
  try {
27
- /* eslint-disable-next-line */
28
- const crypto = require("crypto");
44
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
45
+ const crypto = require('crypto')
29
46
  if (typeof crypto.randomBytes === 'function') {
30
- this._rand = (n: number) => [...crypto.randomBytes(n)]
47
+ this._rand = (n) => {
48
+ return Array.from(crypto.randomBytes(n))
49
+ }
50
+ return
31
51
  }
32
- } catch {
33
- this._rand = noRand
52
+ } catch (e) {
53
+ // crypto module not available, continue to other checks
34
54
  }
35
55
  }
56
+
57
+ // Try self.crypto (Web Workers and Service Workers)
58
+ if (typeof self !== 'undefined' && typeof self.crypto?.getRandomValues === 'function') {
59
+ this._rand = (n) => {
60
+ /* eslint-disable-next-line */
61
+ return this.getRandomValues(self as any, n)
62
+ }
63
+ return
64
+ }
65
+
66
+ // Try window.crypto (browsers)
67
+ if (typeof window !== 'undefined' && typeof (window as any).crypto?.getRandomValues === 'function') {
68
+ this._rand = (n) => {
69
+ /* eslint-disable-next-line */
70
+ return this.getRandomValues(window as any, n)
71
+ }
72
+ return
73
+ }
74
+
75
+ // React Native support - try to load polyfill
76
+ if (typeof navigator !== 'undefined' && (navigator as any).product === 'ReactNative') {
77
+ try {
78
+ // Try to require the polyfill - this will populate globalThis.crypto
79
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
80
+ require('react-native-get-random-values')
81
+
82
+ if (typeof (globalThis as any).crypto?.getRandomValues === 'function') {
83
+ this._rand = (n) => {
84
+ /* eslint-disable-next-line */
85
+ return this.getRandomValues(globalThis as any, n)
86
+ }
87
+ return
88
+ }
89
+ } catch (e) {
90
+ // Polyfill not available - provide helpful error
91
+ this._rand = (): never => {
92
+ throw new Error(
93
+ 'React Native detected but crypto is not available. ' +
94
+ 'Please install and import "react-native-get-random-values" at the top of your entry file:\n' +
95
+ 'npm install react-native-get-random-values\n' +
96
+ 'Then add: import "react-native-get-random-values" to your index.js/App.js'
97
+ )
98
+ }
99
+ return
100
+ }
101
+ }
102
+
103
+ // No crypto available
104
+ this._rand = noRand
36
105
  }
37
106
 
38
107
  generate (len: number): number[] {
@@ -11,4 +11,25 @@ describe('Random', () => {
11
11
  // I haven't seen it fail yet. If you see it fail, please let me know.
12
12
  expect(Random(32)).not.toEqual(Random(32))
13
13
  })
14
+ it('Produces values in valid byte range (0-255)', () => {
15
+ const bytes = Random(100)
16
+ bytes.forEach(byte => {
17
+ expect(byte).toBeGreaterThanOrEqual(0)
18
+ expect(byte).toBeLessThanOrEqual(255)
19
+ })
20
+ })
21
+ it('Works with various lengths including edge cases', () => {
22
+ expect(Random(1).length).toBe(1)
23
+ expect(Random(16).length).toBe(16)
24
+ expect(Random(32).length).toBe(32)
25
+ expect(Random(64).length).toBe(64)
26
+ expect(Random(256).length).toBe(256)
27
+ })
28
+ it('Returns an array of numbers', () => {
29
+ const bytes = Random(10)
30
+ expect(Array.isArray(bytes)).toBe(true)
31
+ bytes.forEach(byte => {
32
+ expect(typeof byte).toBe('number')
33
+ })
34
+ })
14
35
  })