mmn-client-js 1.0.14-node14 → 1.0.14

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/index.esm.js CHANGED
@@ -1,160 +1,161 @@
1
1
  import bs58 from 'bs58';
2
2
  import nacl from 'tweetnacl';
3
3
 
4
- // Fetch and AbortController polyfills for Node 14 compatibility
5
- /* eslint-disable @typescript-eslint/no-require-imports */
6
- let fetchPolyfill;
7
- let AbortControllerPolyfill;
8
- if (typeof fetch === 'undefined') {
9
- try {
10
- // Use node-fetch in Node.js environments that don't have global fetch
11
- fetchPolyfill = require('node-fetch');
12
- }
13
- catch {
14
- throw new Error('node-fetch is required for Node 14 compatibility. Please install it: npm install node-fetch@2');
15
- }
16
- }
17
- else {
18
- fetchPolyfill = fetch;
19
- }
20
- if (typeof AbortController === 'undefined') {
21
- try {
22
- // Use abort-controller in environments that don't have AbortController
23
- AbortControllerPolyfill = require('abort-controller');
24
- }
25
- catch {
26
- throw new Error('abort-controller is required for Node 14 compatibility. Please install it: npm install abort-controller');
27
- }
28
- }
29
- else {
30
- AbortControllerPolyfill = AbortController;
31
- }
32
-
33
- const API_FILTER_PARAMS = {
34
- ALL: 0,
35
- SENT: 2,
36
- RECEIVED: 1,
37
- };
38
- class IndexerClient {
39
- constructor(config) {
40
- this.endpoint = config.endpoint;
41
- this.chainId = config.chainId;
42
- this.timeout = config.timeout || 30000;
43
- // Minimal headers to avoid CORS preflight issues
44
- this.headers = {
45
- Accept: 'application/json',
46
- ...(config.headers || {}),
47
- };
48
- }
49
- /**
50
- * Make HTTP request with automatic CORS handling
51
- * Works out-of-the-box without CORS configuration
52
- * @param method - HTTP method (GET or POST)
53
- * @param path - API endpoint path
54
- * @param params - URL query parameters
55
- * @param body - Request body for POST requests
56
- * @returns Promise resolving to response data
57
- */
58
- async makeRequest(method, path, params, body) {
59
- // Build full URL
60
- let url = `${this.endpoint}/${path}`;
61
- // Add query parameters
62
- if (params && Object.keys(params).length > 0) {
63
- const searchParams = new URLSearchParams();
64
- Object.entries(params).forEach(([key, value]) => {
65
- searchParams.append(key, String(value));
66
- });
67
- url += `?${searchParams.toString()}`;
68
- }
69
- // Create AbortController for timeout
70
- const controller = new AbortControllerPolyfill();
71
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
72
- try {
73
- // Simple fetch with automatic CORS handling
74
- const requestOptions = {
75
- method,
76
- mode: 'cors',
77
- credentials: 'omit',
78
- signal: controller.signal,
79
- headers: {
80
- Accept: 'application/json',
81
- ...this.headers,
82
- },
83
- };
84
- // Add body and Content-Type for POST requests
85
- if (method === 'POST' && body) {
86
- requestOptions.body = JSON.stringify(body);
87
- requestOptions.headers['Content-Type'] =
88
- 'application/json';
89
- }
90
- const response = await fetchPolyfill(url, requestOptions);
91
- clearTimeout(timeoutId);
92
- // Handle response errors
93
- if (!response.ok) {
94
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
95
- }
96
- // Parse JSON response
97
- const data = await response.json();
98
- return data;
99
- }
100
- catch (error) {
101
- clearTimeout(timeoutId);
102
- if (error instanceof Error) {
103
- if (error.name === 'AbortError') {
104
- throw new Error(`Request timeout after ${this.timeout}ms`);
105
- }
106
- throw error;
107
- }
108
- throw new Error('Request failed');
109
- }
110
- }
111
- async getTransactionByHash(hash) {
112
- const path = `${this.chainId}/tx/${hash}/detail`;
113
- const res = await this.makeRequest('GET', path);
114
- return res.data.transaction;
115
- }
116
- async getTransactionByWallet(wallet, page = 1, limit = 50, filter, sortBy = 'transaction_timestamp', sortOrder = 'desc') {
117
- if (!wallet) {
118
- throw new Error('wallet address cannot be empty');
119
- }
120
- if (page < 1)
121
- page = 1;
122
- if (limit <= 0)
123
- limit = 50;
124
- if (limit > 1000)
125
- limit = 1000;
126
- const params = {
127
- page: page - 1,
128
- limit,
129
- sort_by: sortBy,
130
- sort_order: sortOrder,
131
- };
132
- switch (filter) {
133
- case API_FILTER_PARAMS.ALL:
134
- params['wallet_address'] = wallet;
135
- break;
136
- case API_FILTER_PARAMS.SENT:
137
- params['filter_from_address'] = wallet;
138
- break;
139
- case API_FILTER_PARAMS.RECEIVED:
140
- params['filter_to_address'] = wallet;
141
- break;
142
- }
143
- const path = `${this.chainId}/transactions`;
144
- return this.makeRequest('GET', path, params);
145
- }
146
- async getWalletDetail(wallet) {
147
- if (!wallet) {
148
- throw new Error('wallet address cannot be empty');
149
- }
150
- const path = `${this.chainId}/wallets/${wallet}/detail`;
151
- const res = await this.makeRequest('GET', path);
152
- return res.data;
153
- }
4
+ const API_FILTER_PARAMS = {
5
+ ALL: 0,
6
+ SENT: 2,
7
+ RECEIVED: 1,
8
+ };
9
+ class IndexerClient {
10
+ constructor(config) {
11
+ this.endpoint = config.endpoint;
12
+ this.chainId = config.chainId;
13
+ this.timeout = config.timeout || 30000;
14
+ // Minimal headers to avoid CORS preflight issues
15
+ this.headers = {
16
+ Accept: 'application/json',
17
+ ...(config.headers || {}),
18
+ };
19
+ }
20
+ /**
21
+ * Make HTTP request with automatic CORS handling
22
+ * Works out-of-the-box without CORS configuration
23
+ * @param method - HTTP method (GET or POST)
24
+ * @param path - API endpoint path
25
+ * @param params - URL query parameters
26
+ * @param body - Request body for POST requests
27
+ * @returns Promise resolving to response data
28
+ */
29
+ async makeRequest(method, path, params, body) {
30
+ // Build full URL
31
+ let url = `${this.endpoint}/${path}`;
32
+ // Add query parameters
33
+ if (params && Object.keys(params).length > 0) {
34
+ const searchParams = new URLSearchParams();
35
+ Object.entries(params).forEach(([key, value]) => {
36
+ searchParams.append(key, String(value));
37
+ });
38
+ url += `?${searchParams.toString()}`;
39
+ }
40
+ // Create AbortController for timeout
41
+ const controller = new AbortController();
42
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
43
+ try {
44
+ // Simple fetch with automatic CORS handling
45
+ const requestOptions = {
46
+ method,
47
+ mode: 'cors',
48
+ credentials: 'omit',
49
+ signal: controller.signal,
50
+ headers: {
51
+ Accept: 'application/json',
52
+ ...this.headers,
53
+ },
54
+ };
55
+ // Add body and Content-Type for POST requests
56
+ if (method === 'POST' && body) {
57
+ requestOptions.body = JSON.stringify(body);
58
+ requestOptions.headers['Content-Type'] =
59
+ 'application/json';
60
+ }
61
+ const response = await fetch(url, requestOptions);
62
+ clearTimeout(timeoutId);
63
+ // Handle response errors
64
+ if (!response.ok) {
65
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
66
+ }
67
+ // Parse JSON response
68
+ const data = await response.json();
69
+ return data;
70
+ }
71
+ catch (error) {
72
+ clearTimeout(timeoutId);
73
+ if (error instanceof Error) {
74
+ if (error.name === 'AbortError') {
75
+ throw new Error(`Request timeout after ${this.timeout}ms`);
76
+ }
77
+ throw error;
78
+ }
79
+ throw new Error('Request failed');
80
+ }
81
+ }
82
+ async getTransactionByHash(hash) {
83
+ const path = `${this.chainId}/tx/${hash}/detail`;
84
+ const res = await this.makeRequest('GET', path);
85
+ return res.data.transaction;
86
+ }
87
+ async getTransactionsByWalletBeforeTimestamp(wallet, filter, limit, timestamp_lt, last_hash) {
88
+ if (!wallet) {
89
+ throw new Error("wallet address cannot be empty");
90
+ }
91
+ let finalLimit = limit && limit > 0 ? limit : 20;
92
+ if (finalLimit > 1000)
93
+ finalLimit = 1000;
94
+ const params = {
95
+ limit: finalLimit,
96
+ ...(timestamp_lt && { timestamp_lt }),
97
+ ...(last_hash && { last_hash }),
98
+ };
99
+ switch (filter) {
100
+ case API_FILTER_PARAMS.ALL:
101
+ params["wallet_address"] = wallet;
102
+ break;
103
+ case API_FILTER_PARAMS.SENT:
104
+ params["filter_from_address"] = wallet;
105
+ break;
106
+ case API_FILTER_PARAMS.RECEIVED:
107
+ params["filter_to_address"] = wallet;
108
+ break;
109
+ }
110
+ const path = `${this.chainId}/transactions/infinite`;
111
+ return this.makeRequest("GET", path, params);
112
+ }
113
+ async getTransactionByWallet(wallet, page = 1, limit = 50, filter, sortBy = 'transaction_timestamp', sortOrder = 'desc') {
114
+ if (!wallet) {
115
+ throw new Error('wallet address cannot be empty');
116
+ }
117
+ if (page < 1)
118
+ page = 1;
119
+ if (limit <= 0)
120
+ limit = 50;
121
+ if (limit > 1000)
122
+ limit = 1000;
123
+ const params = {
124
+ page: page - 1,
125
+ limit,
126
+ sort_by: sortBy,
127
+ sort_order: sortOrder,
128
+ };
129
+ switch (filter) {
130
+ case API_FILTER_PARAMS.ALL:
131
+ params['wallet_address'] = wallet;
132
+ break;
133
+ case API_FILTER_PARAMS.SENT:
134
+ params['filter_from_address'] = wallet;
135
+ break;
136
+ case API_FILTER_PARAMS.RECEIVED:
137
+ params['filter_to_address'] = wallet;
138
+ break;
139
+ }
140
+ const path = `${this.chainId}/transactions`;
141
+ return this.makeRequest('GET', path, params);
142
+ }
143
+ async getWalletDetail(wallet) {
144
+ if (!wallet) {
145
+ throw new Error('wallet address cannot be empty');
146
+ }
147
+ const path = `${this.chainId}/wallets/${wallet}/detail`;
148
+ const res = await this.makeRequest('GET', path);
149
+ return res.data;
150
+ }
154
151
  }
155
152
 
156
153
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
157
154
 
155
+ function getDefaultExportFromCjs (x) {
156
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
157
+ }
158
+
158
159
  var cryptoJs = {exports: {}};
159
160
 
160
161
  function commonjsRequire(path) {
@@ -967,8 +968,8 @@ function requireCore () {
967
968
 
968
969
  return CryptoJS;
969
970
 
970
- }));
971
- } (core));
971
+ }));
972
+ } (core));
972
973
  return core.exports;
973
974
  }
974
975
 
@@ -1275,8 +1276,8 @@ function requireX64Core () {
1275
1276
 
1276
1277
  return CryptoJS;
1277
1278
 
1278
- }));
1279
- } (x64Core));
1279
+ }));
1280
+ } (x64Core));
1280
1281
  return x64Core.exports;
1281
1282
  }
1282
1283
 
@@ -1355,8 +1356,8 @@ function requireLibTypedarrays () {
1355
1356
 
1356
1357
  return CryptoJS.lib.WordArray;
1357
1358
 
1358
- }));
1359
- } (libTypedarrays));
1359
+ }));
1360
+ } (libTypedarrays));
1360
1361
  return libTypedarrays.exports;
1361
1362
  }
1362
1363
 
@@ -1508,8 +1509,8 @@ function requireEncUtf16 () {
1508
1509
 
1509
1510
  return CryptoJS.enc.Utf16;
1510
1511
 
1511
- }));
1512
- } (encUtf16));
1512
+ }));
1513
+ } (encUtf16));
1513
1514
  return encUtf16.exports;
1514
1515
  }
1515
1516
 
@@ -1648,8 +1649,8 @@ function requireEncBase64 () {
1648
1649
 
1649
1650
  return CryptoJS.enc.Base64;
1650
1651
 
1651
- }));
1652
- } (encBase64));
1652
+ }));
1653
+ } (encBase64));
1653
1654
  return encBase64.exports;
1654
1655
  }
1655
1656
 
@@ -1800,8 +1801,8 @@ function requireEncBase64url () {
1800
1801
 
1801
1802
  return CryptoJS.enc.Base64url;
1802
1803
 
1803
- }));
1804
- } (encBase64url));
1804
+ }));
1805
+ } (encBase64url));
1805
1806
  return encBase64url.exports;
1806
1807
  }
1807
1808
 
@@ -2072,8 +2073,8 @@ function requireMd5 () {
2072
2073
 
2073
2074
  return CryptoJS.MD5;
2074
2075
 
2075
- }));
2076
- } (md5));
2076
+ }));
2077
+ } (md5));
2077
2078
  return md5.exports;
2078
2079
  }
2079
2080
 
@@ -2226,8 +2227,8 @@ function requireSha1 () {
2226
2227
 
2227
2228
  return CryptoJS.SHA1;
2228
2229
 
2229
- }));
2230
- } (sha1));
2230
+ }));
2231
+ } (sha1));
2231
2232
  return sha1.exports;
2232
2233
  }
2233
2234
 
@@ -2429,8 +2430,8 @@ function requireSha256 () {
2429
2430
 
2430
2431
  return CryptoJS.SHA256;
2431
2432
 
2432
- }));
2433
- } (sha256));
2433
+ }));
2434
+ } (sha256));
2434
2435
  return sha256.exports;
2435
2436
  }
2436
2437
 
@@ -2513,8 +2514,8 @@ function requireSha224 () {
2513
2514
 
2514
2515
  return CryptoJS.SHA224;
2515
2516
 
2516
- }));
2517
- } (sha224));
2517
+ }));
2518
+ } (sha224));
2518
2519
  return sha224.exports;
2519
2520
  }
2520
2521
 
@@ -2843,8 +2844,8 @@ function requireSha512 () {
2843
2844
 
2844
2845
  return CryptoJS.SHA512;
2845
2846
 
2846
- }));
2847
- } (sha512));
2847
+ }));
2848
+ } (sha512));
2848
2849
  return sha512.exports;
2849
2850
  }
2850
2851
 
@@ -2930,8 +2931,8 @@ function requireSha384 () {
2930
2931
 
2931
2932
  return CryptoJS.SHA384;
2932
2933
 
2933
- }));
2934
- } (sha384));
2934
+ }));
2935
+ } (sha384));
2935
2936
  return sha384.exports;
2936
2937
  }
2937
2938
 
@@ -3260,8 +3261,8 @@ function requireSha3 () {
3260
3261
 
3261
3262
  return CryptoJS.SHA3;
3262
3263
 
3263
- }));
3264
- } (sha3));
3264
+ }));
3265
+ } (sha3));
3265
3266
  return sha3.exports;
3266
3267
  }
3267
3268
 
@@ -3531,8 +3532,8 @@ function requireRipemd160 () {
3531
3532
 
3532
3533
  return CryptoJS.RIPEMD160;
3533
3534
 
3534
- }));
3535
- } (ripemd160));
3535
+ }));
3536
+ } (ripemd160));
3536
3537
  return ripemd160.exports;
3537
3538
  }
3538
3539
 
@@ -3678,8 +3679,8 @@ function requireHmac () {
3678
3679
  }());
3679
3680
 
3680
3681
 
3681
- }));
3682
- } (hmac));
3682
+ }));
3683
+ } (hmac));
3683
3684
  return hmac.exports;
3684
3685
  }
3685
3686
 
@@ -3827,8 +3828,8 @@ function requirePbkdf2 () {
3827
3828
 
3828
3829
  return CryptoJS.PBKDF2;
3829
3830
 
3830
- }));
3831
- } (pbkdf2));
3831
+ }));
3832
+ } (pbkdf2));
3832
3833
  return pbkdf2.exports;
3833
3834
  }
3834
3835
 
@@ -3965,8 +3966,8 @@ function requireEvpkdf () {
3965
3966
 
3966
3967
  return CryptoJS.EvpKDF;
3967
3968
 
3968
- }));
3969
- } (evpkdf));
3969
+ }));
3970
+ } (evpkdf));
3970
3971
  return evpkdf.exports;
3971
3972
  }
3972
3973
 
@@ -4189,7 +4190,7 @@ function requireCipherCore () {
4189
4190
  C_lib.StreamCipher = Cipher.extend({
4190
4191
  _doFinalize: function () {
4191
4192
  // Process partial blocks
4192
- var finalProcessedBlocks = this._process(!!'flush');
4193
+ var finalProcessedBlocks = this._process(true);
4193
4194
 
4194
4195
  return finalProcessedBlocks;
4195
4196
  },
@@ -4470,10 +4471,10 @@ function requireCipherCore () {
4470
4471
  padding.pad(this._data, this.blockSize);
4471
4472
 
4472
4473
  // Process final blocks
4473
- finalProcessedBlocks = this._process(!!'flush');
4474
+ finalProcessedBlocks = this._process(true);
4474
4475
  } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
4475
4476
  // Process final blocks
4476
- finalProcessedBlocks = this._process(!!'flush');
4477
+ finalProcessedBlocks = this._process(true);
4477
4478
 
4478
4479
  // Unpad data
4479
4480
  padding.unpad(finalProcessedBlocks);
@@ -4864,8 +4865,8 @@ function requireCipherCore () {
4864
4865
  }());
4865
4866
 
4866
4867
 
4867
- }));
4868
- } (cipherCore));
4868
+ }));
4869
+ } (cipherCore));
4869
4870
  return cipherCore.exports;
4870
4871
  }
4871
4872
 
@@ -4948,8 +4949,8 @@ function requireModeCfb () {
4948
4949
 
4949
4950
  return CryptoJS.mode.CFB;
4950
4951
 
4951
- }));
4952
- } (modeCfb));
4952
+ }));
4953
+ } (modeCfb));
4953
4954
  return modeCfb.exports;
4954
4955
  }
4955
4956
 
@@ -5010,8 +5011,8 @@ function requireModeCtr () {
5010
5011
 
5011
5012
  return CryptoJS.mode.CTR;
5012
5013
 
5013
- }));
5014
- } (modeCtr));
5014
+ }));
5015
+ } (modeCtr));
5015
5016
  return modeCtr.exports;
5016
5017
  }
5017
5018
 
@@ -5130,8 +5131,8 @@ function requireModeCtrGladman () {
5130
5131
 
5131
5132
  return CryptoJS.mode.CTRGladman;
5132
5133
 
5133
- }));
5134
- } (modeCtrGladman));
5134
+ }));
5135
+ } (modeCtrGladman));
5135
5136
  return modeCtrGladman.exports;
5136
5137
  }
5137
5138
 
@@ -5188,8 +5189,8 @@ function requireModeOfb () {
5188
5189
 
5189
5190
  return CryptoJS.mode.OFB;
5190
5191
 
5191
- }));
5192
- } (modeOfb));
5192
+ }));
5193
+ } (modeOfb));
5193
5194
  return modeOfb.exports;
5194
5195
  }
5195
5196
 
@@ -5232,8 +5233,8 @@ function requireModeEcb () {
5232
5233
 
5233
5234
  return CryptoJS.mode.ECB;
5234
5235
 
5235
- }));
5236
- } (modeEcb));
5236
+ }));
5237
+ } (modeEcb));
5237
5238
  return modeEcb.exports;
5238
5239
  }
5239
5240
 
@@ -5285,8 +5286,8 @@ function requirePadAnsix923 () {
5285
5286
 
5286
5287
  return CryptoJS.pad.Ansix923;
5287
5288
 
5288
- }));
5289
- } (padAnsix923));
5289
+ }));
5290
+ } (padAnsix923));
5290
5291
  return padAnsix923.exports;
5291
5292
  }
5292
5293
 
@@ -5333,8 +5334,8 @@ function requirePadIso10126 () {
5333
5334
 
5334
5335
  return CryptoJS.pad.Iso10126;
5335
5336
 
5336
- }));
5337
- } (padIso10126));
5337
+ }));
5338
+ } (padIso10126));
5338
5339
  return padIso10126.exports;
5339
5340
  }
5340
5341
 
@@ -5377,8 +5378,8 @@ function requirePadIso97971 () {
5377
5378
 
5378
5379
  return CryptoJS.pad.Iso97971;
5379
5380
 
5380
- }));
5381
- } (padIso97971));
5381
+ }));
5382
+ } (padIso97971));
5382
5383
  return padIso97971.exports;
5383
5384
  }
5384
5385
 
@@ -5428,8 +5429,8 @@ function requirePadZeropadding () {
5428
5429
 
5429
5430
  return CryptoJS.pad.ZeroPadding;
5430
5431
 
5431
- }));
5432
- } (padZeropadding));
5432
+ }));
5433
+ } (padZeropadding));
5433
5434
  return padZeropadding.exports;
5434
5435
  }
5435
5436
 
@@ -5462,8 +5463,8 @@ function requirePadNopadding () {
5462
5463
 
5463
5464
  return CryptoJS.pad.NoPadding;
5464
5465
 
5465
- }));
5466
- } (padNopadding));
5466
+ }));
5467
+ } (padNopadding));
5467
5468
  return padNopadding.exports;
5468
5469
  }
5469
5470
 
@@ -5532,8 +5533,8 @@ function requireFormatHex () {
5532
5533
 
5533
5534
  return CryptoJS.format.Hex;
5534
5535
 
5535
- }));
5536
- } (formatHex));
5536
+ }));
5537
+ } (formatHex));
5537
5538
  return formatHex.exports;
5538
5539
  }
5539
5540
 
@@ -5770,8 +5771,8 @@ function requireAes () {
5770
5771
 
5771
5772
  return CryptoJS.AES;
5772
5773
 
5773
- }));
5774
- } (aes));
5774
+ }));
5775
+ } (aes));
5775
5776
  return aes.exports;
5776
5777
  }
5777
5778
 
@@ -6553,8 +6554,8 @@ function requireTripledes () {
6553
6554
 
6554
6555
  return CryptoJS.TripleDES;
6555
6556
 
6556
- }));
6557
- } (tripledes));
6557
+ }));
6558
+ } (tripledes));
6558
6559
  return tripledes.exports;
6559
6560
  }
6560
6561
 
@@ -6696,8 +6697,8 @@ function requireRc4 () {
6696
6697
 
6697
6698
  return CryptoJS.RC4;
6698
6699
 
6699
- }));
6700
- } (rc4));
6700
+ }));
6701
+ } (rc4));
6701
6702
  return rc4.exports;
6702
6703
  }
6703
6704
 
@@ -6892,8 +6893,8 @@ function requireRabbit () {
6892
6893
 
6893
6894
  return CryptoJS.Rabbit;
6894
6895
 
6895
- }));
6896
- } (rabbit));
6896
+ }));
6897
+ } (rabbit));
6897
6898
  return rabbit.exports;
6898
6899
  }
6899
6900
 
@@ -7086,8 +7087,8 @@ function requireRabbitLegacy () {
7086
7087
 
7087
7088
  return CryptoJS.RabbitLegacy;
7088
7089
 
7089
- }));
7090
- } (rabbitLegacy));
7090
+ }));
7091
+ } (rabbitLegacy));
7091
7092
  return rabbitLegacy.exports;
7092
7093
  }
7093
7094
 
@@ -7561,8 +7562,8 @@ function requireBlowfish () {
7561
7562
 
7562
7563
  return CryptoJS.Blowfish;
7563
7564
 
7564
- }));
7565
- } (blowfish));
7565
+ }));
7566
+ } (blowfish));
7566
7567
  return blowfish.exports;
7567
7568
  }
7568
7569
 
@@ -7576,621 +7577,631 @@ function requireBlowfish () {
7576
7577
 
7577
7578
  return CryptoJS;
7578
7579
 
7579
- }));
7580
+ }));
7580
7581
  } (cryptoJs));
7581
7582
 
7582
- var CryptoJS = cryptoJs.exports;
7583
-
7584
- // MMN Client
7585
- // Buffer polyfill for mobile environments
7586
- class BufferPolyfill {
7587
- static isBuffer(obj) {
7588
- if (typeof Buffer !== 'undefined' && Buffer.isBuffer) {
7589
- return Buffer.isBuffer(obj);
7590
- }
7591
- return obj instanceof Uint8Array;
7592
- }
7593
- static from(data, encoding) {
7594
- if (typeof Buffer !== 'undefined' && Buffer.from) {
7595
- return Buffer.from(data, encoding);
7596
- }
7597
- let result;
7598
- if (Array.isArray(data)) {
7599
- result = new Uint8Array(data);
7600
- }
7601
- else if (typeof data === 'string') {
7602
- if (encoding === 'hex') {
7603
- const bytes = [];
7604
- for (let i = 0; i < data.length; i += 2) {
7605
- bytes.push(parseInt(data.substr(i, 2), 16));
7606
- }
7607
- result = new Uint8Array(bytes);
7608
- }
7609
- else {
7610
- // UTF-8 encoding
7611
- const encoder = new TextEncoder();
7612
- result = encoder.encode(data);
7613
- }
7614
- }
7615
- else if (data instanceof Uint8Array) {
7616
- result = data;
7617
- }
7618
- else {
7619
- result = new Uint8Array(data);
7620
- }
7621
- // Add toString method
7622
- result.toString = function (encoding) {
7623
- if (encoding === 'hex') {
7624
- return Array.from(this)
7625
- .map((b) => b.toString(16).padStart(2, '0'))
7626
- .join('');
7627
- }
7628
- else if (encoding === 'base64') {
7629
- // Simple base64 encoding
7630
- const bytes = this;
7631
- let binary = '';
7632
- for (let i = 0; i < bytes.length; i++) {
7633
- binary += String.fromCharCode(bytes[i]);
7634
- }
7635
- return btoa(binary);
7636
- }
7637
- else {
7638
- // UTF-8 decoding
7639
- const decoder = new TextDecoder();
7640
- return decoder.decode(this);
7641
- }
7642
- };
7643
- return result;
7644
- }
7645
- static concat(arrays) {
7646
- if (typeof Buffer !== 'undefined' && Buffer.concat) {
7647
- return Buffer.concat(arrays);
7648
- }
7649
- const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
7650
- const result = new Uint8Array(totalLength);
7651
- let offset = 0;
7652
- for (const arr of arrays) {
7653
- result.set(arr, offset);
7654
- offset += arr.length;
7655
- }
7656
- // Add toString method
7657
- result.toString = function (encoding) {
7658
- if (encoding === 'hex') {
7659
- return Array.from(this)
7660
- .map((b) => b.toString(16).padStart(2, '0'))
7661
- .join('');
7662
- }
7663
- else {
7664
- const decoder = new TextDecoder();
7665
- return decoder.decode(this);
7666
- }
7667
- };
7668
- return result;
7669
- }
7670
- }
7671
- // Use polyfill if Buffer is not available
7672
- const BufferCompat = typeof Buffer !== 'undefined' ? Buffer : BufferPolyfill;
7673
- // Cryptographic constants
7674
- const CRYPTO_CONSTANTS = {
7675
- ED25519_PRIVATE_KEY_LENGTH: 32,
7676
- ED25519_PUBLIC_KEY_LENGTH: 32,
7677
- MNEMONIC_ENTROPY_BITS: 128,
7678
- PKCS8_VERSION: 0,
7679
- // ASN.1 DER encoding
7680
- ASN1_SEQUENCE_TAG: 0x30,
7681
- ASN1_OCTET_STRING_TAG: 0x04,
7682
- ASN1_INTEGER_TAG: 0x02,
7683
- ASN1_LENGTH: 0x80,
7684
- // Ed25519 OID bytes: 1.3.101.112 (RFC 8410)
7685
- ED25519_OID_BYTES: [0x06, 0x03, 0x2b, 0x65, 0x70],
7686
- // PKCS#8 structure length constants
7687
- PKCS8_ALGORITHM_ID_LENGTH: 0x0b,
7688
- PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH: 0x22,
7689
- PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH: 0x20, // Inner OCTET STRING length (32 bytes)
7690
- };
7691
- // PRNG (Pseudo-Random Number Generator) constants
7692
- const PRNG_CONSTANTS = {
7693
- // Numerical Recipes LCG
7694
- LCG_MULTIPLIER: 1664525,
7695
- LCG_INCREMENT: 1013904223,
7696
- LCG_MODULUS: 4294967296,
7697
- TIMESTAMP_MULTIPLIER: 2654435761,
7698
- HASH_SUBSTRING_LENGTH: 8,
7699
- BYTE_SHIFT: 24,
7700
- BYTE_MASK: 0xff,
7701
- };
7702
- const TX_TYPE = {
7703
- TRANSFER: 0,
7704
- PRIVATE_KEY: 1,
7705
- };
7706
- const DECIMALS = 6;
7707
- class MmnClient {
7708
- constructor(config) {
7709
- this.requestId = 0;
7710
- this.config = {
7711
- timeout: 30000,
7712
- headers: {
7713
- 'Content-Type': 'application/json',
7714
- Accept: 'application/json',
7715
- },
7716
- ...config,
7717
- };
7718
- }
7719
- async makeRequest(method, params) {
7720
- const request = {
7721
- jsonrpc: '2.0',
7722
- method,
7723
- params,
7724
- id: ++this.requestId,
7725
- };
7726
- // Create AbortController for timeout
7727
- const controller = new AbortControllerPolyfill();
7728
- const timeoutId = setTimeout(() => controller.abort(), this.config.timeout || 30000);
7729
- try {
7730
- const requestOptions = {
7731
- method: 'POST',
7732
- mode: 'cors',
7733
- credentials: 'omit',
7734
- signal: controller.signal,
7735
- headers: this.config.headers || {},
7736
- body: JSON.stringify(request),
7737
- };
7738
- const response = await fetchPolyfill(this.config.baseUrl, requestOptions);
7739
- clearTimeout(timeoutId);
7740
- if (!response.ok) {
7741
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
7742
- }
7743
- const result = await response.json();
7744
- if (result.error) {
7745
- throw new Error(`JSON-RPC Error ${result.error.code}: ${result.error.message}`);
7746
- }
7747
- return result.result;
7748
- }
7749
- catch (error) {
7750
- clearTimeout(timeoutId);
7751
- if (error instanceof Error) {
7752
- if (error.name === 'AbortError') {
7753
- throw new Error(`Request timeout after ${this.config.timeout || 30000}ms`);
7754
- }
7755
- throw error;
7756
- }
7757
- throw new Error('Unknown error occurred');
7758
- }
7759
- }
7760
- /**
7761
- * Securely convert raw Ed25519 private key to PKCS#8 format
7762
- * @param raw - Raw 32-byte Ed25519 private key
7763
- * @returns PKCS#8 formatted private key in hex
7764
- * @throws Error if input validation fails
7765
- */
7766
- rawEd25519ToPkcs8Hex(raw) {
7767
- // Input validation
7768
- if (!BufferCompat.isBuffer(raw)) {
7769
- throw new Error('Private key must be a Buffer');
7770
- }
7771
- if (raw.length !== CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH) {
7772
- throw new Error(`Ed25519 private key must be exactly ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH} bytes`);
7773
- }
7774
- try {
7775
- // Ed25519 OID: 1.3.101.112 (RFC 8410 - Algorithm Identifiers for Ed25519)
7776
- const ED25519_OID = BufferCompat.from(CRYPTO_CONSTANTS.ED25519_OID_BYTES);
7777
- const VERSION_BYTES = BufferCompat.from([
7778
- CRYPTO_CONSTANTS.ASN1_INTEGER_TAG,
7779
- 0x01,
7780
- CRYPTO_CONSTANTS.PKCS8_VERSION,
7781
- ]);
7782
- // Create algorithm identifier sequence (AlgorithmIdentifier)
7783
- const algorithmId = BufferCompat.concat([
7784
- BufferCompat.from([
7785
- CRYPTO_CONSTANTS.ASN1_SEQUENCE_TAG,
7786
- CRYPTO_CONSTANTS.PKCS8_ALGORITHM_ID_LENGTH,
7787
- ]),
7788
- ED25519_OID,
7789
- ]);
7790
- // Create private key octet string (wrapped Ed25519 private key)
7791
- const privateKeyOctetString = BufferCompat.concat([
7792
- BufferCompat.from([
7793
- CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7794
- CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH,
7795
- ]),
7796
- BufferCompat.from([
7797
- CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7798
- CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH,
7799
- ]),
7800
- raw,
7801
- ]);
7802
- // Create PKCS#8 body
7803
- const pkcs8Body = BufferCompat.concat([
7804
- VERSION_BYTES,
7805
- algorithmId,
7806
- privateKeyOctetString,
7807
- ]);
7808
- // Create final PKCS#8 structure
7809
- const pkcs8 = BufferCompat.concat([
7810
- BufferCompat.from([CRYPTO_CONSTANTS.ASN1_SEQUENCE_TAG]),
7811
- this.encodeLength(pkcs8Body.length),
7812
- pkcs8Body,
7813
- ]);
7814
- const result = pkcs8.toString('hex');
7815
- // Clear sensitive data from memory
7816
- raw.fill(0);
7817
- privateKeyOctetString.fill(0);
7818
- pkcs8Body.fill(0);
7819
- pkcs8.fill(0);
7820
- return result;
7821
- }
7822
- catch (error) {
7823
- // Clear sensitive data on error
7824
- raw.fill(0);
7825
- throw new Error(`Failed to convert private key to PKCS#8: ${error instanceof Error ? error.message : 'Unknown error'}`);
7826
- }
7827
- }
7828
- /**
7829
- * Encode length in ASN.1 DER format
7830
- * ASN.1 length encoding rules:
7831
- * - Short form (0-127): single byte with the length value
7832
- * - Long form (128+): first byte is 0x80 + number of length bytes, followed by length bytes
7833
- * @param length - The length value to encode
7834
- * @returns ASN.1 DER encoded length bytes
7835
- */
7836
- encodeLength(length) {
7837
- if (length < CRYPTO_CONSTANTS.ASN1_LENGTH) {
7838
- return BufferCompat.from([length]);
7839
- }
7840
- const bytes = [];
7841
- let len = length;
7842
- while (len > 0) {
7843
- bytes.unshift(len & PRNG_CONSTANTS.BYTE_MASK);
7844
- len >>= 8;
7845
- }
7846
- return BufferCompat.from([
7847
- CRYPTO_CONSTANTS.ASN1_LENGTH | bytes.length,
7848
- ...bytes,
7849
- ]);
7850
- }
7851
- /**
7852
- * Generate secure entropy using multiple sources for maximum compatibility
7853
- * @returns Array of 32 random bytes
7854
- */
7855
- generateSecureEntropy() {
7856
- const entropy = [];
7857
- const targetLength = CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH;
7858
- // Use multiple entropy sources
7859
- const now = Date.now();
7860
- const performance = typeof window !== 'undefined' && window.performance
7861
- ? window.performance.now()
7862
- : now;
7863
- const random = Math.random();
7864
- // Create initial seed from timestamp and random
7865
- let seed = now + performance + random;
7866
- // Generate bytes using Linear Congruential Generator (LCG) with multiple entropy sources
7867
- // This provides a fallback Pseudorandom Number Generator (PRNG) when crypto.getRandomValues is not available
7868
- for (let i = 0; i < targetLength; i++) {
7869
- // Xₙ₊₁ = (a * Xₙ + c) mod m
7870
- seed =
7871
- (seed * PRNG_CONSTANTS.LCG_MULTIPLIER + PRNG_CONSTANTS.LCG_INCREMENT) %
7872
- PRNG_CONSTANTS.LCG_MODULUS;
7873
- // Mix with timestamp to add time-based entropy
7874
- seed ^= (now + i) * PRNG_CONSTANTS.TIMESTAMP_MULTIPLIER;
7875
- // Mix with Math.random() for additional browser-provided randomness
7876
- seed ^= Math.floor(Math.random() * PRNG_CONSTANTS.LCG_MODULUS);
7877
- // Additional cryptographic mixing using SHA256 if CryptoJS is available
7878
- if (typeof CryptoJS !== 'undefined') {
7879
- const hashInput = seed.toString() + i.toString() + now.toString();
7880
- const hash = CryptoJS.SHA256(hashInput).toString();
7881
- // Extract first 8 hex characters (32 bits) from hash for mixing
7882
- seed ^= parseInt(hash.substring(0, PRNG_CONSTANTS.HASH_SUBSTRING_LENGTH), 16);
7883
- }
7884
- entropy.push((seed >>> PRNG_CONSTANTS.BYTE_SHIFT) & PRNG_CONSTANTS.BYTE_MASK);
7885
- }
7886
- return entropy;
7887
- }
7888
- /**
7889
- * Securely generate ephemeral key pair with proper entropy
7890
- * React Native compatible version with multiple fallbacks
7891
- * @returns Ephemeral key pair with private and public keys
7892
- * @throws Error if key generation fails
7893
- */
7894
- generateEphemeralKeyPair() {
7895
- try {
7896
- let seed;
7897
- // Try multiple approaches for mobile compatibility
7898
- try {
7899
- // Method 1: Try nacl.randomBytes first
7900
- seed = nacl.randomBytes(CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH);
7901
- }
7902
- catch (naclError) {
7903
- try {
7904
- // Method 2: Use crypto.getRandomValues if available (browsers/React Native)
7905
- if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
7906
- seed = new Uint8Array(CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH);
7907
- crypto.getRandomValues(seed);
7908
- }
7909
- else {
7910
- throw new Error('crypto.getRandomValues not available');
7911
- }
7912
- }
7913
- catch (cryptoError) {
7914
- // Method 3: Fallback to secure pseudo-random generation
7915
- const entropy = this.generateSecureEntropy();
7916
- seed = new Uint8Array(entropy);
7917
- }
7918
- }
7919
- // Validate seed length
7920
- if (seed.length !== CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH) {
7921
- throw new Error(`Invalid seed length: expected ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH}, got ${seed.length}`);
7922
- }
7923
- // Generate key pair from seed
7924
- const keyPair = nacl.sign.keyPair.fromSeed(seed);
7925
- const publicKeyBytes = keyPair.publicKey;
7926
- // Validate public key
7927
- if (publicKeyBytes.length !== CRYPTO_CONSTANTS.ED25519_PUBLIC_KEY_LENGTH) {
7928
- throw new Error(`Invalid public key length: expected ${CRYPTO_CONSTANTS.ED25519_PUBLIC_KEY_LENGTH}, got ${publicKeyBytes.length}`);
7929
- }
7930
- // Convert private key to PKCS#8 format
7931
- const privateKeyHex = this.rawEd25519ToPkcs8Hex(BufferCompat.from(seed));
7932
- // Clear sensitive data
7933
- seed.fill(0);
7934
- keyPair.secretKey.fill(0);
7935
- return {
7936
- privateKey: privateKeyHex,
7937
- publicKey: bs58.encode(publicKeyBytes),
7938
- };
7939
- }
7940
- catch (error) {
7941
- throw new Error(`Failed to generate ephemeral key pair: ${error instanceof Error ? error.message : 'Unknown error'}`);
7942
- }
7943
- }
7944
- getAddressFromUserId(userId) {
7945
- // Use crypto-js for SHA-256 in React Native
7946
- const hash = CryptoJS.SHA256(userId).toString(CryptoJS.enc.Hex);
7947
- const hashBuffer = BufferCompat.from(hash, 'hex');
7948
- return bs58.encode(hashBuffer);
7949
- }
7950
- /**
7951
- * Create and sign a transaction message
7952
- */
7953
- createAndSignTx(params) {
7954
- if (!this.validateAddress(params.sender)) {
7955
- throw new Error('Invalid sender address');
7956
- }
7957
- if (!this.validateAddress(params.recipient)) {
7958
- throw new Error('Invalid recipient address');
7959
- }
7960
- if (params.sender === params.recipient) {
7961
- throw new Error('Sender and recipient addresses cannot be the same');
7962
- }
7963
- const txMsg = {
7964
- type: params.type,
7965
- sender: params.sender,
7966
- recipient: params.recipient,
7967
- amount: params.amount,
7968
- timestamp: params.timestamp || Date.now(),
7969
- text_data: params.textData || '',
7970
- nonce: params.nonce,
7971
- extra_info: JSON.stringify(params.extraInfo) || '',
7972
- zk_proof: params.zkProof || '',
7973
- zk_pub: params.zkPub || '',
7974
- };
7975
- const signature = this.signTransaction(txMsg, params.privateKey);
7976
- return {
7977
- tx_msg: txMsg,
7978
- signature,
7979
- };
7980
- }
7981
- /**
7982
- * Securely sign a transaction with Ed25519
7983
- * @param tx - Transaction message to sign
7984
- * @param privateKeyHex - Private key in PKCS#8 hex format
7985
- * @returns Base58 encoded signature
7986
- * @throws Error if signing fails
7987
- */
7988
- signTransaction(tx, privateKeyHex) {
7989
- try {
7990
- // Validate inputs
7991
- if (!tx || typeof tx !== 'object') {
7992
- throw new Error('Invalid transaction object');
7993
- }
7994
- if (!privateKeyHex || typeof privateKeyHex !== 'string') {
7995
- throw new Error('Invalid private key format');
7996
- }
7997
- // Serialize transaction data
7998
- const serializedData = this.serializeTransaction(tx);
7999
- if (!serializedData || serializedData.length === 0) {
8000
- throw new Error('Failed to serialize transaction');
8001
- }
8002
- // Extract the Ed25519 seed from the private key for nacl signing
8003
- const privateKeyDer = BufferCompat.from(privateKeyHex, 'hex');
8004
- if (privateKeyDer.length < CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH) {
8005
- throw new Error(`Invalid private key length: expected at least ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH} bytes, got ${privateKeyDer.length}`);
8006
- }
8007
- const seed = privateKeyDer.subarray(-CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH); // Last 32 bytes
8008
- const keyPair = nacl.sign.keyPair.fromSeed(seed);
8009
- // Validate key pair
8010
- if (!keyPair.publicKey || !keyPair.secretKey) {
8011
- throw new Error('Failed to create key pair from seed');
8012
- }
8013
- // Sign using Ed25519 (nacl) - constant time operation
8014
- const signature = nacl.sign.detached(serializedData, keyPair.secretKey);
8015
- if (!signature || signature.length === 0) {
8016
- throw new Error('Failed to generate signature');
8017
- }
8018
- // Clear sensitive data
8019
- privateKeyDer.fill(0);
8020
- seed.fill(0);
8021
- keyPair.secretKey.fill(0);
8022
- // Return signature based on transaction type
8023
- if (tx.type === TX_TYPE.PRIVATE_KEY) {
8024
- return bs58.encode(BufferCompat.from(signature));
8025
- }
8026
- // For regular transactions, wrap signature with public key
8027
- const userSig = {
8028
- PubKey: BufferCompat.from(keyPair.publicKey).toString('base64'),
8029
- Sig: BufferCompat.from(signature).toString('base64'),
8030
- };
8031
- return bs58.encode(BufferCompat.from(JSON.stringify(userSig)));
8032
- }
8033
- catch (error) {
8034
- throw new Error(`Transaction signing failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
8035
- }
8036
- }
8037
- /**
8038
- * Serialize transaction for signing
8039
- */
8040
- serializeTransaction(tx) {
8041
- const data = `${tx.type}|${tx.sender}|${tx.recipient}|${tx.amount}|${tx.text_data}|${tx.nonce}|${tx.extra_info}`;
8042
- return BufferCompat.from(data, 'utf8');
8043
- }
8044
- /**
8045
- * Add a signed transaction to the blockchain
8046
- */
8047
- async addTx(signedTx) {
8048
- return this.makeRequest('tx.addtx', signedTx);
8049
- }
8050
- /**
8051
- * Send a transaction (create, sign, and submit)
8052
- */
8053
- async sendTransaction(params) {
8054
- const fromAddress = this.getAddressFromUserId(params.sender);
8055
- const toAddress = this.getAddressFromUserId(params.recipient);
8056
- const signedTx = this.createAndSignTx({
8057
- ...params,
8058
- type: TX_TYPE.TRANSFER,
8059
- sender: fromAddress,
8060
- recipient: toAddress,
8061
- });
8062
- return this.addTx(signedTx);
8063
- }
8064
- async sendTransactionByAddress(params) {
8065
- const signedTx = this.createAndSignTx({
8066
- ...params,
8067
- type: TX_TYPE.TRANSFER,
8068
- });
8069
- return this.addTx(signedTx);
8070
- }
8071
- async sendTransactionByPrivateKey(params) {
8072
- const signedTx = this.createAndSignTx({
8073
- ...params,
8074
- type: TX_TYPE.PRIVATE_KEY,
8075
- });
8076
- return this.addTx(signedTx);
8077
- }
8078
- /**
8079
- * Get current nonce for an account
8080
- */
8081
- async getCurrentNonce(userId, tag = 'latest') {
8082
- const address = this.getAddressFromUserId(userId);
8083
- return this.makeRequest('account.getcurrentnonce', { address, tag });
8084
- }
8085
- async getAccountByUserId(userId) {
8086
- const address = this.getAddressFromUserId(userId);
8087
- return this.makeRequest('account.getaccount', {
8088
- address,
8089
- });
8090
- }
8091
- scaleAmountToDecimals(originalAmount, decimals = DECIMALS) {
8092
- let scaledAmount = BigInt(originalAmount);
8093
- for (let i = 0; i < decimals; i++) {
8094
- scaledAmount = scaledAmount * BigInt(10);
8095
- }
8096
- return scaledAmount.toString();
8097
- }
8098
- validateAddress(addr) {
8099
- const decoded = bs58.decode(addr);
8100
- if (!decoded ||
8101
- decoded.length !== CRYPTO_CONSTANTS.ED25519_PUBLIC_KEY_LENGTH) {
8102
- return false;
8103
- }
8104
- return true;
8105
- }
8106
- validateAmount(balance, amount) {
8107
- const bigBalance = BigInt(balance);
8108
- const bigAmount = BigInt(typeof amount === 'number' ? this.scaleAmountToDecimals(amount) : amount);
8109
- return bigAmount <= bigBalance;
8110
- }
8111
- }
8112
- function createMmnClient(config) {
8113
- return new MmnClient(config);
7583
+ var cryptoJsExports = cryptoJs.exports;
7584
+ var CryptoJS = /*@__PURE__*/getDefaultExportFromCjs(cryptoJsExports);
7585
+
7586
+ // MMN Client
7587
+ // This client provides a complete interface for interacting with MMN blockchain
7588
+ // Buffer polyfill for mobile environments
7589
+ class BufferPolyfill {
7590
+ static isBuffer(obj) {
7591
+ if (typeof Buffer !== 'undefined' && Buffer.isBuffer) {
7592
+ return Buffer.isBuffer(obj);
7593
+ }
7594
+ return obj instanceof Uint8Array;
7595
+ }
7596
+ static from(data, encoding) {
7597
+ if (typeof Buffer !== 'undefined' && Buffer.from) {
7598
+ return Buffer.from(data, encoding);
7599
+ }
7600
+ let result;
7601
+ if (Array.isArray(data)) {
7602
+ result = new Uint8Array(data);
7603
+ }
7604
+ else if (typeof data === 'string') {
7605
+ if (encoding === 'hex') {
7606
+ const bytes = [];
7607
+ for (let i = 0; i < data.length; i += 2) {
7608
+ bytes.push(parseInt(data.substr(i, 2), 16));
7609
+ }
7610
+ result = new Uint8Array(bytes);
7611
+ }
7612
+ else {
7613
+ // UTF-8 encoding
7614
+ const encoder = new TextEncoder();
7615
+ result = encoder.encode(data);
7616
+ }
7617
+ }
7618
+ else if (data instanceof Uint8Array) {
7619
+ result = data;
7620
+ }
7621
+ else {
7622
+ result = new Uint8Array(data);
7623
+ }
7624
+ // Add toString method
7625
+ result.toString = function (encoding) {
7626
+ if (encoding === 'hex') {
7627
+ return Array.from(this)
7628
+ .map((b) => b.toString(16).padStart(2, '0'))
7629
+ .join('');
7630
+ }
7631
+ else if (encoding === 'base64') {
7632
+ // Simple base64 encoding
7633
+ const bytes = this;
7634
+ let binary = '';
7635
+ for (let i = 0; i < bytes.length; i++) {
7636
+ binary += String.fromCharCode(bytes[i]);
7637
+ }
7638
+ return btoa(binary);
7639
+ }
7640
+ else {
7641
+ // UTF-8 decoding
7642
+ const decoder = new TextDecoder();
7643
+ return decoder.decode(this);
7644
+ }
7645
+ };
7646
+ return result;
7647
+ }
7648
+ static concat(arrays) {
7649
+ if (typeof Buffer !== 'undefined' && Buffer.concat) {
7650
+ return Buffer.concat(arrays);
7651
+ }
7652
+ const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
7653
+ const result = new Uint8Array(totalLength);
7654
+ let offset = 0;
7655
+ for (const arr of arrays) {
7656
+ result.set(arr, offset);
7657
+ offset += arr.length;
7658
+ }
7659
+ // Add toString method
7660
+ result.toString = function (encoding) {
7661
+ if (encoding === 'hex') {
7662
+ return Array.from(this)
7663
+ .map((b) => b.toString(16).padStart(2, '0'))
7664
+ .join('');
7665
+ }
7666
+ else {
7667
+ const decoder = new TextDecoder();
7668
+ return decoder.decode(this);
7669
+ }
7670
+ };
7671
+ return result;
7672
+ }
7673
+ }
7674
+ // Use polyfill if Buffer is not available
7675
+ const BufferCompat = typeof Buffer !== 'undefined' ? Buffer : BufferPolyfill;
7676
+ // Cryptographic constants
7677
+ const CRYPTO_CONSTANTS = {
7678
+ ED25519_PRIVATE_KEY_LENGTH: 32,
7679
+ ED25519_PUBLIC_KEY_LENGTH: 32,
7680
+ MNEMONIC_ENTROPY_BITS: 128,
7681
+ PKCS8_VERSION: 0,
7682
+ // ASN.1 DER encoding
7683
+ ASN1_SEQUENCE_TAG: 0x30,
7684
+ ASN1_OCTET_STRING_TAG: 0x04,
7685
+ ASN1_INTEGER_TAG: 0x02,
7686
+ ASN1_LENGTH: 0x80,
7687
+ // Ed25519 OID bytes: 1.3.101.112 (RFC 8410)
7688
+ ED25519_OID_BYTES: [0x06, 0x03, 0x2b, 0x65, 0x70],
7689
+ // PKCS#8 structure length constants
7690
+ PKCS8_ALGORITHM_ID_LENGTH: 0x0b, // SEQUENCE length for algorithm identifier
7691
+ PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH: 0x22, // Outer OCTET STRING length (34 bytes)
7692
+ PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH: 0x20, // Inner OCTET STRING length (32 bytes)
7693
+ };
7694
+ // PRNG (Pseudo-Random Number Generator) constants
7695
+ const PRNG_CONSTANTS = {
7696
+ // Numerical Recipes LCG
7697
+ LCG_MULTIPLIER: 1664525, // LCG multiplier (from Numerical Recipes)
7698
+ LCG_INCREMENT: 1013904223, // LCG increment
7699
+ LCG_MODULUS: 4294967296, // 2^32 modulus for LCG
7700
+ TIMESTAMP_MULTIPLIER: 2654435761, // Golden Ratio constant
7701
+ HASH_SUBSTRING_LENGTH: 8,
7702
+ BYTE_SHIFT: 24,
7703
+ BYTE_MASK: 0xff,
7704
+ };
7705
+ const TX_TYPE = {
7706
+ TRANSFER_BY_ZK: 0,
7707
+ TRANSFER_BY_KEY: 1,
7708
+ USER_CONTENT: 2,
7709
+ };
7710
+ const DECIMALS = 6;
7711
+ class MmnClient {
7712
+ constructor(config) {
7713
+ this.requestId = 0;
7714
+ this.config = {
7715
+ timeout: 30000,
7716
+ headers: {
7717
+ 'Content-Type': 'application/json',
7718
+ Accept: 'application/json',
7719
+ },
7720
+ ...config,
7721
+ };
7722
+ }
7723
+ async makeRequest(method, params) {
7724
+ const request = {
7725
+ jsonrpc: '2.0',
7726
+ method,
7727
+ params,
7728
+ id: ++this.requestId,
7729
+ };
7730
+ // Create AbortController for timeout
7731
+ const controller = new AbortController();
7732
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout || 30000);
7733
+ try {
7734
+ const requestOptions = {
7735
+ method: 'POST',
7736
+ mode: 'cors',
7737
+ credentials: 'omit',
7738
+ signal: controller.signal,
7739
+ headers: this.config.headers || {},
7740
+ body: JSON.stringify(request),
7741
+ };
7742
+ const response = await fetch(this.config.baseUrl, requestOptions);
7743
+ clearTimeout(timeoutId);
7744
+ if (!response.ok) {
7745
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
7746
+ }
7747
+ const result = await response.json();
7748
+ if (result.error) {
7749
+ throw new Error(`JSON-RPC Error ${result.error.code}: ${result.error.message}`);
7750
+ }
7751
+ return result.result;
7752
+ }
7753
+ catch (error) {
7754
+ clearTimeout(timeoutId);
7755
+ if (error instanceof Error) {
7756
+ if (error.name === 'AbortError') {
7757
+ throw new Error(`Request timeout after ${this.config.timeout || 30000}ms`);
7758
+ }
7759
+ throw error;
7760
+ }
7761
+ throw new Error('Unknown error occurred');
7762
+ }
7763
+ }
7764
+ /**
7765
+ * Securely convert raw Ed25519 private key to PKCS#8 format
7766
+ * @param raw - Raw 32-byte Ed25519 private key
7767
+ * @returns PKCS#8 formatted private key in hex
7768
+ * @throws Error if input validation fails
7769
+ */
7770
+ rawEd25519ToPkcs8Hex(raw) {
7771
+ // Input validation
7772
+ if (!BufferCompat.isBuffer(raw)) {
7773
+ throw new Error('Private key must be a Buffer');
7774
+ }
7775
+ if (raw.length !== CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH) {
7776
+ throw new Error(`Ed25519 private key must be exactly ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH} bytes`);
7777
+ }
7778
+ try {
7779
+ // Ed25519 OID: 1.3.101.112 (RFC 8410 - Algorithm Identifiers for Ed25519)
7780
+ const ED25519_OID = BufferCompat.from(CRYPTO_CONSTANTS.ED25519_OID_BYTES);
7781
+ const VERSION_BYTES = BufferCompat.from([
7782
+ CRYPTO_CONSTANTS.ASN1_INTEGER_TAG,
7783
+ 0x01, // Length of integer (1 byte)
7784
+ CRYPTO_CONSTANTS.PKCS8_VERSION,
7785
+ ]);
7786
+ // Create algorithm identifier sequence (AlgorithmIdentifier)
7787
+ const algorithmId = BufferCompat.concat([
7788
+ BufferCompat.from([
7789
+ CRYPTO_CONSTANTS.ASN1_SEQUENCE_TAG,
7790
+ CRYPTO_CONSTANTS.PKCS8_ALGORITHM_ID_LENGTH,
7791
+ ]),
7792
+ ED25519_OID,
7793
+ ]);
7794
+ // Create private key octet string (wrapped Ed25519 private key)
7795
+ const privateKeyOctetString = BufferCompat.concat([
7796
+ BufferCompat.from([
7797
+ CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7798
+ CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH,
7799
+ ]), // OCTET STRING, length 34
7800
+ BufferCompat.from([
7801
+ CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7802
+ CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH,
7803
+ ]), // inner OCTET STRING, length 32
7804
+ raw,
7805
+ ]);
7806
+ // Create PKCS#8 body
7807
+ const pkcs8Body = BufferCompat.concat([
7808
+ VERSION_BYTES,
7809
+ algorithmId,
7810
+ privateKeyOctetString,
7811
+ ]);
7812
+ // Create final PKCS#8 structure
7813
+ const pkcs8 = BufferCompat.concat([
7814
+ BufferCompat.from([CRYPTO_CONSTANTS.ASN1_SEQUENCE_TAG]), // SEQUENCE
7815
+ this.encodeLength(pkcs8Body.length),
7816
+ pkcs8Body,
7817
+ ]);
7818
+ const result = pkcs8.toString('hex');
7819
+ // Clear sensitive data from memory
7820
+ raw.fill(0);
7821
+ privateKeyOctetString.fill(0);
7822
+ pkcs8Body.fill(0);
7823
+ pkcs8.fill(0);
7824
+ return result;
7825
+ }
7826
+ catch (error) {
7827
+ // Clear sensitive data on error
7828
+ raw.fill(0);
7829
+ throw new Error(`Failed to convert private key to PKCS#8: ${error instanceof Error ? error.message : 'Unknown error'}`);
7830
+ }
7831
+ }
7832
+ /**
7833
+ * Encode length in ASN.1 DER format
7834
+ * ASN.1 length encoding rules:
7835
+ * - Short form (0-127): single byte with the length value
7836
+ * - Long form (128+): first byte is 0x80 + number of length bytes, followed by length bytes
7837
+ * @param length - The length value to encode
7838
+ * @returns ASN.1 DER encoded length bytes
7839
+ */
7840
+ encodeLength(length) {
7841
+ if (length < CRYPTO_CONSTANTS.ASN1_LENGTH) {
7842
+ return BufferCompat.from([length]);
7843
+ }
7844
+ const bytes = [];
7845
+ let len = length;
7846
+ while (len > 0) {
7847
+ bytes.unshift(len & PRNG_CONSTANTS.BYTE_MASK);
7848
+ len >>= 8;
7849
+ }
7850
+ return BufferCompat.from([
7851
+ CRYPTO_CONSTANTS.ASN1_LENGTH | bytes.length,
7852
+ ...bytes,
7853
+ ]);
7854
+ }
7855
+ /**
7856
+ * Generate secure entropy using multiple sources for maximum compatibility
7857
+ * @returns Array of 32 random bytes
7858
+ */
7859
+ generateSecureEntropy() {
7860
+ const entropy = [];
7861
+ const targetLength = CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH;
7862
+ // Use multiple entropy sources
7863
+ const now = Date.now();
7864
+ const performance = typeof window !== 'undefined' && window.performance
7865
+ ? window.performance.now()
7866
+ : now;
7867
+ const random = Math.random();
7868
+ // Create initial seed from timestamp and random
7869
+ let seed = now + performance + random;
7870
+ // Generate bytes using Linear Congruential Generator (LCG) with multiple entropy sources
7871
+ // This provides a fallback Pseudorandom Number Generator (PRNG) when crypto.getRandomValues is not available
7872
+ for (let i = 0; i < targetLength; i++) {
7873
+ // Xₙ₊₁ = (a * Xₙ + c) mod m
7874
+ seed =
7875
+ (seed * PRNG_CONSTANTS.LCG_MULTIPLIER + PRNG_CONSTANTS.LCG_INCREMENT) %
7876
+ PRNG_CONSTANTS.LCG_MODULUS;
7877
+ // Mix with timestamp to add time-based entropy
7878
+ seed ^= (now + i) * PRNG_CONSTANTS.TIMESTAMP_MULTIPLIER;
7879
+ // Mix with Math.random() for additional browser-provided randomness
7880
+ seed ^= Math.floor(Math.random() * PRNG_CONSTANTS.LCG_MODULUS);
7881
+ // Additional cryptographic mixing using SHA256 if CryptoJS is available
7882
+ if (typeof CryptoJS !== 'undefined') {
7883
+ const hashInput = seed.toString() + i.toString() + now.toString();
7884
+ const hash = CryptoJS.SHA256(hashInput).toString();
7885
+ // Extract first 8 hex characters (32 bits) from hash for mixing
7886
+ seed ^= parseInt(hash.substring(0, PRNG_CONSTANTS.HASH_SUBSTRING_LENGTH), 16);
7887
+ }
7888
+ entropy.push((seed >>> PRNG_CONSTANTS.BYTE_SHIFT) & PRNG_CONSTANTS.BYTE_MASK);
7889
+ }
7890
+ return entropy;
7891
+ }
7892
+ /**
7893
+ * Securely generate ephemeral key pair with proper entropy
7894
+ * React Native compatible version with multiple fallbacks
7895
+ * @returns Ephemeral key pair with private and public keys
7896
+ * @throws Error if key generation fails
7897
+ */
7898
+ generateEphemeralKeyPair() {
7899
+ try {
7900
+ let seed;
7901
+ // Try multiple approaches for mobile compatibility
7902
+ try {
7903
+ // Method 1: Try nacl.randomBytes first
7904
+ seed = nacl.randomBytes(CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH);
7905
+ }
7906
+ catch (naclError) {
7907
+ try {
7908
+ // Method 2: Use crypto.getRandomValues if available (browsers/React Native)
7909
+ if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
7910
+ seed = new Uint8Array(CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH);
7911
+ crypto.getRandomValues(seed);
7912
+ }
7913
+ else {
7914
+ throw new Error('crypto.getRandomValues not available');
7915
+ }
7916
+ }
7917
+ catch (cryptoError) {
7918
+ // Method 3: Fallback to secure pseudo-random generation
7919
+ const entropy = this.generateSecureEntropy();
7920
+ seed = new Uint8Array(entropy);
7921
+ }
7922
+ }
7923
+ // Validate seed length
7924
+ if (seed.length !== CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH) {
7925
+ throw new Error(`Invalid seed length: expected ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH}, got ${seed.length}`);
7926
+ }
7927
+ // Generate key pair from seed
7928
+ const keyPair = nacl.sign.keyPair.fromSeed(seed);
7929
+ const publicKeyBytes = keyPair.publicKey;
7930
+ // Validate public key
7931
+ if (publicKeyBytes.length !== CRYPTO_CONSTANTS.ED25519_PUBLIC_KEY_LENGTH) {
7932
+ throw new Error(`Invalid public key length: expected ${CRYPTO_CONSTANTS.ED25519_PUBLIC_KEY_LENGTH}, got ${publicKeyBytes.length}`);
7933
+ }
7934
+ // Convert private key to PKCS#8 format
7935
+ const privateKeyHex = this.rawEd25519ToPkcs8Hex(BufferCompat.from(seed));
7936
+ // Clear sensitive data
7937
+ seed.fill(0);
7938
+ keyPair.secretKey.fill(0);
7939
+ return {
7940
+ privateKey: privateKeyHex,
7941
+ publicKey: bs58.encode(publicKeyBytes),
7942
+ };
7943
+ }
7944
+ catch (error) {
7945
+ throw new Error(`Failed to generate ephemeral key pair: ${error instanceof Error ? error.message : 'Unknown error'}`);
7946
+ }
7947
+ }
7948
+ getAddressFromUserId(userId) {
7949
+ // Use crypto-js for SHA-256 in React Native
7950
+ const hash = CryptoJS.SHA256(userId).toString(CryptoJS.enc.Hex);
7951
+ const hashBuffer = BufferCompat.from(hash, 'hex');
7952
+ return bs58.encode(hashBuffer);
7953
+ }
7954
+ /**
7955
+ * Create and sign a transaction message
7956
+ */
7957
+ createAndSignTx(params) {
7958
+ if (!this.validateAddress(params.sender)) {
7959
+ throw new Error('Invalid sender address');
7960
+ }
7961
+ if (!this.validateAddress(params.recipient)) {
7962
+ throw new Error('Invalid recipient address');
7963
+ }
7964
+ if (params.sender === params.recipient) {
7965
+ throw new Error('Sender and recipient addresses cannot be the same');
7966
+ }
7967
+ const txMsg = {
7968
+ type: params.type,
7969
+ sender: params.sender,
7970
+ recipient: params.recipient,
7971
+ amount: params.amount,
7972
+ timestamp: params.timestamp || Date.now(),
7973
+ text_data: params.textData || '',
7974
+ nonce: params.nonce,
7975
+ extra_info: JSON.stringify(params.extraInfo) || '',
7976
+ zk_proof: params.zkProof || '',
7977
+ zk_pub: params.zkPub || '',
7978
+ };
7979
+ const signature = this.signTransaction(txMsg, params.privateKey);
7980
+ return {
7981
+ tx_msg: txMsg,
7982
+ signature,
7983
+ };
7984
+ }
7985
+ /**
7986
+ * Securely sign a transaction with Ed25519
7987
+ * @param tx - Transaction message to sign
7988
+ * @param privateKeyHex - Private key in PKCS#8 hex format
7989
+ * @returns Base58 encoded signature
7990
+ * @throws Error if signing fails
7991
+ */
7992
+ signTransaction(tx, privateKeyHex) {
7993
+ try {
7994
+ // Validate inputs
7995
+ if (!tx || typeof tx !== 'object') {
7996
+ throw new Error('Invalid transaction object');
7997
+ }
7998
+ if (!privateKeyHex || typeof privateKeyHex !== 'string') {
7999
+ throw new Error('Invalid private key format');
8000
+ }
8001
+ // Serialize transaction data
8002
+ const serializedData = this.serializeTransaction(tx);
8003
+ if (!serializedData || serializedData.length === 0) {
8004
+ throw new Error('Failed to serialize transaction');
8005
+ }
8006
+ // Extract the Ed25519 seed from the private key for nacl signing
8007
+ const privateKeyDer = BufferCompat.from(privateKeyHex, 'hex');
8008
+ if (privateKeyDer.length < CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH) {
8009
+ throw new Error(`Invalid private key length: expected at least ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH} bytes, got ${privateKeyDer.length}`);
8010
+ }
8011
+ const seed = privateKeyDer.subarray(-CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH); // Last 32 bytes
8012
+ const keyPair = nacl.sign.keyPair.fromSeed(seed);
8013
+ // Validate key pair
8014
+ if (!keyPair.publicKey || !keyPair.secretKey) {
8015
+ throw new Error('Failed to create key pair from seed');
8016
+ }
8017
+ // Sign using Ed25519 (nacl) - constant time operation
8018
+ const signature = nacl.sign.detached(serializedData, keyPair.secretKey);
8019
+ if (!signature || signature.length === 0) {
8020
+ throw new Error('Failed to generate signature');
8021
+ }
8022
+ // Clear sensitive data
8023
+ privateKeyDer.fill(0);
8024
+ seed.fill(0);
8025
+ keyPair.secretKey.fill(0);
8026
+ // Return signature based on transaction type
8027
+ if (tx.type === TX_TYPE.TRANSFER_BY_KEY) {
8028
+ return bs58.encode(BufferCompat.from(signature));
8029
+ }
8030
+ // For regular transactions, wrap signature with public key
8031
+ const userSig = {
8032
+ PubKey: BufferCompat.from(keyPair.publicKey).toString('base64'),
8033
+ Sig: BufferCompat.from(signature).toString('base64'),
8034
+ };
8035
+ return bs58.encode(BufferCompat.from(JSON.stringify(userSig)));
8036
+ }
8037
+ catch (error) {
8038
+ throw new Error(`Transaction signing failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
8039
+ }
8040
+ }
8041
+ /**
8042
+ * Serialize transaction for signing
8043
+ */
8044
+ serializeTransaction(tx) {
8045
+ const data = `${tx.type}|${tx.sender}|${tx.recipient}|${tx.amount}|${tx.text_data}|${tx.nonce}|${tx.extra_info}`;
8046
+ return BufferCompat.from(data, 'utf8');
8047
+ }
8048
+ /**
8049
+ * Add a signed transaction to the blockchain
8050
+ */
8051
+ async addTx(signedTx) {
8052
+ return this.makeRequest('tx.addtx', signedTx);
8053
+ }
8054
+ /**
8055
+ * Send a transaction (create, sign, and submit)
8056
+ */
8057
+ async sendTransaction(params) {
8058
+ const fromAddress = this.getAddressFromUserId(params.sender);
8059
+ const toAddress = this.getAddressFromUserId(params.recipient);
8060
+ const signedTx = this.createAndSignTx({
8061
+ ...params,
8062
+ type: TX_TYPE.TRANSFER_BY_ZK,
8063
+ sender: fromAddress,
8064
+ recipient: toAddress,
8065
+ });
8066
+ return this.addTx(signedTx);
8067
+ }
8068
+ async sendTransactionByAddress(params) {
8069
+ const signedTx = this.createAndSignTx({
8070
+ ...params,
8071
+ type: TX_TYPE.TRANSFER_BY_ZK,
8072
+ });
8073
+ return this.addTx(signedTx);
8074
+ }
8075
+ async sendTransactionByPrivateKey(params) {
8076
+ const signedTx = this.createAndSignTx({
8077
+ ...params,
8078
+ type: TX_TYPE.TRANSFER_BY_KEY,
8079
+ });
8080
+ return this.addTx(signedTx);
8081
+ }
8082
+ async postDonationCampaignFeed(params) {
8083
+ const signedTx = this.createAndSignTx({
8084
+ ...params,
8085
+ type: TX_TYPE.USER_CONTENT,
8086
+ });
8087
+ return this.addTx(signedTx);
8088
+ }
8089
+ /**
8090
+ * Get current nonce for an account
8091
+ */
8092
+ async getCurrentNonce(userId, tag = 'latest') {
8093
+ const address = this.getAddressFromUserId(userId);
8094
+ return this.makeRequest('account.getcurrentnonce', { address, tag });
8095
+ }
8096
+ async getAccountByUserId(userId) {
8097
+ const address = this.getAddressFromUserId(userId);
8098
+ return this.makeRequest('account.getaccount', {
8099
+ address,
8100
+ });
8101
+ }
8102
+ scaleAmountToDecimals(originalAmount, decimals = DECIMALS) {
8103
+ let scaledAmount = BigInt(originalAmount);
8104
+ for (let i = 0; i < decimals; i++) {
8105
+ scaledAmount = scaledAmount * BigInt(10);
8106
+ }
8107
+ return scaledAmount.toString();
8108
+ }
8109
+ validateAddress(addr) {
8110
+ const decoded = bs58.decode(addr);
8111
+ if (!decoded ||
8112
+ decoded.length !== CRYPTO_CONSTANTS.ED25519_PUBLIC_KEY_LENGTH) {
8113
+ return false;
8114
+ }
8115
+ return true;
8116
+ }
8117
+ validateAmount(balance, amount) {
8118
+ const bigBalance = BigInt(balance);
8119
+ const bigAmount = BigInt(typeof amount === 'number' ? this.scaleAmountToDecimals(amount) : amount);
8120
+ return bigAmount <= bigBalance;
8121
+ }
8122
+ }
8123
+ function createMmnClient(config) {
8124
+ return new MmnClient(config);
8114
8125
  }
8115
8126
 
8116
- // --- JSON-RPC Types ---
8117
- var ETransferType;
8118
- (function (ETransferType) {
8119
- ETransferType["GiveCoffee"] = "give_coffee";
8120
- ETransferType["TransferToken"] = "transfer_token";
8121
- ETransferType["UnlockItem"] = "unlock_item";
8122
- })(ETransferType || (ETransferType = {}));
8123
- var EZkClientType;
8124
- (function (EZkClientType) {
8125
- EZkClientType["MEZON"] = "mezon";
8126
- EZkClientType["OAUTH"] = "oauth";
8127
+ // --- JSON-RPC Types ---
8128
+ var ETransferType;
8129
+ (function (ETransferType) {
8130
+ ETransferType["GiveCoffee"] = "give_coffee";
8131
+ ETransferType["TransferToken"] = "transfer_token";
8132
+ ETransferType["UnlockItem"] = "unlock_item";
8133
+ })(ETransferType || (ETransferType = {}));
8134
+ var EZkClientType;
8135
+ (function (EZkClientType) {
8136
+ EZkClientType["MEZON"] = "mezon";
8137
+ EZkClientType["OAUTH"] = "oauth";
8127
8138
  })(EZkClientType || (EZkClientType = {}));
8128
8139
 
8129
- class ZkClient {
8130
- constructor(config) {
8131
- this.endpoint = config.endpoint;
8132
- this.timeout = config.timeout || 30000;
8133
- this.headers = {
8134
- Accept: 'application/json',
8135
- 'Content-Type': 'application/json',
8136
- ...(config.headers || {}),
8137
- };
8138
- }
8139
- async makeRequest(method, path, params, body) {
8140
- let url = `${this.endpoint}/${path}`;
8141
- // Add query parameters for GET requests
8142
- if (params && Object.keys(params).length > 0) {
8143
- const searchParams = new URLSearchParams();
8144
- Object.entries(params).forEach(([key, value]) => {
8145
- searchParams.append(key, String(value));
8146
- });
8147
- url += `?${searchParams.toString()}`;
8148
- }
8149
- // Create AbortController for timeout
8150
- const controller = new AbortControllerPolyfill();
8151
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8152
- try {
8153
- const requestOptions = {
8154
- method,
8155
- mode: 'cors',
8156
- credentials: 'omit',
8157
- signal: controller.signal,
8158
- headers: this.headers,
8159
- };
8160
- // Add body for POST requests
8161
- if (method === 'POST' && body) {
8162
- requestOptions.body = JSON.stringify(body);
8163
- }
8164
- const response = await fetchPolyfill(url, requestOptions);
8165
- clearTimeout(timeoutId);
8166
- if (!response.ok) {
8167
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
8168
- }
8169
- const data = await response.json();
8170
- return data;
8171
- }
8172
- catch (error) {
8173
- clearTimeout(timeoutId);
8174
- if (error instanceof Error) {
8175
- if (error.name === 'AbortError') {
8176
- throw new Error(`Request timeout after ${this.timeout}ms`);
8177
- }
8178
- throw error;
8179
- }
8180
- throw new Error('Request failed');
8181
- }
8182
- }
8183
- async getZkProofs({ userId, ephemeralPublicKey, jwt, address, clientType = EZkClientType.MEZON, }) {
8184
- const path = `prove`;
8185
- const res = await this.makeRequest('POST', path, undefined, {
8186
- user_id: userId,
8187
- ephemeral_pk: ephemeralPublicKey,
8188
- jwt,
8189
- address,
8190
- client_type: clientType,
8191
- });
8192
- return res.data;
8193
- }
8140
+ class ZkClient {
8141
+ constructor(config) {
8142
+ this.endpoint = config.endpoint;
8143
+ this.timeout = config.timeout || 30000;
8144
+ this.headers = {
8145
+ Accept: 'application/json',
8146
+ 'Content-Type': 'application/json',
8147
+ ...(config.headers || {}),
8148
+ };
8149
+ }
8150
+ async makeRequest(method, path, params, body) {
8151
+ let url = `${this.endpoint}/${path}`;
8152
+ // Add query parameters for GET requests
8153
+ if (params && Object.keys(params).length > 0) {
8154
+ const searchParams = new URLSearchParams();
8155
+ Object.entries(params).forEach(([key, value]) => {
8156
+ searchParams.append(key, String(value));
8157
+ });
8158
+ url += `?${searchParams.toString()}`;
8159
+ }
8160
+ // Create AbortController for timeout
8161
+ const controller = new AbortController();
8162
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8163
+ try {
8164
+ const requestOptions = {
8165
+ method,
8166
+ mode: 'cors',
8167
+ credentials: 'omit',
8168
+ signal: controller.signal,
8169
+ headers: this.headers,
8170
+ };
8171
+ // Add body for POST requests
8172
+ if (method === 'POST' && body) {
8173
+ requestOptions.body = JSON.stringify(body);
8174
+ }
8175
+ const response = await fetch(url, requestOptions);
8176
+ clearTimeout(timeoutId);
8177
+ if (!response.ok) {
8178
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
8179
+ }
8180
+ const data = await response.json();
8181
+ return data;
8182
+ }
8183
+ catch (error) {
8184
+ clearTimeout(timeoutId);
8185
+ if (error instanceof Error) {
8186
+ if (error.name === 'AbortError') {
8187
+ throw new Error(`Request timeout after ${this.timeout}ms`);
8188
+ }
8189
+ throw error;
8190
+ }
8191
+ throw new Error('Request failed');
8192
+ }
8193
+ }
8194
+ async getZkProofs({ userId, ephemeralPublicKey, jwt, address, clientType = EZkClientType.MEZON, }) {
8195
+ const path = `prove`;
8196
+ const res = await this.makeRequest('POST', path, undefined, {
8197
+ user_id: userId,
8198
+ ephemeral_pk: ephemeralPublicKey,
8199
+ jwt,
8200
+ address,
8201
+ client_type: clientType,
8202
+ });
8203
+ return res.data;
8204
+ }
8194
8205
  }
8195
8206
 
8196
8207
  export { ETransferType, EZkClientType, IndexerClient, MmnClient, ZkClient, createMmnClient };