@sip-protocol/sdk 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{TransportWebUSB-YQMAGJAJ.mjs → TransportWebUSB-2KITI5HD.mjs} +24 -12
  3. package/dist/browser.d.mts +4 -4
  4. package/dist/browser.d.ts +4 -4
  5. package/dist/browser.js +1363 -844
  6. package/dist/browser.mjs +13 -3
  7. package/dist/{chunk-64AYA5F5.mjs → chunk-7IUKXWDN.mjs} +229 -148
  8. package/dist/{chunk-4GRJ5MAW.mjs → chunk-KXETSSKP.mjs} +4 -0
  9. package/dist/{chunk-6EU6WQFK.mjs → chunk-L4RKPNIJ.mjs} +266 -239
  10. package/dist/{constants-LHAAUC2T.mjs → constants-DCJYTIU3.mjs} +5 -1
  11. package/dist/{dist-2OGQ7FED.mjs → dist-PYEXZNFD.mjs} +609 -221
  12. package/dist/{index-DeE1ZzA4.d.mts → index-Cwo3WhxX.d.mts} +128 -37
  13. package/dist/{index-DXh2IGkz.d.ts → index-X8qPQdp6.d.ts} +128 -37
  14. package/dist/index.d.mts +3 -3
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +1356 -837
  17. package/dist/index.mjs +13 -3
  18. package/dist/{interface-Bf7w1PLW.d.mts → interface-CQi0-WfS.d.mts} +2 -2
  19. package/dist/{interface-Bf7w1PLW.d.ts → interface-CQi0-WfS.d.ts} +2 -2
  20. package/dist/{noir-kzbLVTei.d.mts → noir-CwPIyBLj.d.mts} +1 -1
  21. package/dist/{noir-kzbLVTei.d.ts → noir-CwPIyBLj.d.ts} +1 -1
  22. package/dist/proofs/halo2.d.mts +1 -1
  23. package/dist/proofs/halo2.d.ts +1 -1
  24. package/dist/proofs/kimchi.d.mts +1 -1
  25. package/dist/proofs/kimchi.d.ts +1 -1
  26. package/dist/proofs/noir.d.mts +1 -1
  27. package/dist/proofs/noir.d.ts +1 -1
  28. package/dist/{solana-U3MEGU7W.mjs → solana-7QOA3HBZ.mjs} +6 -6
  29. package/package.json +32 -32
  30. package/src/adapters/gelato-relay.ts +386 -0
  31. package/src/adapters/index.ts +28 -0
  32. package/src/adapters/oneinch.ts +126 -0
  33. package/src/chains/ethereum/index.ts +2 -0
  34. package/src/chains/ethereum/privacy-adapter.ts +64 -5
  35. package/src/chains/ethereum/stealth.ts +89 -14
  36. package/src/chains/ethereum/types.ts +18 -2
  37. package/src/chains/near/constants.ts +13 -1
  38. package/src/chains/near/index.ts +2 -0
  39. package/src/chains/near/privacy-adapter.ts +8 -5
  40. package/src/chains/near/resolver.ts +24 -10
  41. package/src/chains/near/stealth.ts +9 -9
  42. package/src/chains/near/types.ts +20 -9
  43. package/src/chains/solana/constants.ts +13 -1
  44. package/src/chains/solana/ephemeral-keys.ts +3 -257
  45. package/src/chains/solana/index.ts +2 -3
  46. package/src/chains/solana/providers/helius-enhanced.ts +6 -6
  47. package/src/chains/solana/providers/webhook.ts +2 -2
  48. package/src/chains/solana/scan.ts +9 -8
  49. package/src/chains/solana/stealth-scanner.ts +3 -3
  50. package/src/chains/solana/transfer.ts +1 -1
  51. package/src/chains/solana/types.ts +18 -4
  52. package/src/cosmos/ibc-stealth.ts +6 -6
  53. package/src/index.ts +6 -0
  54. package/src/move/aptos.ts +15 -9
  55. package/src/move/sui.ts +15 -9
  56. package/src/nft/private-nft.ts +10 -6
  57. package/src/privacy-backends/shadowwire.ts +13 -0
  58. package/src/stealth/ed25519.ts +173 -12
  59. package/src/stealth/index.ts +47 -4
  60. package/src/stealth/secp256k1.ts +157 -9
  61. package/src/stealth.ts +7 -0
  62. package/src/wallet/ethereum/privacy-adapter.ts +1 -1
  63. package/src/wallet/hardware/ledger-privacy.ts +2 -2
  64. package/src/wallet/near/adapter.ts +2 -2
  65. package/src/wallet/near/meteor-wallet.ts +2 -2
  66. package/src/wallet/near/my-near-wallet.ts +2 -2
  67. package/src/wallet/near/wallet-selector.ts +2 -2
  68. package/src/wallet/solana/privacy-adapter.ts +9 -9
  69. package/dist/chunk-5EKF243P.mjs +0 -33809
  70. package/dist/chunk-YWGJ77A2.mjs +0 -33806
package/dist/browser.mjs CHANGED
@@ -458,7 +458,7 @@ import {
458
458
  verifyOracleSignature,
459
459
  verifyOwnership,
460
460
  walletRegistry
461
- } from "./chunk-5EKF243P.mjs";
461
+ } from "./chunk-L4RKPNIJ.mjs";
462
462
  import {
463
463
  DEFAULT_NETWORK_CONFIG,
464
464
  DEFAULT_PROXY_TIMEOUT,
@@ -473,7 +473,9 @@ import {
473
473
  addBlindings,
474
474
  addCommitments,
475
475
  checkEd25519StealthAddress,
476
+ checkEd25519StealthAddressV1,
476
477
  checkProxyAvailability,
478
+ checkSecp256k1StealthAddressV1,
477
479
  checkStealthAddress,
478
480
  claimStealthPayment,
479
481
  commit,
@@ -487,7 +489,10 @@ import {
487
489
  createWebhookHandler,
488
490
  decodeStealthMetaAddress,
489
491
  deriveEd25519StealthPrivateKey,
492
+ deriveEd25519StealthPrivateKeyV1,
493
+ deriveSecp256k1StealthPrivateKeyV1,
490
494
  deriveStealthPrivateKey,
495
+ deriveStealthPrivateKeyV1,
491
496
  detectTorPort,
492
497
  ed25519PublicKeyToNearAddress,
493
498
  ed25519PublicKeyToSolanaAddress,
@@ -545,7 +550,7 @@ import {
545
550
  verifyWebhookSignature,
546
551
  withSecureBuffer,
547
552
  withSecureBufferSync
548
- } from "./chunk-64AYA5F5.mjs";
553
+ } from "./chunk-7IUKXWDN.mjs";
549
554
  import {
550
555
  Halo2Provider,
551
556
  KimchiProvider,
@@ -598,7 +603,7 @@ import {
598
603
  getExplorerUrl,
599
604
  getSolanaTokenDecimals,
600
605
  getTokenMint
601
- } from "./chunk-4GRJ5MAW.mjs";
606
+ } from "./chunk-KXETSSKP.mjs";
602
607
  import "./chunk-XGB3TDIC.mjs";
603
608
 
604
609
  // src/proofs/browser.ts
@@ -2348,9 +2353,11 @@ export {
2348
2353
  calculateSIPComparison,
2349
2354
  checkAptosStealthAddress,
2350
2355
  checkEd25519StealthAddress,
2356
+ checkEd25519StealthAddressV1,
2351
2357
  checkMobileWASMCompatibility,
2352
2358
  checkNEARStealthAddress,
2353
2359
  checkProxyAvailability,
2360
+ checkSecp256k1StealthAddressV1,
2354
2361
  checkStealthAddress,
2355
2362
  checkSuiStealthAddress,
2356
2363
  claimStealthPayment,
@@ -2458,11 +2465,14 @@ export {
2458
2465
  defaultRegistry,
2459
2466
  deriveAptosStealthPrivateKey,
2460
2467
  deriveEd25519StealthPrivateKey,
2468
+ deriveEd25519StealthPrivateKeyV1,
2461
2469
  deriveNEARChildViewingKey,
2462
2470
  deriveNEARStealthPrivateKey,
2463
2471
  deriveObliviousNullifier,
2464
2472
  deriveOracleId,
2473
+ deriveSecp256k1StealthPrivateKeyV1,
2465
2474
  deriveStealthPrivateKey,
2475
+ deriveStealthPrivateKeyV1,
2466
2476
  deriveSuiStealthPrivateKey,
2467
2477
  deriveTraditionalNullifier,
2468
2478
  deriveViewingKey,
@@ -11,21 +11,23 @@ import {
11
11
  HELIUS_DAS_PAGE_LIMIT,
12
12
  HELIUS_MAX_PAGES,
13
13
  MEMO_PROGRAM_ID,
14
- SIP_MEMO_PREFIX,
14
+ SIP_MEMO_PREFIX_ANY,
15
15
  SOLANA_ADDRESS_MAX_LENGTH,
16
16
  SOLANA_ADDRESS_MIN_LENGTH,
17
17
  SOLANA_TOKEN_MINTS,
18
18
  VIEW_TAG_MAX,
19
19
  getExplorerUrl,
20
20
  sanitizeUrl
21
- } from "./chunk-4GRJ5MAW.mjs";
21
+ } from "./chunk-KXETSSKP.mjs";
22
22
 
23
23
  // src/chains/solana/types.ts
24
24
  function parseAnnouncement(memo) {
25
- if (!memo.startsWith("SIP:1:")) {
25
+ const versionMatch = /^SIP:([12]):/.exec(memo);
26
+ if (!versionMatch) {
26
27
  return null;
27
28
  }
28
- const parts = memo.slice(6).split(":");
29
+ const version = versionMatch[1];
30
+ const parts = memo.slice(versionMatch[0].length).split(":");
29
31
  if (parts.length < 2) {
30
32
  return null;
31
33
  }
@@ -46,13 +48,14 @@ function parseAnnouncement(memo) {
46
48
  return null;
47
49
  }
48
50
  return {
51
+ version,
49
52
  ephemeralPublicKey,
50
53
  viewTag,
51
54
  stealthAddress
52
55
  };
53
56
  }
54
57
  function createAnnouncementMemo(ephemeralPublicKey, viewTag, stealthAddress) {
55
- const parts = ["SIP:1", ephemeralPublicKey, viewTag];
58
+ const parts = ["SIP:2", ephemeralPublicKey, viewTag];
56
59
  if (stealthAddress) {
57
60
  parts.push(stealthAddress);
58
61
  }
@@ -626,16 +629,16 @@ function generateEd25519StealthAddress(recipientMetaAddress) {
626
629
  if (ephemeralScalar === 0n) {
627
630
  throw new Error("CRITICAL: Zero ephemeral scalar after reduction - investigate RNG");
628
631
  }
629
- const spendingPoint = ed25519.ExtendedPoint.fromHex(spendingKeyBytes);
630
- const sharedSecretPoint = spendingPoint.multiply(ephemeralScalar);
632
+ const viewingPoint = ed25519.ExtendedPoint.fromHex(viewingKeyBytes);
633
+ const sharedSecretPoint = viewingPoint.multiply(ephemeralScalar);
631
634
  const sharedSecretHash = sha256(sharedSecretPoint.toRawBytes());
632
635
  const hashScalar = bytesToBigInt(sharedSecretHash) % ED25519_ORDER;
633
636
  if (hashScalar === 0n) {
634
637
  throw new Error("CRITICAL: Zero hash scalar after reduction - investigate hash computation");
635
638
  }
636
639
  const hashTimesG = ed25519.ExtendedPoint.BASE.multiply(hashScalar);
637
- const viewingPoint = ed25519.ExtendedPoint.fromHex(viewingKeyBytes);
638
- const stealthPoint = viewingPoint.add(hashTimesG);
640
+ const spendingPoint = ed25519.ExtendedPoint.fromHex(spendingKeyBytes);
641
+ const stealthPoint = spendingPoint.add(hashTimesG);
639
642
  const stealthAddressBytes = stealthPoint.toRawBytes();
640
643
  const viewTag = sharedSecretHash[0];
641
644
  return {
@@ -651,6 +654,57 @@ function generateEd25519StealthAddress(recipientMetaAddress) {
651
654
  }
652
655
  }
653
656
  function deriveEd25519StealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
657
+ validateEd25519StealthAddress(stealthAddress);
658
+ if (!isValidPrivateKey(spendingPrivateKey)) {
659
+ throw new ValidationError(
660
+ "must be a valid 32-byte hex string",
661
+ "spendingPrivateKey"
662
+ );
663
+ }
664
+ if (!isValidPrivateKey(viewingPrivateKey)) {
665
+ throw new ValidationError(
666
+ "must be a valid 32-byte hex string",
667
+ "viewingPrivateKey"
668
+ );
669
+ }
670
+ const spendingPrivBytes = hexToBytes(spendingPrivateKey.slice(2));
671
+ const viewingPrivBytes = hexToBytes(viewingPrivateKey.slice(2));
672
+ const ephemeralPubBytes = hexToBytes(stealthAddress.ephemeralPublicKey.slice(2));
673
+ try {
674
+ const rawViewingScalar = getEd25519Scalar(viewingPrivBytes);
675
+ const viewingScalar = rawViewingScalar % ED25519_ORDER;
676
+ if (viewingScalar === 0n) {
677
+ throw new Error("CRITICAL: Zero viewing scalar after reduction - investigate key derivation");
678
+ }
679
+ const ephemeralPoint = ed25519.ExtendedPoint.fromHex(ephemeralPubBytes);
680
+ const sharedSecretPoint = ephemeralPoint.multiply(viewingScalar);
681
+ const sharedSecretHash = sha256(sharedSecretPoint.toRawBytes());
682
+ const rawSpendingScalar = getEd25519Scalar(spendingPrivBytes);
683
+ const spendingScalar = rawSpendingScalar % ED25519_ORDER;
684
+ if (spendingScalar === 0n) {
685
+ throw new Error("CRITICAL: Zero spending scalar after reduction - investigate key derivation");
686
+ }
687
+ const hashScalar = bytesToBigInt(sharedSecretHash) % ED25519_ORDER;
688
+ if (hashScalar === 0n) {
689
+ throw new Error("CRITICAL: Zero hash scalar after reduction - investigate hash computation");
690
+ }
691
+ const stealthPrivateScalar = (spendingScalar + hashScalar) % ED25519_ORDER;
692
+ if (stealthPrivateScalar === 0n) {
693
+ throw new Error("CRITICAL: Zero stealth scalar after reduction - investigate key derivation");
694
+ }
695
+ const stealthPrivateKey = bigIntToBytesLE(stealthPrivateScalar, 32);
696
+ const result = {
697
+ stealthAddress: stealthAddress.address,
698
+ ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
699
+ privateKey: `0x${bytesToHex(stealthPrivateKey)}`
700
+ };
701
+ secureWipe(stealthPrivateKey);
702
+ return result;
703
+ } finally {
704
+ secureWipeAll(spendingPrivBytes, viewingPrivBytes);
705
+ }
706
+ }
707
+ function deriveEd25519StealthPrivateKeyV1(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
654
708
  validateEd25519StealthAddress(stealthAddress);
655
709
  if (!isValidPrivateKey(spendingPrivateKey)) {
656
710
  throw new ValidationError(
@@ -701,7 +755,50 @@ function deriveEd25519StealthPrivateKey(stealthAddress, spendingPrivateKey, view
701
755
  secureWipeAll(spendingPrivBytes, viewingPrivBytes);
702
756
  }
703
757
  }
704
- function checkEd25519StealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
758
+ function checkEd25519StealthAddress(stealthAddress, viewingPrivateKey, spendingPublicKey) {
759
+ validateEd25519StealthAddress(stealthAddress);
760
+ if (!isValidPrivateKey(viewingPrivateKey)) {
761
+ throw new ValidationError(
762
+ "must be a valid 32-byte hex string",
763
+ "viewingPrivateKey"
764
+ );
765
+ }
766
+ if (!isValidEd25519PublicKey(spendingPublicKey)) {
767
+ throw new ValidationError(
768
+ "must be a valid ed25519 public key (32 bytes)",
769
+ "spendingPublicKey"
770
+ );
771
+ }
772
+ const viewingPrivBytes = hexToBytes(viewingPrivateKey.slice(2));
773
+ const spendingPubBytes = hexToBytes(spendingPublicKey.slice(2));
774
+ const ephemeralPubBytes = hexToBytes(stealthAddress.ephemeralPublicKey.slice(2));
775
+ try {
776
+ const rawViewingScalar = getEd25519Scalar(viewingPrivBytes);
777
+ const viewingScalar = rawViewingScalar % ED25519_ORDER;
778
+ if (viewingScalar === 0n) {
779
+ throw new Error("CRITICAL: Zero viewing scalar after reduction - investigate key derivation");
780
+ }
781
+ const ephemeralPoint = ed25519.ExtendedPoint.fromHex(ephemeralPubBytes);
782
+ const sharedSecretPoint = ephemeralPoint.multiply(viewingScalar);
783
+ const sharedSecretHash = sha256(sharedSecretPoint.toRawBytes());
784
+ if (sharedSecretHash[0] !== stealthAddress.viewTag) {
785
+ return false;
786
+ }
787
+ const hashScalar = bytesToBigInt(sharedSecretHash) % ED25519_ORDER;
788
+ if (hashScalar === 0n) {
789
+ throw new Error("CRITICAL: Zero hash scalar after reduction - investigate hash computation");
790
+ }
791
+ const hashTimesG = ed25519.ExtendedPoint.BASE.multiply(hashScalar);
792
+ const spendingPoint = ed25519.ExtendedPoint.fromHex(spendingPubBytes);
793
+ const expectedPoint = spendingPoint.add(hashTimesG);
794
+ const expectedPubKeyBytes = expectedPoint.toRawBytes();
795
+ const providedAddress = hexToBytes(stealthAddress.address.slice(2));
796
+ return bytesToHex(expectedPubKeyBytes) === bytesToHex(providedAddress);
797
+ } finally {
798
+ secureWipe(viewingPrivBytes);
799
+ }
800
+ }
801
+ function checkEd25519StealthAddressV1(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
705
802
  validateEd25519StealthAddress(stealthAddress);
706
803
  if (!isValidPrivateKey(spendingPrivateKey)) {
707
804
  throw new ValidationError(
@@ -830,13 +927,16 @@ function generateSecp256k1StealthAddress(recipientMetaAddress) {
830
927
  const viewingKeyBytes = hexToBytes(recipientMetaAddress.viewingKey.slice(2));
831
928
  const sharedSecretPoint = secp256k1.getSharedSecret(
832
929
  ephemeralPrivateKey,
833
- spendingKeyBytes
930
+ viewingKeyBytes
834
931
  );
835
932
  const sharedSecretHash = sha256(sharedSecretPoint);
836
- const hashTimesG = secp256k1.getPublicKey(sharedSecretHash, true);
837
- const viewingKeyPoint = secp256k1.ProjectivePoint.fromHex(viewingKeyBytes);
838
- const hashTimesGPoint = secp256k1.ProjectivePoint.fromHex(hashTimesG);
839
- const stealthPoint = viewingKeyPoint.add(hashTimesGPoint);
933
+ const hashScalar = bytesToBigInt(sharedSecretHash) % secp256k1.CURVE.n;
934
+ if (hashScalar === 0n) {
935
+ throw new Error("CRITICAL: zero hash scalar after reduction - investigate hash computation");
936
+ }
937
+ const spendingKeyPoint = secp256k1.ProjectivePoint.fromHex(spendingKeyBytes);
938
+ const hashTimesGPoint = secp256k1.ProjectivePoint.BASE.multiply(hashScalar);
939
+ const stealthPoint = spendingKeyPoint.add(hashTimesGPoint);
840
940
  const stealthAddressBytes = stealthPoint.toRawBytes(true);
841
941
  const viewTag = sharedSecretHash[0];
842
942
  return {
@@ -852,6 +952,44 @@ function generateSecp256k1StealthAddress(recipientMetaAddress) {
852
952
  }
853
953
  }
854
954
  function deriveSecp256k1StealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
955
+ validateSecp256k1StealthAddress(stealthAddress);
956
+ if (!isValidPrivateKey(spendingPrivateKey)) {
957
+ throw new ValidationError(
958
+ "must be a valid 32-byte hex string",
959
+ "spendingPrivateKey"
960
+ );
961
+ }
962
+ if (!isValidPrivateKey(viewingPrivateKey)) {
963
+ throw new ValidationError(
964
+ "must be a valid 32-byte hex string",
965
+ "viewingPrivateKey"
966
+ );
967
+ }
968
+ const spendingPrivBytes = hexToBytes(spendingPrivateKey.slice(2));
969
+ const viewingPrivBytes = hexToBytes(viewingPrivateKey.slice(2));
970
+ const ephemeralPubBytes = hexToBytes(stealthAddress.ephemeralPublicKey.slice(2));
971
+ try {
972
+ const sharedSecretPoint = secp256k1.getSharedSecret(
973
+ viewingPrivBytes,
974
+ ephemeralPubBytes
975
+ );
976
+ const sharedSecretHash = sha256(sharedSecretPoint);
977
+ const spendingScalar = bytesToBigInt(spendingPrivBytes);
978
+ const hashScalar = bytesToBigInt(sharedSecretHash);
979
+ const stealthPrivateScalar = (spendingScalar + hashScalar) % secp256k1.CURVE.n;
980
+ const stealthPrivateKey = bigIntToBytes(stealthPrivateScalar, 32);
981
+ const result = {
982
+ stealthAddress: stealthAddress.address,
983
+ ephemeralPublicKey: stealthAddress.ephemeralPublicKey,
984
+ privateKey: `0x${bytesToHex(stealthPrivateKey)}`
985
+ };
986
+ secureWipe(stealthPrivateKey);
987
+ return result;
988
+ } finally {
989
+ secureWipeAll(spendingPrivBytes, viewingPrivBytes);
990
+ }
991
+ }
992
+ function deriveSecp256k1StealthPrivateKeyV1(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
855
993
  validateSecp256k1StealthAddress(stealthAddress);
856
994
  if (!isValidPrivateKey(spendingPrivateKey)) {
857
995
  throw new ValidationError(
@@ -889,7 +1027,46 @@ function deriveSecp256k1StealthPrivateKey(stealthAddress, spendingPrivateKey, vi
889
1027
  secureWipeAll(spendingPrivBytes, viewingPrivBytes);
890
1028
  }
891
1029
  }
892
- function checkSecp256k1StealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
1030
+ function checkSecp256k1StealthAddress(stealthAddress, viewingPrivateKey, spendingPublicKey) {
1031
+ validateSecp256k1StealthAddress(stealthAddress);
1032
+ if (!isValidPrivateKey(viewingPrivateKey)) {
1033
+ throw new ValidationError(
1034
+ "must be a valid 32-byte hex string",
1035
+ "viewingPrivateKey"
1036
+ );
1037
+ }
1038
+ if (!isValidCompressedPublicKey(spendingPublicKey)) {
1039
+ throw new ValidationError(
1040
+ "must be a valid compressed secp256k1 public key (33 bytes, starting with 02 or 03)",
1041
+ "spendingPublicKey"
1042
+ );
1043
+ }
1044
+ const viewingPrivBytes = hexToBytes(viewingPrivateKey.slice(2));
1045
+ const spendingPubBytes = hexToBytes(spendingPublicKey.slice(2));
1046
+ const ephemeralPubBytes = hexToBytes(stealthAddress.ephemeralPublicKey.slice(2));
1047
+ try {
1048
+ const sharedSecretPoint = secp256k1.getSharedSecret(
1049
+ viewingPrivBytes,
1050
+ ephemeralPubBytes
1051
+ );
1052
+ const sharedSecretHash = sha256(sharedSecretPoint);
1053
+ if (sharedSecretHash[0] !== stealthAddress.viewTag) {
1054
+ return false;
1055
+ }
1056
+ const hashScalar = bytesToBigInt(sharedSecretHash) % secp256k1.CURVE.n;
1057
+ if (hashScalar === 0n) {
1058
+ return false;
1059
+ }
1060
+ const expectedPoint = secp256k1.ProjectivePoint.fromHex(spendingPubBytes).add(
1061
+ secp256k1.ProjectivePoint.BASE.multiply(hashScalar)
1062
+ );
1063
+ const providedAddress = hexToBytes(stealthAddress.address.slice(2));
1064
+ return bytesToHex(expectedPoint.toRawBytes(true)) === bytesToHex(providedAddress);
1065
+ } finally {
1066
+ secureWipe(viewingPrivBytes);
1067
+ }
1068
+ }
1069
+ function checkSecp256k1StealthAddressV1(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
893
1070
  validateSecp256k1StealthAddress(stealthAddress);
894
1071
  if (!isValidPrivateKey(spendingPrivateKey)) {
895
1072
  throw new ValidationError(
@@ -1213,12 +1390,19 @@ function deriveStealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPriv
1213
1390
  }
1214
1391
  return deriveSecp256k1StealthPrivateKey(stealthAddress, spendingPrivateKey, viewingPrivateKey);
1215
1392
  }
1216
- function checkStealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
1393
+ function deriveStealthPrivateKeyV1(stealthAddress, spendingPrivateKey, viewingPrivateKey) {
1394
+ const addressHex = stealthAddress.address.slice(2);
1395
+ if (addressHex.length === 64) {
1396
+ return deriveEd25519StealthPrivateKeyV1(stealthAddress, spendingPrivateKey, viewingPrivateKey);
1397
+ }
1398
+ return deriveSecp256k1StealthPrivateKeyV1(stealthAddress, spendingPrivateKey, viewingPrivateKey);
1399
+ }
1400
+ function checkStealthAddress(stealthAddress, viewingPrivateKey, spendingPublicKey) {
1217
1401
  const addressHex = stealthAddress.address.slice(2);
1218
1402
  if (addressHex.length === 64) {
1219
- return checkEd25519StealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey);
1403
+ return checkEd25519StealthAddress(stealthAddress, viewingPrivateKey, spendingPublicKey);
1220
1404
  }
1221
- return checkSecp256k1StealthAddress(stealthAddress, spendingPrivateKey, viewingPrivateKey);
1405
+ return checkSecp256k1StealthAddress(stealthAddress, viewingPrivateKey, spendingPublicKey);
1222
1406
  }
1223
1407
 
1224
1408
  // src/chains/solana/transfer.ts
@@ -2281,7 +2465,7 @@ async function scanForPayments(params) {
2281
2465
  });
2282
2466
  if (!tx?.meta?.logMessages) continue;
2283
2467
  for (const log of tx.meta.logMessages) {
2284
- if (!log.includes(SIP_MEMO_PREFIX)) continue;
2468
+ if (!log.includes(SIP_MEMO_PREFIX_ANY)) continue;
2285
2469
  const memoMatch = log.match(/Program log: (.+)/);
2286
2470
  if (!memoMatch) continue;
2287
2471
  const memoContent = memoMatch[1];
@@ -2371,7 +2555,8 @@ async function claimStealthPayment(params) {
2371
2555
  viewingPrivateKey,
2372
2556
  spendingPrivateKey,
2373
2557
  destinationAddress,
2374
- mint
2558
+ mint,
2559
+ version = "2"
2375
2560
  } = params;
2376
2561
  const stealthPubkeyForBalance = new PublicKey4(stealthAddress);
2377
2562
  const solBalance = await connection.getBalance(stealthPubkeyForBalance);
@@ -2388,17 +2573,13 @@ async function claimStealthPayment(params) {
2388
2573
  viewTag: 0
2389
2574
  // Not needed for derivation
2390
2575
  };
2391
- const recovery = deriveEd25519StealthPrivateKey(
2392
- stealthAddressObj,
2393
- spendingPrivateKey,
2394
- viewingPrivateKey
2395
- );
2576
+ const recovery = version === "1" ? deriveEd25519StealthPrivateKeyV1(stealthAddressObj, spendingPrivateKey, viewingPrivateKey) : deriveEd25519StealthPrivateKey(stealthAddressObj, spendingPrivateKey, viewingPrivateKey);
2396
2577
  const stealthPrivKeyBytes = hexToBytes2(recovery.privateKey.slice(2));
2397
2578
  const stealthPubkey = new PublicKey4(stealthAddress);
2398
2579
  const expectedPubKeyBytes = stealthPubkey.toBytes();
2399
2580
  const scalarBigInt = bytesToBigIntLE2(stealthPrivKeyBytes);
2400
- const ED25519_ORDER4 = 2n ** 252n + 27742317777372353535851937790883648493n;
2401
- let validScalar = scalarBigInt % ED25519_ORDER4;
2581
+ const ED25519_ORDER3 = 2n ** 252n + 27742317777372353535851937790883648493n;
2582
+ let validScalar = scalarBigInt % ED25519_ORDER3;
2402
2583
  if (validScalar === 0n) validScalar = 1n;
2403
2584
  const derivedPubKeyBytes = ed255192.ExtendedPoint.BASE.multiply(validScalar).toRawBytes();
2404
2585
  if (!derivedPubKeyBytes.every((b, i) => b === expectedPubKeyBytes[i])) {
@@ -2583,7 +2764,7 @@ var StealthScanner = class {
2583
2764
  });
2584
2765
  if (!tx?.meta?.logMessages) continue;
2585
2766
  for (const log of tx.meta.logMessages) {
2586
- if (!log.includes(SIP_MEMO_PREFIX)) continue;
2767
+ if (!log.includes(SIP_MEMO_PREFIX_ANY)) continue;
2587
2768
  const memoMatch = log.match(/Program log: (.+)/);
2588
2769
  if (!memoMatch) continue;
2589
2770
  const announcement = parseAnnouncement(memoMatch[1]);
@@ -2636,7 +2817,7 @@ var StealthScanner = class {
2636
2817
  async (logs) => {
2637
2818
  try {
2638
2819
  for (const log of logs.logs) {
2639
- if (!log.includes(SIP_MEMO_PREFIX)) continue;
2820
+ if (!log.includes(SIP_MEMO_PREFIX_ANY)) continue;
2640
2821
  const memoMatch = log.match(/Program log: (.+)/);
2641
2822
  if (!memoMatch) continue;
2642
2823
  const announcement = parseAnnouncement(memoMatch[1]);
@@ -2832,26 +3013,6 @@ function generateManagedEphemeralKeypair() {
2832
3013
  secureWipe(privateKeyBytes);
2833
3014
  disposed = true;
2834
3015
  }
2835
- },
2836
- useForStealthAddress(recipientSpendingKey, recipientViewingKey) {
2837
- if (disposed) {
2838
- throw new Error("Ephemeral keypair has been disposed");
2839
- }
2840
- try {
2841
- const result = computeStealthAddress(
2842
- privateKeyBytes,
2843
- publicKeyBytes,
2844
- recipientSpendingKey,
2845
- recipientViewingKey
2846
- );
2847
- return {
2848
- ...result,
2849
- ephemeralPublicKey: publicKeyHex,
2850
- ephemeralPublicKeyBase58: publicKeyBase58
2851
- };
2852
- } finally {
2853
- managed.dispose();
2854
- }
2855
3016
  }
2856
3017
  };
2857
3018
  return managed;
@@ -2909,89 +3070,6 @@ function wipeEphemeralPrivateKey(privateKeyHex) {
2909
3070
  const bytes = hexToBytes3(privateKeyHex.slice(2));
2910
3071
  secureWipe(bytes);
2911
3072
  }
2912
- var ED25519_ORDER2 = 2n ** 252n + 27742317777372353535851937790883648493n;
2913
- function bytesToBigIntLE3(bytes) {
2914
- let result = 0n;
2915
- for (let i = bytes.length - 1; i >= 0; i--) {
2916
- result = result << 8n | BigInt(bytes[i]);
2917
- }
2918
- return result;
2919
- }
2920
- function getEd25519Scalar2(privateKey) {
2921
- const hash = sha2562(privateKey);
2922
- hash[0] &= 248;
2923
- hash[31] &= 127;
2924
- hash[31] |= 64;
2925
- return bytesToBigIntLE3(hash.slice(0, 32));
2926
- }
2927
- function computeStealthAddress(ephemeralPrivateBytes, _ephemeralPublicBytes, recipientSpendingKey, recipientViewingKey) {
2928
- const spendingKeyBytes = hexToBytes3(recipientSpendingKey.slice(2));
2929
- const viewingKeyBytes = hexToBytes3(recipientViewingKey.slice(2));
2930
- const rawEphemeralScalar = getEd25519Scalar2(ephemeralPrivateBytes);
2931
- const ephemeralScalar = rawEphemeralScalar % ED25519_ORDER2;
2932
- if (ephemeralScalar === 0n) {
2933
- throw new Error("Invalid ephemeral scalar");
2934
- }
2935
- const spendingPoint = ed255193.ExtendedPoint.fromHex(spendingKeyBytes);
2936
- const sharedSecretPoint = spendingPoint.multiply(ephemeralScalar);
2937
- const sharedSecretBytes = sharedSecretPoint.toRawBytes();
2938
- const sharedSecretHash = sha2562(sharedSecretBytes);
2939
- const viewTag = sharedSecretHash[0];
2940
- const hashScalar = bytesToBigIntLE3(sharedSecretHash) % ED25519_ORDER2;
2941
- if (hashScalar === 0n) {
2942
- throw new Error("Invalid hash scalar");
2943
- }
2944
- const hashTimesG = ed255193.ExtendedPoint.BASE.multiply(hashScalar);
2945
- const viewingPoint = ed255193.ExtendedPoint.fromHex(viewingKeyBytes);
2946
- const stealthPoint = viewingPoint.add(hashTimesG);
2947
- const stealthAddressBytes = stealthPoint.toRawBytes();
2948
- const stealthAddress = `0x${bytesToHex2(stealthAddressBytes)}`;
2949
- const stealthAddressBase58 = ed25519PublicKeyToSolanaAddress(stealthAddress);
2950
- return {
2951
- sharedSecret: `0x${bytesToHex2(sharedSecretHash)}`,
2952
- viewTag,
2953
- stealthAddress,
2954
- stealthAddressBase58
2955
- };
2956
- }
2957
- function formatEphemeralAnnouncement(ephemeralPublicKeyBase58, viewTag, stealthAddressBase58) {
2958
- const viewTagHex = viewTag.toString(16).padStart(2, "0");
2959
- const parts = ["SIP:1", ephemeralPublicKeyBase58, viewTagHex];
2960
- if (stealthAddressBase58) {
2961
- parts.push(stealthAddressBase58);
2962
- }
2963
- return parts.join(":");
2964
- }
2965
- function parseEphemeralAnnouncement(announcement) {
2966
- if (!announcement.startsWith("SIP:1:")) {
2967
- return null;
2968
- }
2969
- const parts = announcement.slice(6).split(":");
2970
- if (parts.length < 2) {
2971
- return null;
2972
- }
2973
- const ephemeralPublicKeyBase58 = parts[0];
2974
- const viewTagHex = parts[1];
2975
- const stealthAddressBase58 = parts[2];
2976
- if (!ephemeralPublicKeyBase58 || ephemeralPublicKeyBase58.length < 32 || ephemeralPublicKeyBase58.length > 44) {
2977
- return null;
2978
- }
2979
- if (!viewTagHex || viewTagHex.length > 2 || !/^[0-9a-fA-F]+$/.test(viewTagHex)) {
2980
- return null;
2981
- }
2982
- const viewTag = parseInt(viewTagHex, 16);
2983
- if (viewTag < 0 || viewTag > 255) {
2984
- return null;
2985
- }
2986
- if (stealthAddressBase58 && (stealthAddressBase58.length < 32 || stealthAddressBase58.length > 44)) {
2987
- return null;
2988
- }
2989
- return {
2990
- ephemeralPublicKeyBase58,
2991
- viewTag,
2992
- stealthAddressBase58
2993
- };
2994
- }
2995
3073
 
2996
3074
  // src/chains/solana/privacy-adapter.ts
2997
3075
  import { PublicKey as PublicKey9 } from "@solana/web3.js";
@@ -4059,7 +4137,7 @@ async function processRawTransaction(tx, viewingPrivateKey, spendingPublicKey, o
4059
4137
  return { found: false, signature };
4060
4138
  }
4061
4139
  for (const log of tx.meta.logMessages) {
4062
- if (!log.includes(SIP_MEMO_PREFIX)) continue;
4140
+ if (!log.includes(SIP_MEMO_PREFIX_ANY)) continue;
4063
4141
  const memoMatch = log.match(/Program log: (.+)/);
4064
4142
  if (!memoMatch) continue;
4065
4143
  const memoContent = memoMatch[1];
@@ -4350,7 +4428,7 @@ var HeliusEnhanced = class {
4350
4428
  * Extract SIP metadata from a transaction
4351
4429
  *
4352
4430
  * Parses memo program instructions to find SIP announcements.
4353
- * SIP memo format: SIP:1:<ephemeral_pubkey_base58>:<view_tag_hex>
4431
+ * SIP memo format: SIP:<version>:<ephemeral_pubkey_base58>:<view_tag_hex>
4354
4432
  *
4355
4433
  * @param tx - Enhanced transaction
4356
4434
  * @returns SIP metadata if found
@@ -4361,9 +4439,9 @@ var HeliusEnhanced = class {
4361
4439
  isSIPTransaction: false
4362
4440
  };
4363
4441
  const description = tx.description || "";
4364
- if (description.includes(SIP_MEMO_PREFIX) || description.includes("SIP:")) {
4442
+ if (description.includes(SIP_MEMO_PREFIX_ANY)) {
4365
4443
  metadata.isSIPTransaction = true;
4366
- const sipMemoMatch = description.match(/SIP:1:([A-Za-z0-9]{32,44}):([0-9a-fA-F]{2})/);
4444
+ const sipMemoMatch = description.match(/SIP:[12]:([A-Za-z0-9]{32,44}):([0-9a-fA-F]{1,2})/);
4367
4445
  if (sipMemoMatch) {
4368
4446
  metadata.ephemeralPubKey = sipMemoMatch[1];
4369
4447
  metadata.viewTag = parseInt(sipMemoMatch[2], 16);
@@ -5006,7 +5084,7 @@ import { sha256 as sha2565 } from "@noble/hashes/sha2";
5006
5084
  import { bytesToHex as bytesToHex4, randomBytes as randomBytes5 } from "@noble/hashes/utils";
5007
5085
  var H_DOMAIN = "SIP-SOLANA-PEDERSEN-GENERATOR-H-v1";
5008
5086
  var G = ed255195.ExtendedPoint.BASE;
5009
- var ED25519_ORDER3 = 2n ** 252n + 27742317777372353535851937790883648493n;
5087
+ var ED25519_ORDER2 = 2n ** 252n + 27742317777372353535851937790883648493n;
5010
5088
  var ED25519_COFACTOR = 8n;
5011
5089
  var MAX_SPL_AMOUNT = 2n ** 64n - 1n;
5012
5090
  var H = generateH();
@@ -5042,18 +5120,18 @@ function commitSolana(value, blinding) {
5042
5120
  if (value < 0n) {
5043
5121
  throw new ValidationError("must be non-negative", "value");
5044
5122
  }
5045
- if (value >= ED25519_ORDER3) {
5123
+ if (value >= ED25519_ORDER2) {
5046
5124
  throw new ValidationError(
5047
5125
  "must be less than curve order",
5048
5126
  "value",
5049
- { curveOrder: ED25519_ORDER3.toString(16) }
5127
+ { curveOrder: ED25519_ORDER2.toString(16) }
5050
5128
  );
5051
5129
  }
5052
5130
  const r = blinding ?? randomBytes5(32);
5053
5131
  if (r.length !== 32) {
5054
5132
  throw new ValidationError("must be 32 bytes", "blinding", { received: r.length });
5055
5133
  }
5056
- const rScalar = bytesToBigInt2(r) % ED25519_ORDER3;
5134
+ const rScalar = bytesToBigInt2(r) % ED25519_ORDER2;
5057
5135
  if (rScalar === 0n) {
5058
5136
  return commitSolana(value, randomBytes5(32));
5059
5137
  }
@@ -5076,7 +5154,7 @@ function verifyOpeningSolana(commitment, value, blinding) {
5076
5154
  const commitmentBytes = hexToBytes4(commitment.slice(2));
5077
5155
  const C = ed255195.ExtendedPoint.fromHex(commitmentBytes);
5078
5156
  const blindingBytes = hexToBytes4(blinding.slice(2));
5079
- const rScalar = bytesToBigInt2(blindingBytes) % ED25519_ORDER3;
5157
+ const rScalar = bytesToBigInt2(blindingBytes) % ED25519_ORDER2;
5080
5158
  let expected;
5081
5159
  if (value === 0n) {
5082
5160
  expected = H.multiply(rScalar);
@@ -5189,14 +5267,14 @@ function subtractCommitmentsSolana(c1, c2) {
5189
5267
  function addBlindingsSolana(b1, b2) {
5190
5268
  const r1 = bytesToBigInt2(hexToBytes4(b1.slice(2)));
5191
5269
  const r2 = bytesToBigInt2(hexToBytes4(b2.slice(2)));
5192
- const sum = (r1 + r2) % ED25519_ORDER3;
5270
+ const sum = (r1 + r2) % ED25519_ORDER2;
5193
5271
  const sumBytes = bigIntToBytes2(sum, 32);
5194
5272
  return `0x${bytesToHex4(sumBytes)}`;
5195
5273
  }
5196
5274
  function subtractBlindingsSolana(b1, b2) {
5197
5275
  const r1 = bytesToBigInt2(hexToBytes4(b1.slice(2)));
5198
5276
  const r2 = bytesToBigInt2(hexToBytes4(b2.slice(2)));
5199
- const diff = (r1 - r2 + ED25519_ORDER3) % ED25519_ORDER3;
5277
+ const diff = (r1 - r2 + ED25519_ORDER2) % ED25519_ORDER2;
5200
5278
  const diffBytes = bigIntToBytes2(diff, 32);
5201
5279
  return `0x${bytesToHex4(diffBytes)}`;
5202
5280
  }
@@ -5805,7 +5883,7 @@ async function createProxyAgent(config, options = {}) {
5805
5883
  const parsed = parseProxyConfig(config === "tor" ? `socks5://${TOR_HOST}:${TOR_PORTS[0]}` : config);
5806
5884
  try {
5807
5885
  if (parsed.type === "socks5" || parsed.type === "socks4" || config === "tor") {
5808
- const { SocksProxyAgent } = await import("./dist-2OGQ7FED.mjs");
5886
+ const { SocksProxyAgent } = await import("./dist-PYEXZNFD.mjs");
5809
5887
  return new SocksProxyAgent(proxyUrl, { timeout });
5810
5888
  }
5811
5889
  if (parsed.type === "http" || parsed.type === "https") {
@@ -7665,7 +7743,11 @@ export {
7665
7743
  generateEd25519StealthMetaAddress,
7666
7744
  generateEd25519StealthAddress,
7667
7745
  deriveEd25519StealthPrivateKey,
7746
+ deriveEd25519StealthPrivateKeyV1,
7668
7747
  checkEd25519StealthAddress,
7748
+ checkEd25519StealthAddressV1,
7749
+ deriveSecp256k1StealthPrivateKeyV1,
7750
+ checkSecp256k1StealthAddressV1,
7669
7751
  publicKeyToEthAddress,
7670
7752
  encodeStealthMetaAddress,
7671
7753
  decodeStealthMetaAddress,
@@ -7680,6 +7762,7 @@ export {
7680
7762
  generateStealthMetaAddress,
7681
7763
  generateStealthAddress,
7682
7764
  deriveStealthPrivateKey,
7765
+ deriveStealthPrivateKeyV1,
7683
7766
  checkStealthAddress,
7684
7767
  commit,
7685
7768
  verifyOpening,
@@ -7727,8 +7810,6 @@ export {
7727
7810
  batchGenerateManagedEphemeralKeypairs,
7728
7811
  disposeEphemeralKeypairs,
7729
7812
  wipeEphemeralPrivateKey,
7730
- formatEphemeralAnnouncement,
7731
- parseEphemeralAnnouncement,
7732
7813
  HeliusProvider,
7733
7814
  GenericProvider,
7734
7815
  createProvider,
@@ -7748,7 +7829,7 @@ export {
7748
7829
  generateMnemonic,
7749
7830
  isValidMnemonic,
7750
7831
  getDerivationPath,
7751
- ED25519_ORDER3 as ED25519_ORDER,
7832
+ ED25519_ORDER2 as ED25519_ORDER,
7752
7833
  MAX_SPL_AMOUNT,
7753
7834
  commitSolana,
7754
7835
  verifyOpeningSolana,