mmn-client-js 1.0.6 → 1.0.8

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,35 @@ 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
+ clearTimeout(timeoutId);
7719
+ if (!response.ok) {
7720
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
7721
+ }
7722
+ const result = await response.json();
7645
7723
  if (result.error) {
7646
7724
  throw new Error(`JSON-RPC Error ${result.error.code}: ${result.error.message}`);
7647
7725
  }
7648
7726
  return result.result;
7649
7727
  }
7650
7728
  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
- }
7729
+ clearTimeout(timeoutId);
7665
7730
  if (error instanceof Error) {
7731
+ if (error.name === 'AbortError') {
7732
+ throw new Error(`Request timeout after ${this.config.timeout || 30000}ms`);
7733
+ }
7666
7734
  throw error;
7667
7735
  }
7668
7736
  throw new Error('Unknown error occurred');
@@ -7683,22 +7751,31 @@ class MmnClient {
7683
7751
  throw new Error(`Ed25519 private key must be exactly ${CRYPTO_CONSTANTS.ED25519_PRIVATE_KEY_LENGTH} bytes`);
7684
7752
  }
7685
7753
  try {
7686
- // Ed25519 OID: 1.3.101.112 (constant-time)
7687
- const ED25519_OID = BufferCompat.from([0x06, 0x03, 0x2b, 0x65, 0x70]);
7754
+ // Ed25519 OID: 1.3.101.112 (RFC 8410 - Algorithm Identifiers for Ed25519)
7755
+ const ED25519_OID = BufferCompat.from(CRYPTO_CONSTANTS.ED25519_OID_BYTES);
7688
7756
  const VERSION_BYTES = BufferCompat.from([
7689
7757
  CRYPTO_CONSTANTS.ASN1_INTEGER_TAG,
7690
- 0x01,
7758
+ 0x01, // Length of integer (1 byte)
7691
7759
  CRYPTO_CONSTANTS.PKCS8_VERSION,
7692
- ]); // INTEGER 0
7693
- // Create algorithm identifier sequence
7760
+ ]);
7761
+ // Create algorithm identifier sequence (AlgorithmIdentifier)
7694
7762
  const algorithmId = BufferCompat.concat([
7695
- BufferCompat.from([0x30, 0x0b]), // SEQUENCE, length 11
7763
+ BufferCompat.from([
7764
+ CRYPTO_CONSTANTS.ASN1_SEQUENCE_TAG,
7765
+ CRYPTO_CONSTANTS.PKCS8_ALGORITHM_ID_LENGTH,
7766
+ ]),
7696
7767
  ED25519_OID,
7697
7768
  ]);
7698
- // Create private key octet string
7769
+ // Create private key octet string (wrapped Ed25519 private key)
7699
7770
  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
7771
+ BufferCompat.from([
7772
+ CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7773
+ CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_OUTER_LENGTH,
7774
+ ]), // OCTET STRING, length 34
7775
+ BufferCompat.from([
7776
+ CRYPTO_CONSTANTS.ASN1_OCTET_STRING_TAG,
7777
+ CRYPTO_CONSTANTS.PKCS8_PRIVATE_KEY_OCTET_INNER_LENGTH,
7778
+ ]), // inner OCTET STRING, length 32
7702
7779
  raw,
7703
7780
  ]);
7704
7781
  // Create PKCS#8 body
@@ -7727,17 +7804,28 @@ class MmnClient {
7727
7804
  throw new Error(`Failed to convert private key to PKCS#8: ${error instanceof Error ? error.message : 'Unknown error'}`);
7728
7805
  }
7729
7806
  }
7807
+ /**
7808
+ * Encode length in ASN.1 DER format
7809
+ * ASN.1 length encoding rules:
7810
+ * - Short form (0-127): single byte with the length value
7811
+ * - Long form (128+): first byte is 0x80 + number of length bytes, followed by length bytes
7812
+ * @param length - The length value to encode
7813
+ * @returns ASN.1 DER encoded length bytes
7814
+ */
7730
7815
  encodeLength(length) {
7731
- if (length < 0x80) {
7816
+ if (length < CRYPTO_CONSTANTS.ASN1_LENGTH) {
7732
7817
  return BufferCompat.from([length]);
7733
7818
  }
7734
7819
  const bytes = [];
7735
7820
  let len = length;
7736
7821
  while (len > 0) {
7737
- bytes.unshift(len & 0xff);
7822
+ bytes.unshift(len & PRNG_CONSTANTS.BYTE_MASK);
7738
7823
  len >>= 8;
7739
7824
  }
7740
- return BufferCompat.from([0x80 | bytes.length, ...bytes]);
7825
+ return BufferCompat.from([
7826
+ CRYPTO_CONSTANTS.ASN1_LENGTH | bytes.length,
7827
+ ...bytes,
7828
+ ]);
7741
7829
  }
7742
7830
  /**
7743
7831
  * Generate secure entropy using multiple sources for maximum compatibility
@@ -7754,19 +7842,25 @@ class MmnClient {
7754
7842
  const random = Math.random();
7755
7843
  // Create initial seed from timestamp and random
7756
7844
  let seed = now + performance + random;
7757
- // Generate bytes using linear congruential generator with multiple mixing
7845
+ // Generate bytes using Linear Congruential Generator (LCG) with multiple entropy sources
7846
+ // This provides a fallback Pseudorandom Number Generator (PRNG) when crypto.getRandomValues is not available
7758
7847
  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
7848
+ // Xₙ₊₁ = (a * Xₙ + c) mod m
7849
+ seed =
7850
+ (seed * PRNG_CONSTANTS.LCG_MULTIPLIER + PRNG_CONSTANTS.LCG_INCREMENT) %
7851
+ PRNG_CONSTANTS.LCG_MODULUS;
7852
+ // Mix with timestamp to add time-based entropy
7853
+ seed ^= (now + i) * PRNG_CONSTANTS.TIMESTAMP_MULTIPLIER;
7854
+ // Mix with Math.random() for additional browser-provided randomness
7855
+ seed ^= Math.floor(Math.random() * PRNG_CONSTANTS.LCG_MODULUS);
7856
+ // Additional cryptographic mixing using SHA256 if CryptoJS is available
7764
7857
  if (typeof CryptoJS !== 'undefined') {
7765
7858
  const hashInput = seed.toString() + i.toString() + now.toString();
7766
7859
  const hash = CryptoJS.SHA256(hashInput).toString();
7767
- seed ^= parseInt(hash.substring(0, 8), 16);
7860
+ // Extract first 8 hex characters (32 bits) from hash for mixing
7861
+ seed ^= parseInt(hash.substring(0, PRNG_CONSTANTS.HASH_SUBSTRING_LENGTH), 16);
7768
7862
  }
7769
- entropy.push((seed >>> 24) & 0xff);
7863
+ entropy.push((seed >>> PRNG_CONSTANTS.BYTE_SHIFT) & PRNG_CONSTANTS.BYTE_MASK);
7770
7864
  }
7771
7865
  return entropy;
7772
7866
  }
@@ -7971,24 +8065,56 @@ exports.ETransferType = void 0;
7971
8065
  class ZkClient {
7972
8066
  constructor(config) {
7973
8067
  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
- });
8068
+ this.timeout = config.timeout || 30000;
8069
+ this.headers = {
8070
+ Accept: 'application/json',
8071
+ 'Content-Type': 'application/json',
8072
+ ...(config.headers || {}),
8073
+ };
7983
8074
  }
7984
8075
  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;
8076
+ let url = `${this.endpoint}/${path}`;
8077
+ // Add query parameters for GET requests
8078
+ if (params && Object.keys(params).length > 0) {
8079
+ const searchParams = new URLSearchParams();
8080
+ Object.entries(params).forEach(([key, value]) => {
8081
+ searchParams.append(key, String(value));
8082
+ });
8083
+ url += `?${searchParams.toString()}`;
8084
+ }
8085
+ // Create AbortController for timeout
8086
+ const controller = new AbortController();
8087
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
8088
+ try {
8089
+ const requestOptions = {
8090
+ method,
8091
+ mode: 'cors',
8092
+ credentials: 'omit',
8093
+ signal: controller.signal,
8094
+ headers: this.headers,
8095
+ };
8096
+ // Add body for POST requests
8097
+ if (method === 'POST' && body) {
8098
+ requestOptions.body = JSON.stringify(body);
8099
+ }
8100
+ const response = await fetch(url, requestOptions);
8101
+ clearTimeout(timeoutId);
8102
+ if (!response.ok) {
8103
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
8104
+ }
8105
+ const data = await response.json();
8106
+ return data;
8107
+ }
8108
+ catch (error) {
8109
+ clearTimeout(timeoutId);
8110
+ if (error instanceof Error) {
8111
+ if (error.name === 'AbortError') {
8112
+ throw new Error(`Request timeout after ${this.timeout}ms`);
8113
+ }
8114
+ throw error;
8115
+ }
8116
+ throw new Error('Request failed');
8117
+ }
7992
8118
  }
7993
8119
  async getZkProofs({ userId, ephemeralPublicKey, jwt, address, }) {
7994
8120
  const path = `prove`;