qvtx-developer-kit 1.0.0 → 1.2.0

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 (49) hide show
  1. package/.env.example +108 -0
  2. package/README.md +0 -0
  3. package/abis/QVTXBridge.json +273 -0
  4. package/abis/QVTXDirectPurchase.json +621 -0
  5. package/abis/QVTXGovernance.json +267 -0
  6. package/abis/QVTXNFT.json +370 -0
  7. package/abis/QVTXRewards.json +155 -0
  8. package/abis/QVTXToken.json +311 -0
  9. package/abis/QVTXVesting.json +216 -0
  10. package/abis/index.js +16 -0
  11. package/bin/qvtx-developer-cli.js +99 -0
  12. package/config/index.js +108 -0
  13. package/config/networks.js +247 -0
  14. package/examples/basic-usage.js +39 -0
  15. package/examples/bridge-example.js +123 -0
  16. package/examples/direct-purchase.js +300 -0
  17. package/examples/governance-example.js +140 -0
  18. package/examples/nft-example.js +141 -0
  19. package/examples/staking-example.js +96 -0
  20. package/index.js +145 -0
  21. package/languages/blockchain_ai_sdk.js +0 -0
  22. package/languages/node_sdk.js +0 -0
  23. package/languages/solana_sdk.js +383 -0
  24. package/package.json +30 -3
  25. package/purchase/index.js +567 -0
  26. package/rewards/index.js +71 -0
  27. package/smart-contracts/QVTXBridge.sol +305 -0
  28. package/smart-contracts/QVTXDirectPurchase.sol +543 -0
  29. package/smart-contracts/QVTXGovernance.sol +325 -0
  30. package/smart-contracts/QVTXNFT.sol +338 -0
  31. package/smart-contracts/QVTXRewards.sol +102 -0
  32. package/smart-contracts/QVTXToken.sol +227 -0
  33. package/smart-contracts/QVTXVesting.sol +411 -0
  34. package/smart-contracts/interfaces/IERC20.sol +14 -0
  35. package/smart-contracts/interfaces/IERC20Metadata.sol +8 -0
  36. package/smart-contracts/interfaces/IERC721.sol +18 -0
  37. package/smart-contracts/interfaces/IERC721Metadata.sol +8 -0
  38. package/smart-contracts/interfaces/IERC721Receiver.sol +11 -0
  39. package/storage/index.js +112 -0
  40. package/templates/contract/ERC20Token.sol +116 -0
  41. package/templates/dapp/index.html +93 -0
  42. package/test/index.js +182 -0
  43. package/tools/build-tool.js +63 -0
  44. package/tools/create-template.js +116 -0
  45. package/tools/deploy-tool.js +55 -0
  46. package/tools/generate-docs.js +149 -0
  47. package/tools/init-project.js +138 -0
  48. package/tools/run-tests.js +64 -0
  49. package/types/index.d.ts +386 -0
@@ -0,0 +1,411 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ /**
5
+ * @title QVTX Vesting
6
+ * @dev Token vesting contract for team, advisors, and investors
7
+ * @author QuantVestrix Tech Team (07-Tech)
8
+ */
9
+
10
+ interface IQVTXToken {
11
+ function transfer(address to, uint256 amount) external returns (bool);
12
+ function transferFrom(address from, address to, uint256 amount) external returns (bool);
13
+ function balanceOf(address account) external view returns (uint256);
14
+ }
15
+
16
+ contract QVTXVesting {
17
+ IQVTXToken public qvtxToken;
18
+ address public owner;
19
+
20
+ struct VestingSchedule {
21
+ uint256 id;
22
+ address beneficiary;
23
+ uint256 totalAmount;
24
+ uint256 releasedAmount;
25
+ uint256 startTime;
26
+ uint256 cliffDuration;
27
+ uint256 vestingDuration;
28
+ uint256 slicePeriod;
29
+ bool revocable;
30
+ bool revoked;
31
+ VestingType vestingType;
32
+ }
33
+
34
+ enum VestingType {
35
+ Team,
36
+ Advisor,
37
+ Investor,
38
+ Partnership,
39
+ Community,
40
+ Custom
41
+ }
42
+
43
+ // Storage
44
+ uint256 public scheduleCount;
45
+ mapping(uint256 => VestingSchedule) public vestingSchedules;
46
+ mapping(address => uint256[]) public beneficiarySchedules;
47
+
48
+ uint256 public totalVested;
49
+ uint256 public totalReleased;
50
+
51
+ // Preset vesting configurations
52
+ mapping(VestingType => VestingConfig) public presetConfigs;
53
+
54
+ struct VestingConfig {
55
+ uint256 cliffDuration;
56
+ uint256 vestingDuration;
57
+ uint256 slicePeriod;
58
+ bool revocable;
59
+ }
60
+
61
+ // Events
62
+ event VestingScheduleCreated(
63
+ uint256 indexed scheduleId,
64
+ address indexed beneficiary,
65
+ uint256 amount,
66
+ VestingType vestingType
67
+ );
68
+ event TokensReleased(uint256 indexed scheduleId, address indexed beneficiary, uint256 amount);
69
+ event VestingRevoked(uint256 indexed scheduleId, uint256 refundAmount);
70
+ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
71
+
72
+ modifier onlyOwner() {
73
+ require(msg.sender == owner, "Vesting: not owner");
74
+ _;
75
+ }
76
+
77
+ modifier scheduleExists(uint256 scheduleId) {
78
+ require(scheduleId > 0 && scheduleId <= scheduleCount, "Vesting: invalid schedule");
79
+ _;
80
+ }
81
+
82
+ constructor(address _qvtxToken) {
83
+ qvtxToken = IQVTXToken(_qvtxToken);
84
+ owner = msg.sender;
85
+
86
+ // Initialize preset vesting configurations
87
+ // Team: 1 year cliff, 4 year vesting, monthly releases
88
+ presetConfigs[VestingType.Team] = VestingConfig({
89
+ cliffDuration: 365 days,
90
+ vestingDuration: 4 * 365 days,
91
+ slicePeriod: 30 days,
92
+ revocable: true
93
+ });
94
+
95
+ // Advisors: 6 month cliff, 2 year vesting, monthly releases
96
+ presetConfigs[VestingType.Advisor] = VestingConfig({
97
+ cliffDuration: 180 days,
98
+ vestingDuration: 2 * 365 days,
99
+ slicePeriod: 30 days,
100
+ revocable: true
101
+ });
102
+
103
+ // Investors: 3 month cliff, 18 month vesting, monthly releases
104
+ presetConfigs[VestingType.Investor] = VestingConfig({
105
+ cliffDuration: 90 days,
106
+ vestingDuration: 18 * 30 days,
107
+ slicePeriod: 30 days,
108
+ revocable: false
109
+ });
110
+
111
+ // Partnership: No cliff, 1 year vesting, quarterly releases
112
+ presetConfigs[VestingType.Partnership] = VestingConfig({
113
+ cliffDuration: 0,
114
+ vestingDuration: 365 days,
115
+ slicePeriod: 90 days,
116
+ revocable: false
117
+ });
118
+
119
+ // Community: No cliff, 6 month vesting, weekly releases
120
+ presetConfigs[VestingType.Community] = VestingConfig({
121
+ cliffDuration: 0,
122
+ vestingDuration: 180 days,
123
+ slicePeriod: 7 days,
124
+ revocable: false
125
+ });
126
+ }
127
+
128
+ // Create vesting schedule with preset config
129
+ function createVestingSchedule(
130
+ address beneficiary,
131
+ uint256 amount,
132
+ VestingType vestingType
133
+ ) external onlyOwner returns (uint256) {
134
+ require(beneficiary != address(0), "Vesting: zero address");
135
+ require(amount > 0, "Vesting: zero amount");
136
+
137
+ VestingConfig memory config = presetConfigs[vestingType];
138
+
139
+ return _createSchedule(
140
+ beneficiary,
141
+ amount,
142
+ block.timestamp,
143
+ config.cliffDuration,
144
+ config.vestingDuration,
145
+ config.slicePeriod,
146
+ config.revocable,
147
+ vestingType
148
+ );
149
+ }
150
+
151
+ // Create custom vesting schedule
152
+ function createCustomVestingSchedule(
153
+ address beneficiary,
154
+ uint256 amount,
155
+ uint256 startTime,
156
+ uint256 cliffDuration,
157
+ uint256 vestingDuration,
158
+ uint256 slicePeriod,
159
+ bool revocable
160
+ ) external onlyOwner returns (uint256) {
161
+ require(beneficiary != address(0), "Vesting: zero address");
162
+ require(amount > 0, "Vesting: zero amount");
163
+ require(vestingDuration > 0, "Vesting: zero duration");
164
+ require(slicePeriod > 0, "Vesting: zero slice period");
165
+ require(vestingDuration >= cliffDuration, "Vesting: cliff > duration");
166
+
167
+ return _createSchedule(
168
+ beneficiary,
169
+ amount,
170
+ startTime > 0 ? startTime : block.timestamp,
171
+ cliffDuration,
172
+ vestingDuration,
173
+ slicePeriod,
174
+ revocable,
175
+ VestingType.Custom
176
+ );
177
+ }
178
+
179
+ function _createSchedule(
180
+ address beneficiary,
181
+ uint256 amount,
182
+ uint256 startTime,
183
+ uint256 cliffDuration,
184
+ uint256 vestingDuration,
185
+ uint256 slicePeriod,
186
+ bool revocable,
187
+ VestingType vestingType
188
+ ) internal returns (uint256) {
189
+ // Transfer tokens to this contract
190
+ require(
191
+ qvtxToken.transferFrom(msg.sender, address(this), amount),
192
+ "Vesting: transfer failed"
193
+ );
194
+
195
+ scheduleCount++;
196
+ uint256 scheduleId = scheduleCount;
197
+
198
+ vestingSchedules[scheduleId] = VestingSchedule({
199
+ id: scheduleId,
200
+ beneficiary: beneficiary,
201
+ totalAmount: amount,
202
+ releasedAmount: 0,
203
+ startTime: startTime,
204
+ cliffDuration: cliffDuration,
205
+ vestingDuration: vestingDuration,
206
+ slicePeriod: slicePeriod,
207
+ revocable: revocable,
208
+ revoked: false,
209
+ vestingType: vestingType
210
+ });
211
+
212
+ beneficiarySchedules[beneficiary].push(scheduleId);
213
+ totalVested += amount;
214
+
215
+ emit VestingScheduleCreated(scheduleId, beneficiary, amount, vestingType);
216
+
217
+ return scheduleId;
218
+ }
219
+
220
+ // Batch create vesting schedules
221
+ function batchCreateVestingSchedules(
222
+ address[] calldata beneficiaries,
223
+ uint256[] calldata amounts,
224
+ VestingType vestingType
225
+ ) external onlyOwner returns (uint256[] memory) {
226
+ require(beneficiaries.length == amounts.length, "Vesting: length mismatch");
227
+ require(beneficiaries.length > 0, "Vesting: empty arrays");
228
+
229
+ uint256[] memory scheduleIds = new uint256[](beneficiaries.length);
230
+
231
+ for (uint256 i = 0; i < beneficiaries.length; i++) {
232
+ VestingConfig memory config = presetConfigs[vestingType];
233
+ scheduleIds[i] = _createSchedule(
234
+ beneficiaries[i],
235
+ amounts[i],
236
+ block.timestamp,
237
+ config.cliffDuration,
238
+ config.vestingDuration,
239
+ config.slicePeriod,
240
+ config.revocable,
241
+ vestingType
242
+ );
243
+ }
244
+
245
+ return scheduleIds;
246
+ }
247
+
248
+ // Release vested tokens
249
+ function release(uint256 scheduleId) external scheduleExists(scheduleId) {
250
+ VestingSchedule storage schedule = vestingSchedules[scheduleId];
251
+ require(!schedule.revoked, "Vesting: schedule revoked");
252
+ require(msg.sender == schedule.beneficiary, "Vesting: not beneficiary");
253
+
254
+ uint256 releasable = _computeReleasableAmount(schedule);
255
+ require(releasable > 0, "Vesting: nothing to release");
256
+
257
+ schedule.releasedAmount += releasable;
258
+ totalReleased += releasable;
259
+
260
+ require(
261
+ qvtxToken.transfer(schedule.beneficiary, releasable),
262
+ "Vesting: transfer failed"
263
+ );
264
+
265
+ emit TokensReleased(scheduleId, schedule.beneficiary, releasable);
266
+ }
267
+
268
+ // Release all vested tokens for beneficiary
269
+ function releaseAll() external {
270
+ uint256[] memory scheduleIds = beneficiarySchedules[msg.sender];
271
+ require(scheduleIds.length > 0, "Vesting: no schedules");
272
+
273
+ uint256 totalReleasable = 0;
274
+
275
+ for (uint256 i = 0; i < scheduleIds.length; i++) {
276
+ VestingSchedule storage schedule = vestingSchedules[scheduleIds[i]];
277
+ if (!schedule.revoked) {
278
+ uint256 releasable = _computeReleasableAmount(schedule);
279
+ if (releasable > 0) {
280
+ schedule.releasedAmount += releasable;
281
+ totalReleasable += releasable;
282
+ emit TokensReleased(scheduleIds[i], msg.sender, releasable);
283
+ }
284
+ }
285
+ }
286
+
287
+ require(totalReleasable > 0, "Vesting: nothing to release");
288
+ totalReleased += totalReleasable;
289
+
290
+ require(
291
+ qvtxToken.transfer(msg.sender, totalReleasable),
292
+ "Vesting: transfer failed"
293
+ );
294
+ }
295
+
296
+ // Revoke vesting schedule
297
+ function revoke(uint256 scheduleId) external onlyOwner scheduleExists(scheduleId) {
298
+ VestingSchedule storage schedule = vestingSchedules[scheduleId];
299
+ require(schedule.revocable, "Vesting: not revocable");
300
+ require(!schedule.revoked, "Vesting: already revoked");
301
+
302
+ // Release any vested tokens first
303
+ uint256 releasable = _computeReleasableAmount(schedule);
304
+ if (releasable > 0) {
305
+ schedule.releasedAmount += releasable;
306
+ totalReleased += releasable;
307
+ qvtxToken.transfer(schedule.beneficiary, releasable);
308
+ emit TokensReleased(scheduleId, schedule.beneficiary, releasable);
309
+ }
310
+
311
+ // Calculate refund
312
+ uint256 refundAmount = schedule.totalAmount - schedule.releasedAmount;
313
+ schedule.revoked = true;
314
+
315
+ if (refundAmount > 0) {
316
+ totalVested -= refundAmount;
317
+ qvtxToken.transfer(owner, refundAmount);
318
+ }
319
+
320
+ emit VestingRevoked(scheduleId, refundAmount);
321
+ }
322
+
323
+ // Compute releasable amount
324
+ function _computeReleasableAmount(VestingSchedule storage schedule) internal view returns (uint256) {
325
+ uint256 vestedAmount = _computeVestedAmount(schedule);
326
+ return vestedAmount - schedule.releasedAmount;
327
+ }
328
+
329
+ // Compute vested amount
330
+ function _computeVestedAmount(VestingSchedule storage schedule) internal view returns (uint256) {
331
+ if (block.timestamp < schedule.startTime + schedule.cliffDuration) {
332
+ return 0;
333
+ }
334
+
335
+ uint256 timeFromStart = block.timestamp - schedule.startTime;
336
+
337
+ if (timeFromStart >= schedule.vestingDuration) {
338
+ return schedule.totalAmount;
339
+ }
340
+
341
+ // Calculate vested amount based on slice periods
342
+ uint256 vestedSlices = timeFromStart / schedule.slicePeriod;
343
+ uint256 totalSlices = schedule.vestingDuration / schedule.slicePeriod;
344
+
345
+ return (schedule.totalAmount * vestedSlices) / totalSlices;
346
+ }
347
+
348
+ // View functions
349
+ function getVestingSchedule(uint256 scheduleId) external view returns (VestingSchedule memory) {
350
+ return vestingSchedules[scheduleId];
351
+ }
352
+
353
+ function getBeneficiarySchedules(address beneficiary) external view returns (uint256[] memory) {
354
+ return beneficiarySchedules[beneficiary];
355
+ }
356
+
357
+ function getReleasableAmount(uint256 scheduleId) external view scheduleExists(scheduleId) returns (uint256) {
358
+ VestingSchedule storage schedule = vestingSchedules[scheduleId];
359
+ if (schedule.revoked) return 0;
360
+ return _computeReleasableAmount(schedule);
361
+ }
362
+
363
+ function getVestedAmount(uint256 scheduleId) external view scheduleExists(scheduleId) returns (uint256) {
364
+ return _computeVestedAmount(vestingSchedules[scheduleId]);
365
+ }
366
+
367
+ function getTotalReleasable(address beneficiary) external view returns (uint256) {
368
+ uint256[] memory scheduleIds = beneficiarySchedules[beneficiary];
369
+ uint256 total = 0;
370
+
371
+ for (uint256 i = 0; i < scheduleIds.length; i++) {
372
+ VestingSchedule storage schedule = vestingSchedules[scheduleIds[i]];
373
+ if (!schedule.revoked) {
374
+ total += _computeReleasableAmount(schedule);
375
+ }
376
+ }
377
+
378
+ return total;
379
+ }
380
+
381
+ // Admin functions
382
+ function updatePresetConfig(
383
+ VestingType vestingType,
384
+ uint256 cliffDuration,
385
+ uint256 vestingDuration,
386
+ uint256 slicePeriod,
387
+ bool revocable
388
+ ) external onlyOwner {
389
+ presetConfigs[vestingType] = VestingConfig({
390
+ cliffDuration: cliffDuration,
391
+ vestingDuration: vestingDuration,
392
+ slicePeriod: slicePeriod,
393
+ revocable: revocable
394
+ });
395
+ }
396
+
397
+ function transferOwnership(address newOwner) external onlyOwner {
398
+ require(newOwner != address(0), "Vesting: zero address");
399
+ emit OwnershipTransferred(owner, newOwner);
400
+ owner = newOwner;
401
+ }
402
+
403
+ // Emergency withdraw (only unvested tokens)
404
+ function emergencyWithdraw() external onlyOwner {
405
+ uint256 balance = qvtxToken.balanceOf(address(this));
406
+ uint256 unvested = balance - (totalVested - totalReleased);
407
+ if (unvested > 0) {
408
+ qvtxToken.transfer(owner, unvested);
409
+ }
410
+ }
411
+ }
@@ -0,0 +1,14 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ interface IERC20 {
5
+ event Transfer(address indexed from, address indexed to, uint256 value);
6
+ event Approval(address indexed owner, address indexed spender, uint256 value);
7
+
8
+ function totalSupply() external view returns (uint256);
9
+ function balanceOf(address account) external view returns (uint256);
10
+ function transfer(address to, uint256 amount) external returns (bool);
11
+ function allowance(address owner, address spender) external view returns (uint256);
12
+ function approve(address spender, uint256 amount) external returns (bool);
13
+ function transferFrom(address from, address to, uint256 amount) external returns (bool);
14
+ }
@@ -0,0 +1,8 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ interface IERC20Metadata {
5
+ function name() external view returns (string memory);
6
+ function symbol() external view returns (string memory);
7
+ function decimals() external view returns (uint8);
8
+ }
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ interface IERC721 {
5
+ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
6
+ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
7
+ event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
8
+
9
+ function balanceOf(address owner) external view returns (uint256);
10
+ function ownerOf(uint256 tokenId) external view returns (address);
11
+ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
12
+ function safeTransferFrom(address from, address to, uint256 tokenId) external;
13
+ function transferFrom(address from, address to, uint256 tokenId) external;
14
+ function approve(address to, uint256 tokenId) external;
15
+ function setApprovalForAll(address operator, bool approved) external;
16
+ function getApproved(uint256 tokenId) external view returns (address);
17
+ function isApprovedForAll(address owner, address operator) external view returns (bool);
18
+ }
@@ -0,0 +1,8 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ interface IERC721Metadata {
5
+ function name() external view returns (string memory);
6
+ function symbol() external view returns (string memory);
7
+ function tokenURI(uint256 tokenId) external view returns (string memory);
8
+ }
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.19;
3
+
4
+ interface IERC721Receiver {
5
+ function onERC721Received(
6
+ address operator,
7
+ address from,
8
+ uint256 tokenId,
9
+ bytes calldata data
10
+ ) external returns (bytes4);
11
+ }
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * QVTX Neural Storage Module
5
+ * Decentralized storage utilities with IPFS and Arweave support
6
+ */
7
+
8
+ const crypto = require('crypto');
9
+
10
+ class QVTXStorage {
11
+ constructor(config = {}) {
12
+ this.provider = config.provider || 'ipfs';
13
+ this.gateway = config.gateway || 'https://ipfs.io/ipfs/';
14
+ this.apiKey = config.apiKey || null;
15
+ }
16
+
17
+ // Generate content hash
18
+ hash(content) {
19
+ return crypto.createHash('sha256').update(content).digest('hex');
20
+ }
21
+
22
+ // Upload to IPFS via Pinata or Infura
23
+ async uploadToIPFS(content, options = {}) {
24
+ if (!this.apiKey) {
25
+ throw new Error('IPFS API key required. Set apiKey in config.');
26
+ }
27
+
28
+ const axios = require('axios');
29
+ const FormData = require('form-data');
30
+
31
+ const form = new FormData();
32
+
33
+ if (typeof content === 'string') {
34
+ form.append('file', Buffer.from(content), {
35
+ filename: options.filename || 'data.json'
36
+ });
37
+ } else {
38
+ form.append('file', content);
39
+ }
40
+
41
+ const response = await axios.post('https://api.pinata.cloud/pinning/pinFileToIPFS', form, {
42
+ headers: {
43
+ ...form.getHeaders(),
44
+ 'Authorization': `Bearer ${this.apiKey}`
45
+ }
46
+ });
47
+
48
+ return {
49
+ hash: response.data.IpfsHash,
50
+ url: this.gateway + response.data.IpfsHash,
51
+ size: response.data.PinSize
52
+ };
53
+ }
54
+
55
+ // Fetch from IPFS
56
+ async fetchFromIPFS(hash) {
57
+ const axios = require('axios');
58
+ const url = this.gateway + hash;
59
+ const response = await axios.get(url);
60
+ return response.data;
61
+ }
62
+
63
+ // Create metadata for NFT
64
+ createNFTMetadata(name, description, image, attributes = []) {
65
+ return {
66
+ name,
67
+ description,
68
+ image,
69
+ attributes: attributes.map(attr => ({
70
+ trait_type: attr.trait,
71
+ value: attr.value
72
+ }))
73
+ };
74
+ }
75
+
76
+ // Store encrypted data
77
+ async storeEncrypted(data, password) {
78
+ const algorithm = 'aes-256-gcm';
79
+ const key = crypto.scryptSync(password, 'qvtx-salt', 32);
80
+ const iv = crypto.randomBytes(16);
81
+
82
+ const cipher = crypto.createCipheriv(algorithm, key, iv);
83
+ let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
84
+ encrypted += cipher.final('hex');
85
+
86
+ const authTag = cipher.getAuthTag();
87
+
88
+ return {
89
+ encrypted,
90
+ iv: iv.toString('hex'),
91
+ authTag: authTag.toString('hex')
92
+ };
93
+ }
94
+
95
+ // Retrieve encrypted data
96
+ async retrieveEncrypted(encryptedData, password) {
97
+ const algorithm = 'aes-256-gcm';
98
+ const key = crypto.scryptSync(password, 'qvtx-salt', 32);
99
+ const iv = Buffer.from(encryptedData.iv, 'hex');
100
+ const authTag = Buffer.from(encryptedData.authTag, 'hex');
101
+
102
+ const decipher = crypto.createDecipheriv(algorithm, key, iv);
103
+ decipher.setAuthTag(authTag);
104
+
105
+ let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
106
+ decrypted += decipher.final('utf8');
107
+
108
+ return JSON.parse(decrypted);
109
+ }
110
+ }
111
+
112
+ module.exports = QVTXStorage;