mmn-client-js 1.0.6 → 1.0.7

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.js CHANGED
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var axios = require('axios');
4
3
  var bs58 = require('bs58');
5
4
  var nacl = require('tweetnacl');
6
5
 
@@ -13,24 +12,74 @@ class IndexerClient {
13
12
  constructor(config) {
14
13
  this.endpoint = config.endpoint;
15
14
  this.chainId = config.chainId;
16
- this.axiosInstance = axios.create({
17
- baseURL: this.endpoint,
18
- timeout: config.timeout || 30000,
19
- headers: {
20
- 'Content-Type': 'application/json',
21
- Accept: 'application/json',
22
- ...(config.headers || {}),
23
- },
24
- });
15
+ this.timeout = config.timeout || 30000;
16
+ // Minimal headers to avoid CORS preflight issues
17
+ this.headers = {
18
+ Accept: 'application/json',
19
+ ...(config.headers || {}),
20
+ };
25
21
  }
22
+ /**
23
+ * Make HTTP request with automatic CORS handling
24
+ * Works out-of-the-box without CORS configuration
25
+ * @param method - HTTP method (GET or POST)
26
+ * @param path - API endpoint path
27
+ * @param params - URL query parameters
28
+ * @param body - Request body for POST requests
29
+ * @returns Promise resolving to response data
30
+ */
26
31
  async makeRequest(method, path, params, body) {
27
- const resp = await this.axiosInstance.request({
28
- method,
29
- url: path,
30
- params,
31
- data: body,
32
- });
33
- return resp.data;
32
+ // Build full URL
33
+ let url = `${this.endpoint}/${path}`;
34
+ // Add query parameters
35
+ if (params && Object.keys(params).length > 0) {
36
+ const searchParams = new URLSearchParams();
37
+ Object.entries(params).forEach(([key, value]) => {
38
+ searchParams.append(key, String(value));
39
+ });
40
+ url += `?${searchParams.toString()}`;
41
+ }
42
+ // Create AbortController for timeout
43
+ const controller = new AbortController();
44
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
45
+ try {
46
+ // Simple fetch with automatic CORS handling
47
+ const requestOptions = {
48
+ method,
49
+ mode: 'cors',
50
+ credentials: 'omit',
51
+ signal: controller.signal,
52
+ headers: {
53
+ Accept: 'application/json',
54
+ ...this.headers,
55
+ },
56
+ };
57
+ // Add body and Content-Type for POST requests
58
+ if (method === 'POST' && body) {
59
+ requestOptions.body = JSON.stringify(body);
60
+ requestOptions.headers['Content-Type'] =
61
+ 'application/json';
62
+ }
63
+ const response = await fetch(url, requestOptions);
64
+ clearTimeout(timeoutId);
65
+ // Handle response errors
66
+ if (!response.ok) {
67
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
68
+ }
69
+ // Parse JSON response
70
+ const data = await response.json();
71
+ return data;
72
+ }
73
+ catch (error) {
74
+ clearTimeout(timeoutId);
75
+ if (error instanceof Error) {
76
+ if (error.name === 'AbortError') {
77
+ throw new Error(`Request timeout after ${this.timeout}ms`);
78
+ }
79
+ throw error;
80
+ }
81
+ throw new Error('Request failed');
82
+ }
34
83
  }
35
84
  async getTransactionByHash(hash) {
36
85
  const path = `${this.chainId}/tx/${hash}/detail`;
@@ -7606,9 +7655,28 @@ const CRYPTO_CONSTANTS = {
7606
7655
  ED25519_PUBLIC_KEY_LENGTH: 32,
7607
7656
  MNEMONIC_ENTROPY_BITS: 128,
7608
7657
  PKCS8_VERSION: 0,
7658
+ // ASN.1 DER encoding
7609
7659
  ASN1_SEQUENCE_TAG: 0x30,
7610
7660
  ASN1_OCTET_STRING_TAG: 0x04,
7611
7661
  ASN1_INTEGER_TAG: 0x02,
7662
+ ASN1_LENGTH: 0x80,
7663
+ // Ed25519 OID bytes: 1.3.101.112 (RFC 8410)
7664
+ ED25519_OID_BYTES: [0x06, 0x03, 0x2b, 0x65, 0x70],
7665
+ // PKCS#8 structure length constants
7666
+ PKCS8_ALGORITHM_ID_LENGTH: 0x0b, // SEQUENCE length for algorithm identifier
7667
+ PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH: 0x22, // Outer OCTET STRING length (34 bytes)
7668
+ PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH: 0x20, // Inner OCTET STRING length (32 bytes)
7669
+ };
7670
+ // PRNG (Pseudo-Random Number Generator) constants
7671
+ const PRNG_CONSTANTS = {
7672
+ // Numerical Recipes LCG
7673
+ LCG_MULTIPLIER: 1664525, // LCG multiplier (from Numerical Recipes)
7674
+ LCG_INCREMENT: 1013904223, // LCG increment
7675
+ LCG_MODULUS: 4294967296, // 2^32 modulus for LCG
7676
+ TIMESTAMP_MULTIPLIER: 2654435761, // Golden Ratio constant
7677
+ HASH_SUBSTRING_LENGTH: 8,
7678
+ BYTE_SHIFT: 24,
7679
+ BYTE_MASK: 0xff,
7612
7680
  };
7613
7681
  const TX_TYPE = {
7614
7682
  TRANSFER: 0,
@@ -7622,15 +7690,10 @@ class MmnClient {
7622
7690
  timeout: 30000,
7623
7691
  headers: {
7624
7692
  'Content-Type': 'application/json',
7693
+ Accept: 'application/json',
7625
7694
  },
7626
7695
  ...config,
7627
7696
  };
7628
- this.axiosInstance = axios.create({
7629
- baseURL: this.config.baseUrl,
7630
- timeout: this.config.timeout || 30000,
7631
- headers: this.config.headers || {},
7632
- ...(this.config.axiosConfig || {}),
7633
- });
7634
7697
  }
7635
7698
  async makeRequest(method, params) {
7636
7699
  const request = {
@@ -7639,30 +7702,36 @@ class MmnClient {
7639
7702
  params,
7640
7703
  id: ++this.requestId,
7641
7704
  };
7705
+ // Create AbortController for timeout
7706
+ const controller = new AbortController();
7707
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout || 30000);
7642
7708
  try {
7643
- const response = await this.axiosInstance.post('', request);
7644
- const result = response.data;
7709
+ const requestOptions = {
7710
+ method: 'POST',
7711
+ mode: 'cors',
7712
+ credentials: 'omit',
7713
+ signal: controller.signal,
7714
+ headers: this.config.headers || {},
7715
+ body: JSON.stringify(request),
7716
+ };
7717
+ const response = await fetch(this.config.baseUrl, requestOptions);
7718
+ console.log('🚀 ~ MmnClient ~ makeRequest ~ response:', response);
7719
+ clearTimeout(timeoutId);
7720
+ if (!response.ok) {
7721
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
7722
+ }
7723
+ const result = await response.json();
7645
7724
  if (result.error) {
7646
7725
  throw new Error(`JSON-RPC Error ${result.error.code}: ${result.error.message}`);
7647
7726
  }
7648
7727
  return result.result;
7649
7728
  }
7650
7729
  catch (error) {
7651
- if (axios.isAxiosError(error)) {
7652
- if (error.response) {
7653
- // Server responded with error status
7654
- throw new Error(`HTTP ${error.response.status}: ${error.response.statusText}`);
7655
- }
7656
- else if (error.request) {
7657
- // Request was made but no response received
7658
- throw new Error('Network error: No response received');
7659
- }
7660
- else {
7661
- // Something else happened
7662
- throw new Error(`Request error: ${error.message}`);
7663
- }
7664
- }
7730
+ clearTimeout(timeoutId);
7665
7731
  if (error instanceof Error) {
7732
+ if (error.name === 'AbortError') {
7733
+ throw new Error(`Request timeout after ${this.config.timeout || 30000}ms`);
7734
+ }
7666
7735
  throw error;
7667
7736
  }
7668
7737
  throw new Error('Unknown error occurred');
@@ -7683,22 +7752,31 @@ class MmnClient {
7683
7752
  throw new Error(`Ed25519 private key must be exactly ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH} bytes`);
7684
7753
  }
7685
7754
  try {
7686
- // Ed25519 OID: 1.3.101.112 (constant-time)
7687
- const ED25519_OID = BufferCompat.from([0x06, 0x03, 0x2b, 0x65, 0x70]);
7755
+ // Ed25519 OID: 1.3.101.112 (RFC 8410 - Algorithm Identifiers for Ed25519)
7756
+ const ED25519_OID = BufferCompat.from(CRYPTO_CONSTANTS.ED25519_OID_BYTES);
7688
7757
  const VERSION_BYTES = BufferCompat.from([
7689
7758
  CRYPTO_CONSTANTS.ASN1_INTEGER_TAG,
7690
- 0x01,
7759
+ 0x01, // Length of integer (1 byte)
7691
7760
  CRYPTO_CONSTANTS.PKCS8_VERSION,
7692
- ]); // INTEGER 0
7693
- // Create algorithm identifier sequence
7761
+ ]);
7762
+ // Create algorithm identifier sequence (AlgorithmIdentifier)
7694
7763
  const algorithmId = BufferCompat.concat([
7695
- BufferCompat.from([0x30, 0x0b]), // SEQUENCE, length 11
7764
+ BufferCompat.from([
7765
+ CRYPTO_CONSTANTS.ASN1_SEQUENCE_TAG,
7766
+ CRYPTO_CONSTANTS.PKCS8_ALGORITHM_ID_LENGTH,
7767
+ ]),
7696
7768
  ED25519_OID,
7697
7769
  ]);
7698
- // Create private key octet string
7770
+ // Create private key octet string (wrapped Ed25519 private key)
7699
7771
  const privateKeyOctetString = BufferCompat.concat([
7700
- BufferCompat.from([CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG, 0x22]), // OCTET STRING, length 34
7701
- BufferCompat.from([CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG, 0x20]), // inner OCTET STRING, length 32
7772
+ BufferCompat.from([
7773
+ CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7774
+ CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH,
7775
+ ]), // OCTET STRING, length 34
7776
+ BufferCompat.from([
7777
+ CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7778
+ CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH,
7779
+ ]), // inner OCTET STRING, length 32
7702
7780
  raw,
7703
7781
  ]);
7704
7782
  // Create PKCS#8 body
@@ -7727,17 +7805,28 @@ class MmnClient {
7727
7805
  throw new Error(`Failed to convert private key to PKCS#8: ${error instanceof Error ? error.message : 'Unknown error'}`);
7728
7806
  }
7729
7807
  }
7808
+ /**
7809
+ * Encode length in ASN.1 DER format
7810
+ * ASN.1 length encoding rules:
7811
+ * - Short form (0-127): single byte with the length value
7812
+ * - Long form (128+): first byte is 0x80 + number of length bytes, followed by length bytes
7813
+ * @param length - The length value to encode
7814
+ * @returns ASN.1 DER encoded length bytes
7815
+ */
7730
7816
  encodeLength(length) {
7731
- if (length < 0x80) {
7817
+ if (length < CRYPTO_CONSTANTS.ASN1_LENGTH) {
7732
7818
  return BufferCompat.from([length]);
7733
7819
  }
7734
7820
  const bytes = [];
7735
7821
  let len = length;
7736
7822
  while (len > 0) {
7737
- bytes.unshift(len & 0xff);
7823
+ bytes.unshift(len & PRNG_CONSTANTS.BYTE_MASK);
7738
7824
  len >>= 8;
7739
7825
  }
7740
- return BufferCompat.from([0x80 | bytes.length, ...bytes]);
7826
+ return BufferCompat.from([
7827
+ CRYPTO_CONSTANTS.ASN1_LENGTH | bytes.length,
7828
+ ...bytes,
7829
+ ]);
7741
7830
  }
7742
7831
  /**
7743
7832
  * Generate secure entropy using multiple sources for maximum compatibility
@@ -7754,19 +7843,25 @@ class MmnClient {
7754
7843
  const random = Math.random();
7755
7844
  // Create initial seed from timestamp and random
7756
7845
  let seed = now + performance + random;
7757
- // Generate bytes using linear congruential generator with multiple mixing
7846
+ // Generate bytes using Linear Congruential Generator (LCG) with multiple entropy sources
7847
+ // This provides a fallback Pseudorandom Number Generator (PRNG) when crypto.getRandomValues is not available
7758
7848
  for (let i = 0; i < targetLength; i++) {
7759
- // Mix multiple sources
7760
- seed = (seed * 1664525 + 1013904223) % 4294967296; // LCG
7761
- seed ^= (now + i) * 2654435761; // Mix with timestamp
7762
- seed ^= Math.floor(Math.random() * 4294967296); // Mix with Math.random
7763
- // Additional mixing with crypto-js if available
7849
+ // Xₙ₊₁ = (a * Xₙ + c) mod m
7850
+ seed =
7851
+ (seed * PRNG_CONSTANTS.LCG_MULTIPLIER + PRNG_CONSTANTS.LCG_INCREMENT) %
7852
+ PRNG_CONSTANTS.LCG_MODULUS;
7853
+ // Mix with timestamp to add time-based entropy
7854
+ seed ^= (now + i) * PRNG_CONSTANTS.TIMESTAMP_MULTIPLIER;
7855
+ // Mix with Math.random() for additional browser-provided randomness
7856
+ seed ^= Math.floor(Math.random() * PRNG_CONSTANTS.LCG_MODULUS);
7857
+ // Additional cryptographic mixing using SHA256 if CryptoJS is available
7764
7858
  if (typeof CryptoJS !== 'undefined') {
7765
7859
  const hashInput = seed.toString() + i.toString() + now.toString();
7766
7860
  const hash = CryptoJS.SHA256(hashInput).toString();
7767
- seed ^= parseInt(hash.substring(0, 8), 16);
7861
+ // Extract first 8 hex characters (32 bits) from hash for mixing
7862
+ seed ^= parseInt(hash.substring(0, PRNG_CONSTANTS.HASH_SUBSTRING_LENGTH), 16);
7768
7863
  }
7769
- entropy.push((seed >>> 24) & 0xff);
7864
+ entropy.push((seed >>> PRNG_CONSTANTS.BYTE_SHIFT) & PRNG_CONSTANTS.BYTE_MASK);
7770
7865
  }
7771
7866
  return entropy;
7772
7867
  }
@@ -7971,24 +8066,56 @@ exports.ETransferType = void 0;
7971
8066
  class ZkClient {
7972
8067
  constructor(config) {
7973
8068
  this.endpoint = config.endpoint;
7974
- this.axiosInstance = axios.create({
7975
- baseURL: this.endpoint,
7976
- timeout: config.timeout || 30000,
7977
- headers: {
7978
- 'Content-Type': 'application/json',
7979
- Accept: 'application/json',
7980
- ...(config.headers || {}),
7981
- },
7982
- });
8069
+ this.timeout = config.timeout || 30000;
8070
+ this.headers = {
8071
+ Accept: 'application/json',
8072
+ 'Content-Type': 'application/json',
8073
+ ...(config.headers || {}),
8074
+ };
7983
8075
  }
7984
8076
  async makeRequest(method, path, params, body) {
7985
- const resp = await this.axiosInstance.request({
7986
- method,
7987
- url: path,
7988
- params,
7989
- data: body,
7990
- });
7991
- return resp.data;
8077
+ let url = `${this.endpoint}/${path}`;
8078
+ // Add query parameters for GET requests
8079
+ if (params && Object.keys(params).length > 0) {
8080
+ const searchParams = new URLSearchParams();
8081
+ Object.entries(params).forEach(([key, value]) => {
8082
+ searchParams.append(key, String(value));
8083
+ });
8084
+ url += `?${searchParams.toString()}`;
8085
+ }
8086
+ // Create AbortController for timeout
8087
+ const controller = new AbortController();
8088
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8089
+ try {
8090
+ const requestOptions = {
8091
+ method,
8092
+ mode: 'cors',
8093
+ credentials: 'omit',
8094
+ signal: controller.signal,
8095
+ headers: this.headers,
8096
+ };
8097
+ // Add body for POST requests
8098
+ if (method === 'POST' && body) {
8099
+ requestOptions.body = JSON.stringify(body);
8100
+ }
8101
+ const response = await fetch(url, requestOptions);
8102
+ clearTimeout(timeoutId);
8103
+ if (!response.ok) {
8104
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
8105
+ }
8106
+ const data = await response.json();
8107
+ return data;
8108
+ }
8109
+ catch (error) {
8110
+ clearTimeout(timeoutId);
8111
+ if (error instanceof Error) {
8112
+ if (error.name === 'AbortError') {
8113
+ throw new Error(`Request timeout after ${this.timeout}ms`);
8114
+ }
8115
+ throw error;
8116
+ }
8117
+ throw new Error('Request failed');
8118
+ }
7992
8119
  }
7993
8120
  async getZkProofs({ userId, ephemeralPublicKey, jwt, address, }) {
7994
8121
  const path = `prove`;