@diviswap/sdk 1.9.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -886,34 +886,82 @@ Validating partner credentials with ${environment} API...`
886
886
  features,
887
887
  projectRoot: process.cwd()
888
888
  });
889
- if (!options.skipEnv && keyId && secretKey) {
890
- const envFile = framework.includes("nextjs") ? ".env.local" : ".env";
891
- const envPath = path.join(process.cwd(), envFile);
892
- let envContent = "";
893
- if (fs.existsSync(envPath)) {
894
- envContent = fs.readFileSync(envPath, "utf-8");
889
+ if (!options.skipEnv) {
890
+ const envExampleFile = ".env.example";
891
+ const envExamplePath = path.join(process.cwd(), envExampleFile);
892
+ const gitignorePath = path.join(process.cwd(), ".gitignore");
893
+ const envExampleContent = `# Diviswap SDK Configuration (Partner Authentication)
894
+ # IMPORTANT: These are EXAMPLE values only. Replace with your actual credentials.
895
+ # NEVER commit your actual .env or .env.local files to version control!
896
+
897
+ # Partner Key ID (starts with pk_)
898
+ DIVISWAP_PARTNER_KEY_ID=pk_your_key_id_here
899
+
900
+ # Partner Secret Key (starts with sk_)
901
+ # WARNING: Keep this secret! Never share or commit to git.
902
+ # Store securely using environment variables or a secrets manager.
903
+ DIVISWAP_PARTNER_SECRET_KEY=sk_your_secret_key_here
904
+
905
+ # Environment: 'production' or 'sandbox'
906
+ NEXT_PUBLIC_DIVISWAP_ENV=${environment}
907
+ `;
908
+ if (!fs.existsSync(envExamplePath)) {
909
+ fs.appendFileSync(envExamplePath, envExampleContent);
910
+ console.log(
911
+ kleur__default.default.green(`\u2705 Created ${envExampleFile} template`)
912
+ );
895
913
  }
896
- const envVars = [
897
- `DIVISWAP_PARTNER_KEY_ID=${keyId}`,
898
- `DIVISWAP_PARTNER_SECRET_KEY=${secretKey}`,
899
- `NEXT_PUBLIC_DIVISWAP_ENV=${environment}`
900
- ];
901
- const newEnvVars = envVars.filter((envVar) => {
902
- const key = envVar.split("=")[0];
903
- return !envContent.includes(key);
904
- });
905
- if (newEnvVars.length > 0) {
906
- const separator = envContent && !envContent.endsWith("\n") ? "\n" : "";
914
+ let gitignoreContent = "";
915
+ if (fs.existsSync(gitignorePath)) {
916
+ gitignoreContent = fs.readFileSync(gitignorePath, "utf-8");
917
+ }
918
+ const gitignoreEntries = [".env", ".env.local", ".env.*.local"];
919
+ const missingEntries = gitignoreEntries.filter(
920
+ (entry) => !gitignoreContent.includes(entry)
921
+ );
922
+ if (missingEntries.length > 0) {
923
+ const separator = gitignoreContent && !gitignoreContent.endsWith("\n") ? "\n" : "";
907
924
  fs.appendFileSync(
908
- envPath,
909
- separator + "# Diviswap SDK Configuration (Partner Authentication)\n" + newEnvVars.join("\n") + "\n"
925
+ gitignorePath,
926
+ separator + "# Environment variables (secrets)\n" + missingEntries.join("\n") + "\n"
910
927
  );
911
928
  console.log(
912
929
  kleur__default.default.green(
913
- `\u2705 Updated ${envFile} with partner authentication credentials`
930
+ `\u2705 Updated .gitignore to protect environment files`
914
931
  )
915
932
  );
916
933
  }
934
+ console.log(
935
+ kleur__default.default.yellow(
936
+ "\n\u26A0\uFE0F IMPORTANT SECURITY NOTICE:\n"
937
+ )
938
+ );
939
+ console.log(
940
+ " Your partner credentials were validated but NOT written to files."
941
+ );
942
+ console.log(
943
+ " For security, you must manually add them to your environment:\n"
944
+ );
945
+ console.log(
946
+ kleur__default.default.cyan(
947
+ ` 1. Create a ${framework.includes("nextjs") ? ".env.local" : ".env"} file (already in .gitignore)`
948
+ )
949
+ );
950
+ console.log(
951
+ kleur__default.default.cyan(
952
+ ` 2. Add your credentials (use .env.example as a template)`
953
+ )
954
+ );
955
+ console.log(
956
+ kleur__default.default.cyan(
957
+ " 3. NEVER commit this file to version control"
958
+ )
959
+ );
960
+ console.log(
961
+ kleur__default.default.cyan(
962
+ " 4. In production, use environment variables or a secrets manager\n"
963
+ )
964
+ );
917
965
  }
918
966
  if (framework.includes("nextjs")) {
919
967
  console.log("\nUpdating Next.js configuration...");
@@ -2185,7 +2233,7 @@ async function uninstall(options = {}) {
2185
2233
  }
2186
2234
 
2187
2235
  // package.json
2188
- var version = "1.9.1";
2236
+ var version = "2.0.0";
2189
2237
 
2190
2238
  // src/cli/index.ts
2191
2239
  var program = new commander.Command();
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { d as Address, x as ApiResponse, A as AuthCredentials, m as AuthMode, u as AuthResponse, h as CHAIN_IDS, g as ChainName, C as ComplianceStatus, e as CreateAddressRequest, v as CreatePayeeRequest, f as DeleteAddressRequest, D as Diviswap, a as DiviswapConfig, E as Environment, k as EthereumWallet, I as IndividualData, z as KybMetadata, b as KybStatus, F as KycDocumentRequest, y as KycMetadata, G as KycPersonalInfo, c as KycSessionResponse, K as KycStatus, r as LegacyDiviswapConfig, D as LiberEx, L as LiberExConfig, w as OfframpRequest, O as OnrampRequest, B as OrganizationInfo, o as PartnerDiviswapConfig, q as PartnerLiberExConfig, P as Payee, R as RegisterRequest, S as SetDefaultAddressRequest, T as Transaction, U as User, n as UserDiviswapConfig, p as UserLiberExConfig, W as WalletConnection, i as WalletTracker, l as WalletTrackingConfig, j as connectWallet, s as setupWalletTracking, t as trackCurrentWallet } from './wallet-yDJlJqCw.mjs';
1
+ export { d as Address, x as ApiResponse, A as AuthCredentials, m as AuthMode, u as AuthResponse, h as CHAIN_IDS, g as ChainName, C as ComplianceStatus, e as CreateAddressRequest, v as CreatePayeeRequest, f as DeleteAddressRequest, D as Diviswap, a as DiviswapConfig, E as Environment, k as EthereumWallet, I as IndividualData, z as KybMetadata, b as KybStatus, F as KycDocumentRequest, y as KycMetadata, G as KycPersonalInfo, c as KycSessionResponse, K as KycStatus, r as LegacyDiviswapConfig, D as LiberEx, L as LiberExConfig, w as OfframpRequest, O as OnrampRequest, B as OrganizationInfo, o as PartnerDiviswapConfig, q as PartnerLiberExConfig, P as Payee, R as RegisterRequest, S as SetDefaultAddressRequest, T as Transaction, U as User, n as UserDiviswapConfig, p as UserLiberExConfig, W as WalletConnection, i as WalletTracker, l as WalletTrackingConfig, j as connectWallet, s as setupWalletTracking, t as trackCurrentWallet } from './wallet-DO1Nbsfk.mjs';
2
2
 
3
3
  /**
4
4
  * Custom error classes for Diviswap SDK
@@ -25,36 +25,18 @@ declare class ConfigurationError extends DiviswapError {
25
25
  declare const LiberExError: typeof DiviswapError;
26
26
 
27
27
  /**
28
- * Web3 utilities for handling transaction results
28
+ * Wallet transaction result types (supports various wallet libraries)
29
29
  */
30
- /**
31
- * Type representing the various formats that sendTransaction can return
32
- * - Direct hash string: '0x...'
33
- * - Object with hash property: {hash: '0x...'}
34
- * - Template literal type from viem: `0x${string}`
35
- */
36
- type SendTransactionResult = string | {
30
+ type SendTransactionResult = {
37
31
  hash: string;
38
- } | `0x${string}`;
32
+ } | {
33
+ transactionHash: string;
34
+ } | string;
39
35
  /**
40
- * Safely extract transaction hash from various sendTransaction result formats
41
- *
42
- * Different Web3 libraries and wallet connectors return transaction hashes in different formats:
43
- * - wagmi's sendTransactionAsync: typically returns the hash directly as a string
44
- * - Some wallets: return an object with a hash property
45
- * - viem: uses template literal types `0x${string}`
46
- *
47
- * This utility handles all these cases and extracts the hash string reliably.
48
- *
49
- * @param result - The result from sendTransaction/sendTransactionAsync
50
- * @returns The transaction hash as a string
51
- *
52
- * @example
53
- * ```typescript
54
- * const result = await sendTransactionAsync({...});
55
- * const hash = extractTransactionHash(result);
56
- * // hash is now guaranteed to be a string like '0x...'
57
- * ```
36
+ * Extract transaction hash from various wallet return types
37
+ * Handles different wallet libraries (wagmi, ethers, web3.js, etc.)
38
+ * @param result Transaction result from wallet
39
+ * @returns Transaction hash
58
40
  */
59
41
  declare function extractTransactionHash(result: SendTransactionResult): string;
60
42
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { d as Address, x as ApiResponse, A as AuthCredentials, m as AuthMode, u as AuthResponse, h as CHAIN_IDS, g as ChainName, C as ComplianceStatus, e as CreateAddressRequest, v as CreatePayeeRequest, f as DeleteAddressRequest, D as Diviswap, a as DiviswapConfig, E as Environment, k as EthereumWallet, I as IndividualData, z as KybMetadata, b as KybStatus, F as KycDocumentRequest, y as KycMetadata, G as KycPersonalInfo, c as KycSessionResponse, K as KycStatus, r as LegacyDiviswapConfig, D as LiberEx, L as LiberExConfig, w as OfframpRequest, O as OnrampRequest, B as OrganizationInfo, o as PartnerDiviswapConfig, q as PartnerLiberExConfig, P as Payee, R as RegisterRequest, S as SetDefaultAddressRequest, T as Transaction, U as User, n as UserDiviswapConfig, p as UserLiberExConfig, W as WalletConnection, i as WalletTracker, l as WalletTrackingConfig, j as connectWallet, s as setupWalletTracking, t as trackCurrentWallet } from './wallet-yDJlJqCw.js';
1
+ export { d as Address, x as ApiResponse, A as AuthCredentials, m as AuthMode, u as AuthResponse, h as CHAIN_IDS, g as ChainName, C as ComplianceStatus, e as CreateAddressRequest, v as CreatePayeeRequest, f as DeleteAddressRequest, D as Diviswap, a as DiviswapConfig, E as Environment, k as EthereumWallet, I as IndividualData, z as KybMetadata, b as KybStatus, F as KycDocumentRequest, y as KycMetadata, G as KycPersonalInfo, c as KycSessionResponse, K as KycStatus, r as LegacyDiviswapConfig, D as LiberEx, L as LiberExConfig, w as OfframpRequest, O as OnrampRequest, B as OrganizationInfo, o as PartnerDiviswapConfig, q as PartnerLiberExConfig, P as Payee, R as RegisterRequest, S as SetDefaultAddressRequest, T as Transaction, U as User, n as UserDiviswapConfig, p as UserLiberExConfig, W as WalletConnection, i as WalletTracker, l as WalletTrackingConfig, j as connectWallet, s as setupWalletTracking, t as trackCurrentWallet } from './wallet-DO1Nbsfk.js';
2
2
 
3
3
  /**
4
4
  * Custom error classes for Diviswap SDK
@@ -25,36 +25,18 @@ declare class ConfigurationError extends DiviswapError {
25
25
  declare const LiberExError: typeof DiviswapError;
26
26
 
27
27
  /**
28
- * Web3 utilities for handling transaction results
28
+ * Wallet transaction result types (supports various wallet libraries)
29
29
  */
30
- /**
31
- * Type representing the various formats that sendTransaction can return
32
- * - Direct hash string: '0x...'
33
- * - Object with hash property: {hash: '0x...'}
34
- * - Template literal type from viem: `0x${string}`
35
- */
36
- type SendTransactionResult = string | {
30
+ type SendTransactionResult = {
37
31
  hash: string;
38
- } | `0x${string}`;
32
+ } | {
33
+ transactionHash: string;
34
+ } | string;
39
35
  /**
40
- * Safely extract transaction hash from various sendTransaction result formats
41
- *
42
- * Different Web3 libraries and wallet connectors return transaction hashes in different formats:
43
- * - wagmi's sendTransactionAsync: typically returns the hash directly as a string
44
- * - Some wallets: return an object with a hash property
45
- * - viem: uses template literal types `0x${string}`
46
- *
47
- * This utility handles all these cases and extracts the hash string reliably.
48
- *
49
- * @param result - The result from sendTransaction/sendTransactionAsync
50
- * @returns The transaction hash as a string
51
- *
52
- * @example
53
- * ```typescript
54
- * const result = await sendTransactionAsync({...});
55
- * const hash = extractTransactionHash(result);
56
- * // hash is now guaranteed to be a string like '0x...'
57
- * ```
36
+ * Extract transaction hash from various wallet return types
37
+ * Handles different wallet libraries (wagmi, ethers, web3.js, etc.)
38
+ * @param result Transaction result from wallet
39
+ * @returns Transaction hash
58
40
  */
59
41
  declare function extractTransactionHash(result: SendTransactionResult): string;
60
42
 
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var sha3 = require('@noble/hashes/sha3');
3
4
  var crypto = require('crypto');
4
5
 
5
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -70,31 +71,43 @@ var AuthModule = class {
70
71
  * ```
71
72
  */
72
73
  async register(data) {
74
+ if (!data.email || !data.password) {
75
+ throw new ValidationError("Email and password are required");
76
+ }
77
+ if (!data.firstName || !data.lastName) {
78
+ throw new ValidationError("First name and last name are required for KYC compliance");
79
+ }
80
+ if (!data.individual) {
81
+ throw new ValidationError(
82
+ "Complete individual KYC information is required for registration. Please provide residential address, date of birth, and government ID information."
83
+ );
84
+ }
85
+ const individual = data.individual;
86
+ const requiredIndividualFields = [
87
+ "residential_country_code",
88
+ "residential_address_line_one",
89
+ "residential_city",
90
+ "residential_state",
91
+ "residential_postal_code",
92
+ "id_country_code",
93
+ "dob",
94
+ "id_number"
95
+ ];
96
+ for (const field of requiredIndividualFields) {
97
+ const value = individual[field];
98
+ if (value === void 0 || value === null || value === "") {
99
+ throw new ValidationError(
100
+ `Missing required KYC field: ${field}. All identity information must be provided for compliance.`
101
+ );
102
+ }
103
+ }
73
104
  const requestData = {
74
105
  email: data.email,
75
106
  password: data.password,
76
- first_name: data.firstName || "Test",
77
- last_name: data.lastName || "User",
78
- // Individual object is REQUIRED by the backend
79
- individual: {
80
- // Use 'USA' (3-letter code) as seen in working lbx-landing implementation
81
- residential_country_code: "USA",
82
- residential_address_line_one: "123 Main Street",
83
- residential_address_line_two: "",
84
- residential_city: "Anytown",
85
- residential_state: "CA",
86
- residential_postal_code: "12345",
87
- id_type: "ssn",
88
- // Add id_type field as seen in lbx-landing
89
- id_country_code: "USA",
90
- dob: "1990-01-01",
91
- id_number: "123456789"
92
- // Remove dashes from SSN like lbx-landing does
93
- }
107
+ first_name: data.firstName,
108
+ last_name: data.lastName,
109
+ individual: data.individual
94
110
  };
95
- if (data.individual) {
96
- requestData.individual = data.individual;
97
- }
98
111
  if (data.phone) requestData.phone = data.phone;
99
112
  if (data.referralCode) requestData.referral_code = data.referralCode;
100
113
  const response = await this.client.post(
@@ -525,19 +538,116 @@ var STABLECOIN_ADDRESSES = {
525
538
  // Wrapped SOL
526
539
  }
527
540
  };
541
+ function isValidEthereumAddress(address) {
542
+ if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
543
+ return false;
544
+ }
545
+ if (address === address.toLowerCase() || address === address.toUpperCase()) {
546
+ return true;
547
+ }
548
+ return address === toChecksumAddress(address);
549
+ }
550
+ function toChecksumAddress(address) {
551
+ if (!address.startsWith("0x")) {
552
+ throw new Error("Invalid Ethereum address: must start with 0x");
553
+ }
554
+ const lowerAddress = address.toLowerCase().replace("0x", "");
555
+ const hash = keccak256(lowerAddress);
556
+ let checksumAddress = "0x";
557
+ for (let i = 0; i < lowerAddress.length; i++) {
558
+ const hashByte = parseInt(hash[i], 16);
559
+ checksumAddress += hashByte >= 8 ? lowerAddress[i].toUpperCase() : lowerAddress[i];
560
+ }
561
+ return checksumAddress;
562
+ }
563
+ function keccak256(input) {
564
+ const bytes = new TextEncoder().encode(input);
565
+ const hash = sha3.keccak_256(bytes);
566
+ return Array.from(hash).map((b) => b.toString(16).padStart(2, "0")).join("");
567
+ }
568
+ function isValidSolanaAddress(address) {
569
+ const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
570
+ if (!base58Regex.test(address)) {
571
+ return false;
572
+ }
573
+ if (/[0OIl]/.test(address)) {
574
+ return false;
575
+ }
576
+ return true;
577
+ }
578
+ function isValidBitcoinAddress(address) {
579
+ const legacyRegex = /^1[1-9A-HJ-NP-Za-km-z]{25,34}$/;
580
+ const segwitRegex = /^3[1-9A-HJ-NP-Za-km-z]{25,34}$/;
581
+ const bech32Regex = /^bc1[a-z0-9]{39,87}$/i;
582
+ return legacyRegex.test(address) || segwitRegex.test(address) || bech32Regex.test(address);
583
+ }
584
+ function isValidTronAddress(address) {
585
+ if (!address.startsWith("T") || address.length !== 34) {
586
+ return false;
587
+ }
588
+ const base58Regex = /^T[1-9A-HJ-NP-Za-km-z]{33}$/;
589
+ return base58Regex.test(address);
590
+ }
591
+ function isValidCryptoAddress(address, chain) {
592
+ const chainLower = chain.toLowerCase();
593
+ switch (chainLower) {
594
+ case "ethereum":
595
+ case "eth":
596
+ case "polygon":
597
+ case "matic":
598
+ case "arbitrum":
599
+ case "optimism":
600
+ case "base":
601
+ case "avalanche":
602
+ case "bsc":
603
+ case "binance":
604
+ return isValidEthereumAddress(address);
605
+ case "solana":
606
+ case "sol":
607
+ return isValidSolanaAddress(address);
608
+ case "bitcoin":
609
+ case "btc":
610
+ return isValidBitcoinAddress(address);
611
+ case "tron":
612
+ case "trx":
613
+ return isValidTronAddress(address);
614
+ default:
615
+ throw new Error(`Unsupported chain: ${chain}`);
616
+ }
617
+ }
618
+ function extractTransactionHash(result) {
619
+ if (typeof result === "string") {
620
+ return result;
621
+ }
622
+ if ("hash" in result && result.hash) {
623
+ return result.hash;
624
+ }
625
+ if ("transactionHash" in result && result.transactionHash) {
626
+ return result.transactionHash;
627
+ }
628
+ throw new Error(
629
+ 'Unable to extract transaction hash from result. Expected string or object with "hash" or "transactionHash" property.'
630
+ );
631
+ }
528
632
 
529
633
  // src/modules/transactions.ts
530
- var TransactionsModule = class {
634
+ var _TransactionsModule = class _TransactionsModule {
531
635
  constructor(client, environment = "sandbox") {
532
636
  this.client = client;
533
637
  this.depositAddresses = getDepositAddresses(environment);
534
638
  }
535
639
  /**
536
- * Map chain name to chain ID
640
+ * Map chain name to chain ID with validation
537
641
  * @private
538
642
  */
539
643
  getChainId(chain) {
540
- const chainId = CHAIN_NAME_TO_ID[chain.toLowerCase()];
644
+ const chainLower = chain.toLowerCase();
645
+ if (!_TransactionsModule.SUPPORTED_CHAINS.includes(chainLower)) {
646
+ throw new ValidationError(
647
+ `Unsupported chain: ${chain}. Supported chains: ${_TransactionsModule.SUPPORTED_CHAINS.filter((c, i, arr) => arr.indexOf(c) === i).join(", ")}`
648
+ );
649
+ }
650
+ const chainId = CHAIN_NAME_TO_ID[chainLower];
541
651
  return chainId ? chainId.toString() : chain;
542
652
  }
543
653
  /**
@@ -626,17 +736,30 @@ var TransactionsModule = class {
626
736
  */
627
737
  async offramp(data) {
628
738
  if (!data.txHash || data.txHash.trim() === "") {
629
- throw new Error("txHash is required for offramp transactions.");
739
+ throw new ValidationError("txHash is required for offramp transactions.");
740
+ }
741
+ const chain = data.chain || "ethereum";
742
+ const chainId = this.getChainId(chain);
743
+ if (!isValidCryptoAddress(data.fromAddress, chain)) {
744
+ throw new ValidationError(
745
+ `Invalid ${chain} address: ${data.fromAddress}. Please check the address format.`
746
+ );
747
+ }
748
+ const toAddress = data.toAddress || this.getDepositAddress(chain);
749
+ if (!isValidCryptoAddress(toAddress, chain)) {
750
+ throw new ValidationError(
751
+ `Invalid ${chain} deposit address: ${toAddress}. Please contact support.`
752
+ );
630
753
  }
631
754
  const payload = {
632
755
  payee_id: data.payeeId,
633
756
  tx_hash: data.txHash,
634
757
  // Required: must send crypto first
635
758
  from_address: data.fromAddress,
636
- to_address: data.toAddress || this.getDepositAddress(data.chain || "ethereum"),
759
+ to_address: toAddress,
637
760
  amount: data.amount,
638
761
  currency: data.currency,
639
- chain_id: this.getChainId(data.chain || "ethereum")
762
+ chain_id: chainId
640
763
  };
641
764
  if (data.memo) {
642
765
  payload.memo = data.memo;
@@ -824,6 +947,26 @@ var TransactionsModule = class {
824
947
  return STABLECOIN_ADDRESSES[chainName] || {};
825
948
  }
826
949
  };
950
+ // Supported chains for validation
951
+ _TransactionsModule.SUPPORTED_CHAINS = [
952
+ "ethereum",
953
+ "eth",
954
+ "polygon",
955
+ "matic",
956
+ "arbitrum",
957
+ "optimism",
958
+ "base",
959
+ "avalanche",
960
+ "bsc",
961
+ "binance",
962
+ "solana",
963
+ "sol",
964
+ "bitcoin",
965
+ "btc",
966
+ "tron",
967
+ "trx"
968
+ ];
969
+ var TransactionsModule = _TransactionsModule;
827
970
 
828
971
  // src/modules/kyc.ts
829
972
  var KycModule = class {
@@ -1539,8 +1682,8 @@ var MemoryTokenStorage = class {
1539
1682
  }
1540
1683
  };
1541
1684
  var LocalStorageTokenStorage = class {
1542
- constructor() {
1543
- this.key = "liberex_tokens";
1685
+ constructor(userId) {
1686
+ this.key = userId ? `liberex_tokens_${userId}` : "liberex_tokens";
1544
1687
  }
1545
1688
  get() {
1546
1689
  if (typeof globalThis.window === "undefined") return null;
@@ -1562,9 +1705,14 @@ var LocalStorageTokenStorage = class {
1562
1705
  }
1563
1706
  };
1564
1707
  var TokenManager = class {
1565
- constructor(useLocalStorage = false) {
1708
+ /**
1709
+ * Create a new TokenManager
1710
+ * @param useLocalStorage Whether to use localStorage (default: memory storage for security)
1711
+ * @param userId Optional user ID for multi-user session isolation
1712
+ */
1713
+ constructor(useLocalStorage = false, userId) {
1566
1714
  this.refreshPromise = null;
1567
- this.storage = useLocalStorage && typeof globalThis.window !== "undefined" ? new LocalStorageTokenStorage() : new MemoryTokenStorage();
1715
+ this.storage = useLocalStorage && typeof globalThis.window !== "undefined" ? new LocalStorageTokenStorage(userId) : new MemoryTokenStorage();
1568
1716
  }
1569
1717
  /**
1570
1718
  * Parse JWT token to extract expiration
@@ -1665,6 +1813,18 @@ var PartnerAuth = class {
1665
1813
  constructor(credentials) {
1666
1814
  this.credentials = credentials;
1667
1815
  }
1816
+ /**
1817
+ * Override toJSON to prevent accidental serialization of secret key
1818
+ */
1819
+ toJSON() {
1820
+ return {
1821
+ keyId: this.credentials.keyId,
1822
+ customerId: this.credentials.customerId,
1823
+ customerEmail: this.credentials.customerEmail,
1824
+ secretKey: "***REDACTED***"
1825
+ // Never expose secret key
1826
+ };
1827
+ }
1668
1828
  /**
1669
1829
  * Generate HMAC authentication headers for a request
1670
1830
  */
@@ -1756,17 +1916,54 @@ var PartnerAuth = class {
1756
1916
  // src/api/unified-client.ts
1757
1917
  var UnifiedApiClient = class _UnifiedApiClient {
1758
1918
  constructor(config, useLocalStorage = true) {
1759
- this.config = config;
1919
+ Object.defineProperty(this, "_secureApiKey", {
1920
+ value: config.apiKey,
1921
+ writable: false,
1922
+ enumerable: false,
1923
+ configurable: false
1924
+ });
1925
+ Object.defineProperty(this, "_secureSecretKey", {
1926
+ value: config.secretKey,
1927
+ writable: false,
1928
+ enumerable: false,
1929
+ configurable: false
1930
+ });
1931
+ const { apiKey, secretKey, ...safeConfig } = config;
1932
+ this.config = safeConfig;
1760
1933
  this.tokenManager = new TokenManager(useLocalStorage);
1761
- if (config.mode === "partner" && config.keyId && config.secretKey) {
1934
+ const secureSecretKey = this._secureSecretKey;
1935
+ if (config.mode === "partner" && config.keyId && secureSecretKey) {
1762
1936
  this.partnerAuth = new PartnerAuth({
1763
1937
  keyId: config.keyId,
1764
- secretKey: config.secretKey,
1938
+ secretKey: secureSecretKey,
1765
1939
  customerId: config.customerId,
1766
1940
  customerEmail: config.customerEmail
1767
1941
  });
1768
1942
  }
1769
1943
  }
1944
+ /**
1945
+ * Override toJSON to prevent accidental serialization of sensitive data
1946
+ */
1947
+ toJSON() {
1948
+ return {
1949
+ mode: this.config.mode,
1950
+ baseUrl: this.config.baseUrl,
1951
+ timeout: this.config.timeout,
1952
+ debug: this.config.debug,
1953
+ // Never expose credentials
1954
+ apiKey: this.config.apiKey ? "***REDACTED***" : void 0,
1955
+ secretKey: this.config.secretKey ? "***REDACTED***" : void 0,
1956
+ keyId: this.config.keyId,
1957
+ clientId: this.config.clientId
1958
+ };
1959
+ }
1960
+ /**
1961
+ * Get the actual API key (for internal use only)
1962
+ * @internal
1963
+ */
1964
+ getApiKey() {
1965
+ return this._secureApiKey;
1966
+ }
1770
1967
  /**
1771
1968
  * Create client from legacy user config (backward compatibility)
1772
1969
  */
@@ -1914,7 +2111,15 @@ var UnifiedApiClient = class _UnifiedApiClient {
1914
2111
  this.config.timeout
1915
2112
  );
1916
2113
  if (this.config.debug) {
1917
- console.log(`[Diviswap SDK] ${method} ${url}`);
2114
+ const safeHeaders = { ...requestHeaders };
2115
+ if (safeHeaders["X-API-Key"]) safeHeaders["X-API-Key"] = "***REDACTED***";
2116
+ if (safeHeaders["Authorization"]?.startsWith("Bearer ")) {
2117
+ safeHeaders["Authorization"] = "Bearer ***REDACTED***";
2118
+ }
2119
+ if (safeHeaders["Authorization"]?.startsWith("HMAC ")) {
2120
+ safeHeaders["Authorization"] = "HMAC ***REDACTED***";
2121
+ }
2122
+ console.log(`[Diviswap SDK] ${method} ${url}`, { headers: safeHeaders });
1918
2123
  }
1919
2124
  const response = await fetch(url, {
1920
2125
  method,
@@ -1982,12 +2187,13 @@ var UnifiedApiClient = class _UnifiedApiClient {
1982
2187
  * Add user authentication headers (legacy)
1983
2188
  */
1984
2189
  async addUserAuth(useApiKey, headers) {
1985
- if (!this.config.apiKey || !this.config.clientId) {
2190
+ const apiKey = this.getApiKey();
2191
+ if (!apiKey || !this.config.clientId) {
1986
2192
  throw new AuthenticationError("User authentication not configured");
1987
2193
  }
1988
2194
  headers["X-CLIENT-ID"] = this.config.clientId;
1989
2195
  headers["X-TIMESTAMP"] = Math.floor(Date.now() / 1e3).toString();
1990
- headers["X-API-Key"] = this.config.apiKey;
2196
+ headers["X-API-Key"] = apiKey;
1991
2197
  if (!useApiKey) {
1992
2198
  const accessToken = await this.tokenManager.getValidAccessToken(
1993
2199
  this.refreshCallback
@@ -2423,17 +2629,6 @@ function setupWalletTracking(diviswap, wallet, config) {
2423
2629
  return tracker;
2424
2630
  }
2425
2631
 
2426
- // src/utils/web3.ts
2427
- function extractTransactionHash(result) {
2428
- if (typeof result === "string") {
2429
- return result;
2430
- }
2431
- if (typeof result === "object" && result !== null && "hash" in result) {
2432
- return result.hash;
2433
- }
2434
- return result;
2435
- }
2436
-
2437
2632
  exports.AuthenticationError = AuthenticationError;
2438
2633
  exports.CHAIN_IDS = CHAIN_IDS;
2439
2634
  exports.CHAIN_ID_TO_NAME = CHAIN_ID_TO_NAME;