@autonomys/auto-consensus 0.6.1 → 0.6.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.
Files changed (3) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +547 -13
  3. package/package.json +3 -3
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Autonomys Network (autonomys.xyz)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ 1. **Attribution**: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13
+
14
+ 2. **No Warranty**: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15
+
16
+ 3. **Limitation of Liability**: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+
18
+ ---
package/README.md CHANGED
@@ -1,31 +1,565 @@
1
1
  # Autonomys Auto Consensus SDK
2
2
 
3
+ ![Autonomys Banner](https://github.com/autonomys/auto-sdk/blob/main/.github/images/autonomys-banner.webp)
4
+
5
+ [![Latest Github release](https://img.shields.io/github/v/tag/autonomys/auto-sdk.svg)](https://github.com/autonomys/auto-sdk/tags)
6
+ [![Build status of the main branch on Linux/OSX](https://img.shields.io/github/actions/workflow/status/autonomys/auto-sdk/build.yaml?branch=main&label=Linux%2FOSX%20build)](https://github.com/autonomys/auto-sdk/actions/workflows/build.yaml)
7
+ [![npm version](https://badge.fury.io/js/@autonomys%2Fauto-consensus.svg)](https://badge.fury.io/js/@autonomys%2Fauto-consensus)
8
+
3
9
  ## Overview
4
10
 
5
- The Autonomys Auto Consensus SDK provides functionalities for blockchain consensus interactions, including address management, balance retrieval, staking, and transfers.
11
+ The **Autonomys Auto Consensus SDK** (`@autonomys/auto-consensus`) offers a suite of functions for interacting with the **Autonomys Network's consensus layer**. It enables developers to:
12
+
13
+ - **Manage Accounts**: Retrieve account information and balances.
14
+ - **Handle Balances**: Check balances and total token issuance.
15
+ - **Perform Transfers**: Transfer tokens between accounts.
16
+ - **Stake and Nominate Operators**: Participate in staking operations.
17
+ - **Access Blockchain Information**: Fetch block numbers, hashes, and network timestamps.
18
+ - **Interact with Domains**: Retrieve domain-related data.
19
+
20
+ ## Features
21
+
22
+ - **Account Management**: Access detailed account information, including nonce and balance data.
23
+ - **Balance Operations**: Retrieve account balances and the total issuance of tokens in the network.
24
+ - **Token Transfers**: Transfer tokens securely between addresses.
25
+ - **Staking Functionality**: Register operators, nominate operators, and manage staking operations.
26
+ - **Blockchain Information Access**: Fetch current block numbers, block hashes, and network timestamps.
27
+ - **Domain Interactions**: Access domain registry information and staking summaries.
28
+ - **TypeScript Support**: Fully typed for enhanced developer experience.
29
+
30
+ ## Installation
31
+
32
+ Install the package via npm or yarn:
33
+
34
+ ```bash
35
+ # Using npm
36
+ npm install @autonomys/auto-consensus
37
+
38
+ # Using yarn
39
+ yarn add @autonomys/auto-consensus
40
+ ```
41
+
42
+ ## Getting Started
43
+
44
+ ### Prerequisites
45
+
46
+ - **Node.js** (version 14 or higher)
47
+ - **TypeScript** (optional, but recommended for development)
48
+ - Familiarity with async/await and promise handling in JavaScript/TypeScript.
49
+ - **@autonomys/auto-utils** package installed (as it provides utility functions and API activation).
50
+
51
+ ### Importing the SDK
52
+
53
+ You can import specific functions from the package as needed:
54
+
55
+ ```typescript
56
+ import {
57
+ account,
58
+ balance,
59
+ totalIssuance,
60
+ transfer,
61
+ registerOperator,
62
+ nominateOperator,
63
+ blockNumber,
64
+ blockHash,
65
+ networkTimestamp,
66
+ domains,
67
+ domainStakingSummary,
68
+ latestConfirmedDomainBlock,
69
+ } from '@autonomys/auto-consensus'
70
+ ```
71
+
72
+ ## Usage Examples
73
+
74
+ Below are examples demonstrating how to use the functions provided by `@autonomys/auto-consensus`.
75
+
76
+ ### 1. Account Management
77
+
78
+ #### **Retrieve Account Information**
79
+
80
+ Get detailed account information, including the nonce and balance data.
81
+
82
+ ```typescript
83
+ import { account } from '@autonomys/auto-consensus'
84
+ import { activate } from '@autonomys/auto-utils'
85
+ ;(async () => {
86
+ const api = await activate({ networkId: 'your_network_id' })
87
+ const accountData = await account(api, 'your_address')
88
+
89
+ console.log(`Nonce: ${accountData.nonce}`)
90
+ console.log(`Free Balance: ${accountData.data.free}`)
91
+ console.log(`Reserved Balance: ${accountData.data.reserved}`)
92
+
93
+ await api.disconnect()
94
+ })()
95
+ ```
96
+
97
+ **Parameters:**
98
+
99
+ - `api` (ApiPromise): Connected API instance.
100
+ - `address` (string): The account address.
101
+
102
+ **Returns:**
103
+
104
+ - An object containing:
105
+ - `nonce`: The account's transaction nonce.
106
+ - `data`: An object with balance details (`free`, `reserved`, `miscFrozen`, `feeFrozen`).
107
+
108
+ ### 2. Balance Operations
109
+
110
+ #### **Retrieve Account Balance**
111
+
112
+ Get the free balance of an account.
113
+
114
+ ```typescript
115
+ import { balance } from '@autonomys/auto-consensus'
116
+ import { activate } from '@autonomys/auto-utils'
117
+ ;(async () => {
118
+ const api = await activate({ networkId: 'your_network_id' })
119
+ const accountBalance = await balance(api, 'your_address')
120
+
121
+ console.log(`Free Balance: ${accountBalance.free}`)
122
+
123
+ await api.disconnect()
124
+ })()
125
+ ```
126
+
127
+ #### **Get Total Issuance**
128
+
129
+ Retrieve the total token issuance in the network.
130
+
131
+ ```typescript
132
+ import { totalIssuance } from '@autonomys/auto-consensus'
133
+ ;(async () => {
134
+ const total = await totalIssuance('your_network_id')
135
+
136
+ console.log(`Total Issuance: ${total.toString()}`)
137
+ })()
138
+ ```
139
+
140
+ **Parameters:**
141
+
142
+ - `networkId` (string, optional): The network ID.
143
+
144
+ **Returns:**
145
+
146
+ - A Codec representing the total issuance value.
147
+
148
+ ### 3. Transfers
149
+
150
+ #### **Transfer Tokens**
151
+
152
+ Transfer tokens from one account to another.
153
+
154
+ ```typescript
155
+ import { transfer, events } from '@autonomys/auto-consensus'
156
+ import { activate, activateWallet, signAndSendTx, disconnect } from '@autonomys/auto-utils'
157
+ ;(async () => {
158
+ const api = await activate({ networkId: 'your_network_id' })
159
+ const { accounts } = await activateWallet({
160
+ networkId: 'your_network_id',
161
+ mnemonic: 'your_mnemonic',
162
+ })
163
+
164
+ const sender = accounts[0]
165
+ const recipientAddress = 'recipient_address'
166
+ const amount = '1000000000000' // Amount in smallest units (e.g., wei)
167
+
168
+ const tx = await transfer(api, recipientAddress, amount)
169
+
170
+ // Sign and send the transaction
171
+ await signAndSendTx(sender, tx, [events.transfer])
172
+
173
+ console.log(`Transferred ${amount} tokens to ${recipientAddress}`)
174
+
175
+ await disconnect(api)
176
+ })()
177
+ ```
178
+
179
+ **Parameters:**
180
+
181
+ - `api` (ApiPromise): Connected API instance.
182
+ - `recipient` (string): Recipient's address.
183
+ - `amount` (number | string | BN): Amount to transfer.
184
+
185
+ **Returns:**
186
+
187
+ - A SubmittableExtrinsic transaction object.
188
+
189
+ ### 4. Staking Operations
190
+
191
+ #### **Register an Operator**
192
+
193
+ Register a new operator for staking.
194
+
195
+ ```typescript
196
+ import { registerOperator, events } from '@autonomys/auto-consensus'
197
+ import { activate, activateWallet, signAndSendTx } from '@autonomys/auto-utils'
198
+ ;(async () => {
199
+ const api = await activate({ networkId: 'your_network_id' })
200
+
201
+ // Sender's account (who will register the operator)
202
+ const { accounts: senderAccounts } = await activateWallet({
203
+ networkId: 'your_network_id',
204
+ mnemonic: 'sender_mnemonic',
205
+ })
206
+ const sender = senderAccounts[0]
207
+
208
+ // Operator's account
209
+ const { accounts: operatorAccounts } = await activateWallet({
210
+ networkId: 'your_network_id',
211
+ mnemonic: 'operator_mnemonic',
212
+ })
213
+ const operatorAccount = operatorAccounts[0]
214
+
215
+ const tx = await registerOperator({
216
+ api,
217
+ senderAddress: sender.address,
218
+ Operator: operatorAccount,
219
+ domainId: '0', // Domain ID where the operator will be registered
220
+ amountToStake: '1000000000000000000', // Amount in smallest units
221
+ minimumNominatorStake: '10000000000000000',
222
+ nominationTax: '5', // Percentage as a string (e.g., '5' for 5%)
223
+ })
224
+
225
+ // Sign and send the transaction
226
+ await signAndSendTx(sender, tx, [events.operatorRegistered])
227
+
228
+ console.log('Operator registered successfully')
229
+ })()
230
+ ```
231
+
232
+ **Parameters:**
233
+
234
+ - `api` (ApiPromise): Connected API instance.
235
+ - `senderAddress` (string): Address of the sender registering the operator.
236
+ - `Operator` (KeyringPair): Key pair of the operator account.
237
+ - `domainId` (string): ID of the domain.
238
+ - `amountToStake` (string): Amount to stake in smallest units.
239
+ - `minimumNominatorStake` (string): Minimum stake required from nominators.
240
+ - `nominationTax` (string): Percentage tax for nominations.
241
+
242
+ **Returns:**
243
+
244
+ - A SubmittableExtrinsic transaction object.
245
+
246
+ #### **Nominate an Operator**
247
+
248
+ Nominate an existing operator by staking tokens.
249
+
250
+ ```typescript
251
+ import { nominateOperator, events } from '@autonomys/auto-consensus'
252
+ import { activate, activateWallet, signAndSendTx } from '@autonomys/auto-utils'
253
+ ;(async () => {
254
+ const api = await activate({ networkId: 'your_network_id' })
255
+ const { accounts } = await activateWallet({
256
+ networkId: 'your_network_id',
257
+ mnemonic: 'nominator_mnemonic',
258
+ })
259
+ const nominator = accounts[0]
260
+
261
+ const operatorId = '1' // The ID of the operator to nominate
262
+ const amountToStake = '5000000000000000000' // Amount in smallest units
263
+
264
+ const tx = await nominateOperator({
265
+ api,
266
+ operatorId,
267
+ amountToStake,
268
+ })
269
+
270
+ // Sign and send the transaction
271
+ await signAndSendTx(nominator, tx, [events.operatorNominated])
272
+
273
+ console.log(`Nominated operator ${operatorId} with ${amountToStake} stake`)
274
+ })()
275
+ ```
276
+
277
+ **Parameters:**
278
+
279
+ - `api` (ApiPromise): Connected API instance.
280
+ - `operatorId` (string): ID of the operator to nominate.
281
+ - `amountToStake` (string): Amount to stake in smallest units.
282
+
283
+ **Returns:**
6
284
 
7
- ## Address Management
285
+ - A SubmittableExtrinsic transaction object.
8
286
 
9
- - `generateAddress(params: MnemonicOrURI): string`: Generates a new address.
287
+ ### 5. Blockchain Information
10
288
 
11
- ## Balances
289
+ #### **Get Block and Network Information**
12
290
 
13
- - `getBalance(address: string): Promise<Balance>`: Retrieves the balance of an address.
291
+ Retrieve the current block number, block hash, and network timestamp.
14
292
 
15
- ## Staking
293
+ ```typescript
294
+ import { blockNumber, blockHash, networkTimestamp } from '@autonomys/auto-consensus'
295
+ ;(async () => {
296
+ const currentBlockNumber = await blockNumber()
297
+ const currentBlockHash = await blockHash()
298
+ const currentTimestamp = await networkTimestamp()
299
+
300
+ console.log(`Current Block Number: ${currentBlockNumber}`)
301
+ console.log(`Current Block Hash: ${currentBlockHash}`)
302
+ console.log(`Network Timestamp: ${currentTimestamp}`)
303
+ })()
304
+ ```
305
+
306
+ **Functions:**
307
+
308
+ - `blockNumber()`: Returns the current block number as a `BigInt`.
309
+ - `blockHash()`: Returns the current block hash as a hex string.
310
+ - `networkTimestamp()`: Returns the network timestamp as a `BigInt`.
311
+
312
+ ### 6. Domain Interactions
313
+
314
+ #### **Retrieve Domains Information**
315
+
316
+ Get the list of domains registered on the network.
317
+
318
+ ```typescript
319
+ import { domains } from '@autonomys/auto-consensus'
320
+ import { activate } from '@autonomys/auto-utils'
321
+ ;(async () => {
322
+ const api = await activate({ networkId: 'your_network_id' })
323
+ const domainList = await domains(api)
324
+
325
+ domainList.forEach((domain) => {
326
+ console.log(`Domain ID: ${domain.id}`)
327
+ console.log(`Owner Address: ${domain.owner}`)
328
+ console.log(`Creation Block: ${domain.creationBlock}`)
329
+ // ...other domain properties
330
+ })
331
+
332
+ await api.disconnect()
333
+ })()
334
+ ```
335
+
336
+ #### **Get Domain Staking Summary**
337
+
338
+ Retrieve staking summaries for all domains.
339
+
340
+ ```typescript
341
+ import { domainStakingSummary } from '@autonomys/auto-consensus'
342
+ import { activate } from '@autonomys/auto-utils'
343
+ ;(async () => {
344
+ const api = await activate({ networkId: 'your_network_id' })
345
+ const stakingSummaries = await domainStakingSummary(api)
346
+
347
+ stakingSummaries.forEach((summary) => {
348
+ console.log(`Domain ID: ${summary.domainId}`)
349
+ console.log(`Total Stake: ${summary.totalStake}`)
350
+ // ...other summary properties
351
+ })
352
+
353
+ await api.disconnect()
354
+ })()
355
+ ```
356
+
357
+ #### **Get Latest Confirmed Domain Blocks**
358
+
359
+ Fetch the latest confirmed blocks for each domain.
360
+
361
+ ```typescript
362
+ import { latestConfirmedDomainBlock } from '@autonomys/auto-consensus'
363
+ import { activate } from '@autonomys/auto-utils'
364
+ ;(async () => {
365
+ const api = await activate({ networkId: 'your_network_id' })
366
+ const confirmedBlocks = await latestConfirmedDomainBlock(api)
367
+
368
+ confirmedBlocks.forEach((blockInfo) => {
369
+ console.log(`Domain ID: ${blockInfo.id}`)
370
+ console.log(`Block Number: ${blockInfo.number}`)
371
+ console.log(`Block Hash: ${blockInfo.hash}`)
372
+ // ...other block properties
373
+ })
374
+
375
+ await api.disconnect()
376
+ })()
377
+ ```
378
+
379
+ ## API Reference
380
+
381
+ ### Account Functions
382
+
383
+ #### **`account(api: Api, address: string): Promise<AccountData>`**
384
+
385
+ Retrieve detailed account information.
386
+
387
+ - **Parameters:**
388
+ - `api` (`Api`): Connected API instance.
389
+ - `address` (`string`): The account address.
390
+ - **Returns:** `Promise<AccountData>` containing `nonce` and `data` with balance details.
391
+
392
+ #### **`balance(api: Api, address: string): Promise<BalanceData>`**
393
+
394
+ Get the balance data of an account.
395
+
396
+ - **Parameters:**
397
+ - `api` (`Api`): Connected API instance.
398
+ - `address` (`string`): The account address.
399
+ - **Returns:** `Promise<BalanceData>` with balance details.
400
+
401
+ ### Balance Functions
402
+
403
+ #### **`totalIssuance(networkId?: string): Promise<Codec>`**
404
+
405
+ Retrieve the total token issuance in the network.
406
+
407
+ - **Parameters:**
408
+ - `networkId` (`string`, optional): The network ID.
409
+ - **Returns:** `Promise<Codec>` representing the total issuance.
410
+
411
+ ### Transfer Functions
412
+
413
+ #### **`transfer(api: ApiPromise, recipient: string, amount: BN | string | number): SubmittableExtrinsic`**
414
+
415
+ Create a transfer transaction.
416
+
417
+ - **Parameters:**
418
+ - `api` (`ApiPromise`): Connected API instance.
419
+ - `recipient` (`string`): Recipient's address.
420
+ - `amount` (`BN | string | number`): Amount to transfer.
421
+ - **Returns:** `SubmittableExtrinsic` transaction object.
422
+
423
+ ### Staking Functions
424
+
425
+ #### **`registerOperator(params: RegisterOperatorParams): Promise<SubmittableExtrinsic>`**
426
+
427
+ Register a new operator.
16
428
 
17
- - `stake(address: string, amount: number): Promise<void>`: Stakes an amount from an address.
429
+ - **Parameters:**
430
+ - `params` (`RegisterOperatorParams`): Parameters for operator registration.
431
+ - **Returns:** `Promise<SubmittableExtrinsic>`
18
432
 
19
- ## Transfers
433
+ #### **`nominateOperator(params: NominateOperatorParams): Promise<SubmittableExtrinsic>`**
20
434
 
21
- - `transfer(from: string, to: string, amount: number): Promise<void>`: Transfers an amount from one address to another.
435
+ Nominate an existing operator.
22
436
 
23
- ## Info
437
+ - **Parameters:**
438
+ - `params` (`NominateOperatorParams`): Parameters for nominating an operator.
439
+ - **Returns:** `Promise<SubmittableExtrinsic>`
24
440
 
25
- - `getInfo(): Promise<Info>`: Retrieves blockchain information.
441
+ ### Blockchain Information Functions
26
442
 
27
- ## Import Example
443
+ #### **`blockNumber(): Promise<bigint>`**
444
+
445
+ Get the current block number.
446
+
447
+ - **Returns:** `Promise<bigint>`
448
+
449
+ #### **`blockHash(): Promise<string>`**
450
+
451
+ Get the current block hash.
452
+
453
+ - **Returns:** `Promise<string>`
454
+
455
+ #### **`networkTimestamp(): Promise<bigint>`**
456
+
457
+ Get the network timestamp.
458
+
459
+ - **Returns:** `Promise<bigint>`
460
+
461
+ ### Domain Functions
462
+
463
+ #### **`domains(api: Api): Promise<DomainRegistry[]>`**
464
+
465
+ Retrieve the list of domains.
466
+
467
+ - **Parameters:**
468
+ - `api` (`Api`): Connected API instance.
469
+ - **Returns:** `Promise<DomainRegistry[]>`
470
+
471
+ #### **`domainStakingSummary(api: Api): Promise<DomainStakingSummary[]>`**
472
+
473
+ Get staking summaries for domains.
474
+
475
+ - **Parameters:**
476
+ - `api` (`Api`): Connected API instance.
477
+ - **Returns:** `Promise<DomainStakingSummary[]>`
478
+
479
+ #### **`latestConfirmedDomainBlock(api: Api): Promise<ConfirmedDomainBlock[]>`**
480
+
481
+ Fetch the latest confirmed domain blocks.
482
+
483
+ - **Parameters:**
484
+ - `api` (`Api`): Connected API instance.
485
+ - **Returns:** `Promise<ConfirmedDomainBlock[]>`
486
+
487
+ ## Error Handling
488
+
489
+ When using `@autonomys/auto-consensus`, make sure to handle errors, especially when interacting with network operations.
490
+
491
+ **Example:**
28
492
 
29
493
  ```typescript
30
- import { generateAddress, getBalance, stake, transfer, getInfo } from '@autonomys/auto-consensus'
494
+ import { account } from '@autonomys/auto-consensus'
495
+ import { activate } from '@autonomys/auto-utils'
496
+ ;(async () => {
497
+ try {
498
+ const api = await activate({ networkId: 'your_network_id' })
499
+ const accountData = await account(api, 'your_address')
500
+
501
+ // Use accountData...
502
+
503
+ await api.disconnect()
504
+ } catch (error) {
505
+ console.error('Error occurred:', error)
506
+ }
507
+ })()
31
508
  ```
509
+
510
+ ## Contributing
511
+
512
+ We welcome contributions to `@autonomys/auto-consensus`! Please follow these guidelines:
513
+
514
+ 1. **Fork the repository** on GitHub.
515
+
516
+ 2. **Clone your fork** locally:
517
+
518
+ ```bash
519
+ git clone https://github.com/your-username/auto-sdk.git
520
+ cd auto-sdk/packages/auto-consensus
521
+ ```
522
+
523
+ 3. **Install dependencies**:
524
+
525
+ ```bash
526
+ yarn install
527
+ ```
528
+
529
+ 4. **Make your changes** and ensure all tests pass:
530
+
531
+ ```bash
532
+ yarn test
533
+ ```
534
+
535
+ 5. **Commit your changes** with clear and descriptive messages.
536
+
537
+ 6. **Push to your fork** and **create a pull request** against the `main` branch of the original repository.
538
+
539
+ ### Code Style
540
+
541
+ - Use **TypeScript** for all code.
542
+ - Follow the existing coding conventions.
543
+ - Run `yarn lint` to ensure code style consistency.
544
+
545
+ ### Testing
546
+
547
+ - Add tests for any new features or bug fixes.
548
+ - Ensure all existing tests pass.
549
+
550
+ ## License
551
+
552
+ This project is licensed under the MIT License. See the [LICENSE](../LICENSE) file for details.
553
+
554
+ ## Additional Resources
555
+
556
+ - **Autonomys Academy**: Learn more at [Autonomys Academy](https://academy.autonomys.xyz).
557
+ - **Auto-Utils Package**: Utility functions used alongside `auto-consensus` can be found in [`@autonomys/auto-utils`](../Auto-Utils/README.md).
558
+
559
+ ## Contact
560
+
561
+ If you have any questions or need support, feel free to reach out:
562
+
563
+ - **GitHub Issues**: [GitHub Issues Page](https://github.com/autonomys/auto-sdk/issues)
564
+
565
+ We appreciate your feedback and contributions!
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autonomys/auto-consensus",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "url": "https://www.autonomys.net"
23
23
  },
24
24
  "dependencies": {
25
- "@autonomys/auto-utils": "^0.6.1"
25
+ "@autonomys/auto-utils": "^0.6.3"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/jest": "^29.5.12",
@@ -32,5 +32,5 @@
32
32
  "ts-jest": "^29.1.4",
33
33
  "typescript": "^5.4.5"
34
34
  },
35
- "gitHead": "95bcddae352dc40801bbcea12c6489bd78014f32"
35
+ "gitHead": "68a54c6f18e51cb1f32a5997c04230a6107ab631"
36
36
  }