veilix-sdk 0.2.3 → 0.3.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/index.cjs CHANGED
@@ -65,7 +65,7 @@ function formatBaseUnits(value, decimals) {
65
65
 
66
66
  // src/idl/veilix-devnet.json
67
67
  var veilix_devnet_default = {
68
- address: "HbatG5gpfs2g3N4gc2Qkfmmeu4zaBEVxzrDdYtWNLyyA",
68
+ address: "Vxi1QK84Akv4yGngjvkWNmEsK7XpsSrpDaPBoiyXGPG",
69
69
  metadata: {
70
70
  name: "veilix",
71
71
  version: "0.2.0",
@@ -666,6 +666,38 @@ var veilix_devnet_default = {
666
666
  {
667
667
  name: "system_program",
668
668
  address: "11111111111111111111111111111111"
669
+ },
670
+ {
671
+ name: "event_authority",
672
+ pda: {
673
+ seeds: [
674
+ {
675
+ kind: "const",
676
+ value: [
677
+ 95,
678
+ 95,
679
+ 101,
680
+ 118,
681
+ 101,
682
+ 110,
683
+ 116,
684
+ 95,
685
+ 97,
686
+ 117,
687
+ 116,
688
+ 104,
689
+ 111,
690
+ 114,
691
+ 105,
692
+ 116,
693
+ 121
694
+ ]
695
+ }
696
+ ]
697
+ }
698
+ },
699
+ {
700
+ name: "program"
669
701
  }
670
702
  ],
671
703
  args: [
@@ -728,6 +760,91 @@ var veilix_devnet_default = {
728
760
  ]
729
761
  }
730
762
  },
763
+ {
764
+ name: "program_data",
765
+ docs: [
766
+ "This program's ProgramData. Only its upgrade authority may initialize the network,",
767
+ "so nobody can claim the config authority between deploy and setup."
768
+ ],
769
+ pda: {
770
+ seeds: [
771
+ {
772
+ kind: "const",
773
+ value: [
774
+ 7,
775
+ 107,
776
+ 64,
777
+ 50,
778
+ 251,
779
+ 172,
780
+ 47,
781
+ 215,
782
+ 89,
783
+ 179,
784
+ 92,
785
+ 125,
786
+ 67,
787
+ 162,
788
+ 96,
789
+ 45,
790
+ 239,
791
+ 91,
792
+ 223,
793
+ 168,
794
+ 251,
795
+ 138,
796
+ 165,
797
+ 133,
798
+ 253,
799
+ 74,
800
+ 152,
801
+ 142,
802
+ 6,
803
+ 85,
804
+ 93,
805
+ 119
806
+ ]
807
+ }
808
+ ],
809
+ program: {
810
+ kind: "const",
811
+ value: [
812
+ 2,
813
+ 168,
814
+ 246,
815
+ 145,
816
+ 78,
817
+ 136,
818
+ 161,
819
+ 176,
820
+ 226,
821
+ 16,
822
+ 21,
823
+ 62,
824
+ 247,
825
+ 99,
826
+ 174,
827
+ 43,
828
+ 0,
829
+ 194,
830
+ 185,
831
+ 61,
832
+ 22,
833
+ 193,
834
+ 36,
835
+ 210,
836
+ 192,
837
+ 83,
838
+ 122,
839
+ 16,
840
+ 4,
841
+ 128,
842
+ 0,
843
+ 0
844
+ ]
845
+ }
846
+ }
847
+ },
731
848
  {
732
849
  name: "system_program",
733
850
  address: "11111111111111111111111111111111"
@@ -1056,6 +1173,31 @@ var veilix_devnet_default = {
1056
1173
  ]
1057
1174
  }
1058
1175
  },
1176
+ {
1177
+ name: "treasury",
1178
+ docs: [
1179
+ "Holds the SOL pool. Funded with its rent-exempt reserve here so that no withdrawal",
1180
+ "can fail for leaving it below that reserve."
1181
+ ],
1182
+ writable: true,
1183
+ pda: {
1184
+ seeds: [
1185
+ {
1186
+ kind: "const",
1187
+ value: [
1188
+ 116,
1189
+ 114,
1190
+ 101,
1191
+ 97,
1192
+ 115,
1193
+ 117,
1194
+ 114,
1195
+ 121
1196
+ ]
1197
+ }
1198
+ ]
1199
+ }
1200
+ },
1059
1201
  {
1060
1202
  name: "system_program",
1061
1203
  address: "11111111111111111111111111111111"
@@ -1464,25 +1606,355 @@ var veilix_devnet_default = {
1464
1606
  value: [
1465
1607
  114,
1466
1608
  101,
1467
- 108,
1468
- 97,
1469
- 121,
1609
+ 108,
1610
+ 97,
1611
+ 121,
1612
+ 101,
1613
+ 114
1614
+ ]
1615
+ },
1616
+ {
1617
+ kind: "account",
1618
+ path: "user"
1619
+ }
1620
+ ]
1621
+ }
1622
+ }
1623
+ ],
1624
+ args: [
1625
+ {
1626
+ name: "worker",
1627
+ type: "pubkey"
1628
+ }
1629
+ ]
1630
+ },
1631
+ {
1632
+ name: "swap",
1633
+ docs: [
1634
+ "Private swap. Remaining accounts: the protocol fee wallets for the input asset (SOL",
1635
+ "accounts or their token accounts, in config order), then the DEX instruction's accounts."
1636
+ ],
1637
+ discriminator: [
1638
+ 248,
1639
+ 198,
1640
+ 158,
1641
+ 145,
1642
+ 225,
1643
+ 117,
1644
+ 135,
1645
+ 200
1646
+ ],
1647
+ accounts: [
1648
+ {
1649
+ name: "relayer",
1650
+ writable: true,
1651
+ signer: true
1652
+ },
1653
+ {
1654
+ name: "relayer_account",
1655
+ writable: true,
1656
+ pda: {
1657
+ seeds: [
1658
+ {
1659
+ kind: "const",
1660
+ value: [
1661
+ 114,
1662
+ 101,
1663
+ 108,
1664
+ 97,
1665
+ 121,
1666
+ 101,
1667
+ 114
1668
+ ]
1669
+ },
1670
+ {
1671
+ kind: "account",
1672
+ path: "relayer_account.owner",
1673
+ account: "RelayerAccount"
1674
+ }
1675
+ ]
1676
+ }
1677
+ },
1678
+ {
1679
+ name: "network_state",
1680
+ pda: {
1681
+ seeds: [
1682
+ {
1683
+ kind: "const",
1684
+ value: [
1685
+ 99,
1686
+ 111,
1687
+ 110,
1688
+ 102,
1689
+ 105,
1690
+ 103
1691
+ ]
1692
+ }
1693
+ ]
1694
+ }
1695
+ },
1696
+ {
1697
+ name: "swap_config",
1698
+ pda: {
1699
+ seeds: [
1700
+ {
1701
+ kind: "const",
1702
+ value: [
1703
+ 115,
1704
+ 119,
1705
+ 97,
1706
+ 112,
1707
+ 95,
1708
+ 99,
1709
+ 111,
1710
+ 110,
1711
+ 102,
1712
+ 105,
1713
+ 103
1714
+ ]
1715
+ }
1716
+ ]
1717
+ }
1718
+ },
1719
+ {
1720
+ name: "tree_in",
1721
+ docs: [
1722
+ "Tree of the asset being spent. The handler checks it is the PDA for its mint."
1723
+ ],
1724
+ writable: true
1725
+ },
1726
+ {
1727
+ name: "tree_out",
1728
+ docs: [
1729
+ "Tree that receives the swapped note."
1730
+ ],
1731
+ writable: true
1732
+ },
1733
+ {
1734
+ name: "treasury",
1735
+ writable: true,
1736
+ pda: {
1737
+ seeds: [
1738
+ {
1739
+ kind: "const",
1740
+ value: [
1741
+ 116,
1742
+ 114,
1743
+ 101,
1744
+ 97,
1745
+ 115,
1746
+ 117,
1747
+ 114,
1748
+ 121
1749
+ ]
1750
+ }
1751
+ ]
1752
+ }
1753
+ },
1754
+ {
1755
+ name: "escrow",
1756
+ docs: [
1757
+ "Signs the DEX call. Holds nothing between transactions."
1758
+ ],
1759
+ writable: true,
1760
+ pda: {
1761
+ seeds: [
1762
+ {
1763
+ kind: "const",
1764
+ value: [
1765
+ 115,
1766
+ 119,
1767
+ 97,
1768
+ 112,
1769
+ 95,
1770
+ 101,
1771
+ 115,
1772
+ 99,
1773
+ 114,
1774
+ 111,
1775
+ 119
1776
+ ]
1777
+ }
1778
+ ]
1779
+ }
1780
+ },
1781
+ {
1782
+ name: "treasury_ata_in",
1783
+ docs: [
1784
+ "Treasury ATA for `mint_in`. `None` when spending SOL."
1785
+ ],
1786
+ writable: true,
1787
+ optional: true
1788
+ },
1789
+ {
1790
+ name: "treasury_ata_out",
1791
+ docs: [
1792
+ "Treasury ATA for `mint_out`. `None` when receiving SOL."
1793
+ ],
1794
+ writable: true,
1795
+ optional: true
1796
+ },
1797
+ {
1798
+ name: "escrow_ata_in",
1799
+ docs: [
1800
+ "Escrow ATA for `mint_in` (wrapped SOL when spending SOL). Must exist: prepend an",
1801
+ "idempotent ATA create. A wrapped-SOL escrow account is closed at the end of the swap."
1802
+ ],
1803
+ writable: true
1804
+ },
1805
+ {
1806
+ name: "escrow_ata_out",
1807
+ docs: [
1808
+ "Escrow ATA for `mint_out` (wrapped SOL when receiving SOL). Must exist, as above."
1809
+ ],
1810
+ writable: true
1811
+ },
1812
+ {
1813
+ name: "relayer_ata",
1814
+ docs: [
1815
+ "Relayer ATA for `mint_in`, paid the relayer fee. `None` when spending SOL."
1816
+ ],
1817
+ writable: true,
1818
+ optional: true
1819
+ },
1820
+ {
1821
+ name: "nullifier0",
1822
+ writable: true,
1823
+ pda: {
1824
+ seeds: [
1825
+ {
1826
+ kind: "const",
1827
+ value: [
1828
+ 110,
1829
+ 117,
1830
+ 108,
1831
+ 108,
1832
+ 105,
1833
+ 102,
1834
+ 105,
1835
+ 101,
1836
+ 114
1837
+ ]
1838
+ },
1839
+ {
1840
+ kind: "arg",
1841
+ path: "proof.input_nullifiers [0]"
1842
+ }
1843
+ ]
1844
+ }
1845
+ },
1846
+ {
1847
+ name: "nullifier1",
1848
+ writable: true,
1849
+ pda: {
1850
+ seeds: [
1851
+ {
1852
+ kind: "const",
1853
+ value: [
1854
+ 110,
1855
+ 117,
1856
+ 108,
1857
+ 108,
1858
+ 105,
1859
+ 102,
1860
+ 105,
1861
+ 101,
1862
+ 114
1863
+ ]
1864
+ },
1865
+ {
1866
+ kind: "arg",
1867
+ path: "proof.input_nullifiers [1]"
1868
+ }
1869
+ ]
1870
+ }
1871
+ },
1872
+ {
1873
+ name: "mint_in",
1874
+ docs: [
1875
+ "Mint of the spent asset (the native mint when spending SOL)."
1876
+ ]
1877
+ },
1878
+ {
1879
+ name: "mint_out",
1880
+ docs: [
1881
+ "Mint of the received asset (the native mint when receiving SOL)."
1882
+ ]
1883
+ },
1884
+ {
1885
+ name: "token_program_in"
1886
+ },
1887
+ {
1888
+ name: "token_program_out"
1889
+ },
1890
+ {
1891
+ name: "dex_program"
1892
+ },
1893
+ {
1894
+ name: "system_program",
1895
+ address: "11111111111111111111111111111111"
1896
+ },
1897
+ {
1898
+ name: "event_authority",
1899
+ pda: {
1900
+ seeds: [
1901
+ {
1902
+ kind: "const",
1903
+ value: [
1904
+ 95,
1905
+ 95,
1906
+ 101,
1907
+ 118,
1470
1908
  101,
1471
- 114
1909
+ 110,
1910
+ 116,
1911
+ 95,
1912
+ 97,
1913
+ 117,
1914
+ 116,
1915
+ 104,
1916
+ 111,
1917
+ 114,
1918
+ 105,
1919
+ 116,
1920
+ 121
1472
1921
  ]
1473
- },
1474
- {
1475
- kind: "account",
1476
- path: "user"
1477
1922
  }
1478
1923
  ]
1479
1924
  }
1925
+ },
1926
+ {
1927
+ name: "program"
1480
1928
  }
1481
1929
  ],
1482
1930
  args: [
1483
1931
  {
1484
- name: "worker",
1485
- type: "pubkey"
1932
+ name: "proof",
1933
+ type: {
1934
+ defined: {
1935
+ name: "TransactionProof"
1936
+ }
1937
+ }
1938
+ },
1939
+ {
1940
+ name: "params",
1941
+ type: {
1942
+ defined: {
1943
+ name: "SwapParams"
1944
+ }
1945
+ }
1946
+ },
1947
+ {
1948
+ name: "encrypted_output1",
1949
+ type: "bytes"
1950
+ },
1951
+ {
1952
+ name: "encrypted_output2",
1953
+ type: "bytes"
1954
+ },
1955
+ {
1956
+ name: "route_data",
1957
+ type: "bytes"
1486
1958
  }
1487
1959
  ]
1488
1960
  },
@@ -1720,6 +2192,38 @@ var veilix_devnet_default = {
1720
2192
  {
1721
2193
  name: "system_program",
1722
2194
  address: "11111111111111111111111111111111"
2195
+ },
2196
+ {
2197
+ name: "event_authority",
2198
+ pda: {
2199
+ seeds: [
2200
+ {
2201
+ kind: "const",
2202
+ value: [
2203
+ 95,
2204
+ 95,
2205
+ 101,
2206
+ 118,
2207
+ 101,
2208
+ 110,
2209
+ 116,
2210
+ 95,
2211
+ 97,
2212
+ 117,
2213
+ 116,
2214
+ 104,
2215
+ 111,
2216
+ 114,
2217
+ 105,
2218
+ 116,
2219
+ 121
2220
+ ]
2221
+ }
2222
+ ]
2223
+ }
2224
+ },
2225
+ {
2226
+ name: "program"
1723
2227
  }
1724
2228
  ],
1725
2229
  args: [
@@ -2086,6 +2590,38 @@ var veilix_devnet_default = {
2086
2590
  {
2087
2591
  name: "system_program",
2088
2592
  address: "11111111111111111111111111111111"
2593
+ },
2594
+ {
2595
+ name: "event_authority",
2596
+ pda: {
2597
+ seeds: [
2598
+ {
2599
+ kind: "const",
2600
+ value: [
2601
+ 95,
2602
+ 95,
2603
+ 101,
2604
+ 118,
2605
+ 101,
2606
+ 110,
2607
+ 116,
2608
+ 95,
2609
+ 97,
2610
+ 117,
2611
+ 116,
2612
+ 104,
2613
+ 111,
2614
+ 114,
2615
+ 105,
2616
+ 116,
2617
+ 121
2618
+ ]
2619
+ }
2620
+ ]
2621
+ }
2622
+ },
2623
+ {
2624
+ name: "program"
2089
2625
  }
2090
2626
  ],
2091
2627
  args: [
@@ -2534,6 +3070,83 @@ var veilix_devnet_default = {
2534
3070
  }
2535
3071
  ]
2536
3072
  },
3073
+ {
3074
+ name: "update_swap_config",
3075
+ docs: [
3076
+ "Replaces the list of DEX programs the swap escrow may call. Config authority only."
3077
+ ],
3078
+ discriminator: [
3079
+ 123,
3080
+ 172,
3081
+ 158,
3082
+ 60,
3083
+ 104,
3084
+ 133,
3085
+ 39,
3086
+ 13
3087
+ ],
3088
+ accounts: [
3089
+ {
3090
+ name: "authority",
3091
+ writable: true,
3092
+ signer: true
3093
+ },
3094
+ {
3095
+ name: "network_state",
3096
+ pda: {
3097
+ seeds: [
3098
+ {
3099
+ kind: "const",
3100
+ value: [
3101
+ 99,
3102
+ 111,
3103
+ 110,
3104
+ 102,
3105
+ 105,
3106
+ 103
3107
+ ]
3108
+ }
3109
+ ]
3110
+ }
3111
+ },
3112
+ {
3113
+ name: "swap_config",
3114
+ writable: true,
3115
+ pda: {
3116
+ seeds: [
3117
+ {
3118
+ kind: "const",
3119
+ value: [
3120
+ 115,
3121
+ 119,
3122
+ 97,
3123
+ 112,
3124
+ 95,
3125
+ 99,
3126
+ 111,
3127
+ 110,
3128
+ 102,
3129
+ 105,
3130
+ 103
3131
+ ]
3132
+ }
3133
+ ]
3134
+ }
3135
+ },
3136
+ {
3137
+ name: "system_program",
3138
+ address: "11111111111111111111111111111111"
3139
+ }
3140
+ ],
3141
+ args: [
3142
+ {
3143
+ name: "allowed_programs",
3144
+ type: {
3145
+ vec: "pubkey"
3146
+ }
3147
+ }
3148
+ ]
3149
+ },
2537
3150
  {
2538
3151
  name: "withdraw",
2539
3152
  discriminator: [
@@ -2692,6 +3305,38 @@ var veilix_devnet_default = {
2692
3305
  {
2693
3306
  name: "system_program",
2694
3307
  address: "11111111111111111111111111111111"
3308
+ },
3309
+ {
3310
+ name: "event_authority",
3311
+ pda: {
3312
+ seeds: [
3313
+ {
3314
+ kind: "const",
3315
+ value: [
3316
+ 95,
3317
+ 95,
3318
+ 101,
3319
+ 118,
3320
+ 101,
3321
+ 110,
3322
+ 116,
3323
+ 95,
3324
+ 97,
3325
+ 117,
3326
+ 116,
3327
+ 104,
3328
+ 111,
3329
+ 114,
3330
+ 105,
3331
+ 116,
3332
+ 121
3333
+ ]
3334
+ }
3335
+ ]
3336
+ }
3337
+ },
3338
+ {
3339
+ name: "program"
2695
3340
  }
2696
3341
  ],
2697
3342
  args: [
@@ -2801,6 +3446,19 @@ var veilix_devnet_default = {
2801
3446
  20
2802
3447
  ]
2803
3448
  },
3449
+ {
3450
+ name: "SwapConfig",
3451
+ discriminator: [
3452
+ 212,
3453
+ 45,
3454
+ 70,
3455
+ 222,
3456
+ 245,
3457
+ 122,
3458
+ 125,
3459
+ 166
3460
+ ]
3461
+ },
2804
3462
  {
2805
3463
  name: "TreeAccount",
2806
3464
  discriminator: [
@@ -2842,6 +3500,19 @@ var veilix_devnet_default = {
2842
3500
  159
2843
3501
  ]
2844
3502
  },
3503
+ {
3504
+ name: "PrivateSwapEvent",
3505
+ discriminator: [
3506
+ 150,
3507
+ 165,
3508
+ 138,
3509
+ 189,
3510
+ 123,
3511
+ 86,
3512
+ 117,
3513
+ 39
3514
+ ]
3515
+ },
2845
3516
  {
2846
3517
  name: "RelayerCancelled",
2847
3518
  discriminator: [
@@ -3086,24 +3757,74 @@ var veilix_devnet_default = {
3086
3757
  msg: "Too many workers"
3087
3758
  },
3088
3759
  {
3089
- code: 6030,
3090
- name: "AlreadyRegistered",
3091
- msg: "Already registered"
3760
+ code: 6030,
3761
+ name: "AlreadyRegistered",
3762
+ msg: "Already registered"
3763
+ },
3764
+ {
3765
+ code: 6031,
3766
+ name: "NotRegistered",
3767
+ msg: "Not registered"
3768
+ },
3769
+ {
3770
+ code: 6032,
3771
+ name: "TooManyFeeAssets",
3772
+ msg: "Relayer has earned fees in too many assets"
3773
+ },
3774
+ {
3775
+ code: 6033,
3776
+ name: "FeeRepaymentAccounts",
3777
+ msg: "Fee repayment accounts do not match earned fees"
3778
+ },
3779
+ {
3780
+ code: 6034,
3781
+ name: "DexProgramNotAllowed",
3782
+ msg: "DEX program is not on the swap allowlist"
3783
+ },
3784
+ {
3785
+ code: 6035,
3786
+ name: "TooManyDexPrograms",
3787
+ msg: "Too many allowlisted DEX programs"
3788
+ },
3789
+ {
3790
+ code: 6036,
3791
+ name: "SlippageExceeded",
3792
+ msg: "Swap output is below the minimum amount"
3793
+ },
3794
+ {
3795
+ code: 6037,
3796
+ name: "SwapInputMismatch",
3797
+ msg: "DEX did not use exactly the escrowed swap input"
3798
+ },
3799
+ {
3800
+ code: 6038,
3801
+ name: "InvalidSwapAccounts",
3802
+ msg: "Swap accounts do not match the trees"
3803
+ },
3804
+ {
3805
+ code: 6039,
3806
+ name: "EscrowTampered",
3807
+ msg: "Swap escrow was modified by the DEX"
3808
+ },
3809
+ {
3810
+ code: 6040,
3811
+ name: "InvalidNoteKey",
3812
+ msg: "Note public key or blinding is not a valid field element"
3092
3813
  },
3093
3814
  {
3094
- code: 6031,
3095
- name: "NotRegistered",
3096
- msg: "Not registered"
3815
+ code: 6041,
3816
+ name: "NotUpgradeAuthority",
3817
+ msg: "Only the program upgrade authority can initialize the network"
3097
3818
  },
3098
3819
  {
3099
- code: 6032,
3100
- name: "TooManyFeeAssets",
3101
- msg: "Relayer has earned fees in too many assets"
3820
+ code: 6042,
3821
+ name: "InvalidFeeSplit",
3822
+ msg: "Fee wallets must be distinct, non-default and split at most the allowed total"
3102
3823
  },
3103
3824
  {
3104
- code: 6033,
3105
- name: "FeeRepaymentAccounts",
3106
- msg: "Fee repayment accounts do not match earned fees"
3825
+ code: 6043,
3826
+ name: "UnsupportedMintExtension",
3827
+ msg: "Token mint has an extension the pool does not support"
3107
3828
  }
3108
3829
  ],
3109
3830
  types: [
@@ -3284,6 +4005,68 @@ var veilix_devnet_default = {
3284
4005
  kind: "struct"
3285
4006
  }
3286
4007
  },
4008
+ {
4009
+ name: "PrivateSwapEvent",
4010
+ docs: [
4011
+ "Emitted once per swap. The asset-B note is `commitment` at `index` in the `mint_out` tree."
4012
+ ],
4013
+ type: {
4014
+ kind: "struct",
4015
+ fields: [
4016
+ {
4017
+ name: "mint_in",
4018
+ type: "pubkey"
4019
+ },
4020
+ {
4021
+ name: "mint_out",
4022
+ type: "pubkey"
4023
+ },
4024
+ {
4025
+ name: "amount_in",
4026
+ type: "u64"
4027
+ },
4028
+ {
4029
+ name: "fee",
4030
+ type: "u64"
4031
+ },
4032
+ {
4033
+ name: "amount_out",
4034
+ type: "u64"
4035
+ },
4036
+ {
4037
+ name: "input_nullifiers",
4038
+ type: {
4039
+ array: [
4040
+ {
4041
+ array: [
4042
+ "u8",
4043
+ 32
4044
+ ]
4045
+ },
4046
+ 2
4047
+ ]
4048
+ }
4049
+ },
4050
+ {
4051
+ name: "relayer",
4052
+ type: "pubkey"
4053
+ },
4054
+ {
4055
+ name: "commitment",
4056
+ type: {
4057
+ array: [
4058
+ "u8",
4059
+ 32
4060
+ ]
4061
+ }
4062
+ },
4063
+ {
4064
+ name: "index",
4065
+ type: "u64"
4066
+ }
4067
+ ]
4068
+ }
4069
+ },
3287
4070
  {
3288
4071
  name: "RelayerAccount",
3289
4072
  docs: [
@@ -3478,6 +4261,86 @@ var veilix_devnet_default = {
3478
4261
  ]
3479
4262
  }
3480
4263
  },
4264
+ {
4265
+ name: "SwapConfig",
4266
+ docs: [
4267
+ 'Programs the swap escrow is allowed to call. PDA seeds: `["swap_config"]`.'
4268
+ ],
4269
+ type: {
4270
+ kind: "struct",
4271
+ fields: [
4272
+ {
4273
+ name: "allowed_programs",
4274
+ type: {
4275
+ vec: "pubkey"
4276
+ }
4277
+ }
4278
+ ]
4279
+ }
4280
+ },
4281
+ {
4282
+ name: "SwapParams",
4283
+ docs: [
4284
+ "Swap parameters. All of them are bound into the proof's `extDataHash`."
4285
+ ],
4286
+ type: {
4287
+ kind: "struct",
4288
+ fields: [
4289
+ {
4290
+ name: "amount_in",
4291
+ docs: [
4292
+ "Asset-A amount spent from the pool, fee included."
4293
+ ],
4294
+ type: "u64"
4295
+ },
4296
+ {
4297
+ name: "fee",
4298
+ docs: [
4299
+ "Asset-A fee: protocol wallets get their split of `amount_in`, the relayer the rest."
4300
+ ],
4301
+ type: "u64"
4302
+ },
4303
+ {
4304
+ name: "min_amount_out",
4305
+ docs: [
4306
+ "Minimum asset-B amount that must reach the treasury."
4307
+ ],
4308
+ type: "u64"
4309
+ },
4310
+ {
4311
+ name: "out_pubkey",
4312
+ docs: [
4313
+ "One-time shielded public key of the asset-B note (32-byte big-endian field element)."
4314
+ ],
4315
+ type: {
4316
+ array: [
4317
+ "u8",
4318
+ 32
4319
+ ]
4320
+ }
4321
+ },
4322
+ {
4323
+ name: "out_blinding",
4324
+ docs: [
4325
+ "Blinding of the asset-B note (32-byte big-endian field element)."
4326
+ ],
4327
+ type: {
4328
+ array: [
4329
+ "u8",
4330
+ 32
4331
+ ]
4332
+ }
4333
+ },
4334
+ {
4335
+ name: "encrypted_note",
4336
+ docs: [
4337
+ "Optional encrypted recovery data for the asset-B note."
4338
+ ],
4339
+ type: "bytes"
4340
+ }
4341
+ ]
4342
+ }
4343
+ },
3481
4344
  {
3482
4345
  name: "TransactionProof",
3483
4346
  docs: [
@@ -7376,7 +8239,7 @@ var MAINNET_TOKEN_MINTS = {
7376
8239
  USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
7377
8240
  };
7378
8241
  var DEVNET_TOKEN_MINTS = {
7379
- Veilix: "GAFN64LvtCBoc5BHncVn3JEJGpq42rUzQjPmvMK2UhZH",
8242
+ Veilix: "Gmo636w21RBZX9ySVtPYcuYP6f1E5bdW5eBYhvK1bc8J",
7380
8243
  Bitcoin: "",
7381
8244
  Ethereum: "",
7382
8245
  USDC: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
@@ -7426,7 +8289,7 @@ function getDepositQueueForNetwork(network) {
7426
8289
  // package.json
7427
8290
  var package_default = {
7428
8291
  name: "veilix-sdk",
7429
- version: "0.2.3"};
8292
+ version: "0.3.0"};
7430
8293
 
7431
8294
  // src/circuits/constants.ts
7432
8295
  var PACKAGE_NAME = package_default.name;
@@ -7669,10 +8532,10 @@ var DEPOSIT_COMPUTE_UNIT_LIMIT = 35e4;
7669
8532
  function bytesToHex(bytes) {
7670
8533
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
7671
8534
  }
7672
- function hexToBytes(hex) {
7673
- const clean = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
8535
+ function hexToBytes(hex2) {
8536
+ const clean = hex2.startsWith("0x") || hex2.startsWith("0X") ? hex2.slice(2) : hex2;
7674
8537
  if (clean.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(clean)) {
7675
- throw new Error(`veilix-sdk: invalid hex string "${hex}"`);
8538
+ throw new Error(`veilix-sdk: invalid hex string "${hex2}"`);
7676
8539
  }
7677
8540
  const out = new Uint8Array(clean.length / 2);
7678
8541
  for (let i = 0; i < out.length; i++) {
@@ -7681,15 +8544,15 @@ function hexToBytes(hex) {
7681
8544
  return out;
7682
8545
  }
7683
8546
  function bigintToBytes32(value) {
7684
- const hex = BigInt(value).toString(16).padStart(64, "0");
7685
- if (hex.length > 64) {
8547
+ const hex2 = BigInt(value).toString(16).padStart(64, "0");
8548
+ if (hex2.length > 64) {
7686
8549
  throw new Error("veilix-sdk: value does not fit in 32 bytes");
7687
8550
  }
7688
- return hexToBytes(hex);
8551
+ return hexToBytes(hex2);
7689
8552
  }
7690
8553
  function bytesToBigint(bytes) {
7691
- const hex = bytesToHex(bytes);
7692
- return hex ? BigInt(`0x${hex}`) : 0n;
8554
+ const hex2 = bytesToHex(bytes);
8555
+ return hex2 ? BigInt(`0x${hex2}`) : 0n;
7693
8556
  }
7694
8557
  function toHex32(value) {
7695
8558
  return `0x${BigInt(value).toString(16).padStart(64, "0")}`;
@@ -7807,6 +8670,7 @@ var Utxo = class _Utxo {
7807
8670
  // src/core/note.ts
7808
8671
  var NOTE_PREFIX = "vx2";
7809
8672
  var ENCRYPTED_OUTPUT_VERSION = 1;
8673
+ var ENCRYPTED_SWAP_OUTPUT_VERSION = 2;
7810
8674
  var ENCRYPTED_OUTPUT_PLAINTEXT_BYTES = 1 + 8 + 32 + 32;
7811
8675
  var SECRETBOX_NONCE_BYTES = nacl__default.default.secretbox.nonceLength;
7812
8676
  function encodeNote(utxo) {
@@ -7839,14 +8703,14 @@ function decodeNote(note) {
7839
8703
  throw new Error("veilix-sdk: invalid note format");
7840
8704
  }
7841
8705
  const [, amountHex, privKeyHex, blindingHex, mint] = parts;
7842
- const hex = /^[0-9a-f]+$/i;
7843
- if (!hex.test(amountHex) || !hex.test(privKeyHex) || !hex.test(blindingHex)) {
8706
+ const hex2 = /^[0-9a-f]+$/i;
8707
+ if (!hex2.test(amountHex) || !hex2.test(privKeyHex) || !hex2.test(blindingHex)) {
7844
8708
  throw new Error("veilix-sdk: invalid note format");
7845
8709
  }
7846
- let mintKey = null;
8710
+ let mintKey2 = null;
7847
8711
  if (mint) {
7848
8712
  try {
7849
- mintKey = new web3_js.PublicKey(mint);
8713
+ mintKey2 = new web3_js.PublicKey(mint);
7850
8714
  } catch {
7851
8715
  throw new Error("veilix-sdk: invalid note mint");
7852
8716
  }
@@ -7855,7 +8719,7 @@ function decodeNote(note) {
7855
8719
  amount: BigInt(`0x${amountHex}`),
7856
8720
  keypair: VeilixKeypair.fromPrivateKey(BigInt(`0x${privKeyHex}`)),
7857
8721
  blinding: BigInt(`0x${blindingHex}`),
7858
- mint: mintKey
8722
+ mint: mintKey2
7859
8723
  });
7860
8724
  }
7861
8725
  function describeUtxo(utxo) {
@@ -7873,7 +8737,7 @@ function describeUtxo(utxo) {
7873
8737
  function parseSecretNote(note) {
7874
8738
  return describeUtxo(decodeNote(note));
7875
8739
  }
7876
- function encryptNoteOutput(key, utxo) {
8740
+ function encryptNoteOutput(key2, utxo) {
7877
8741
  const amount = new Uint8Array(8);
7878
8742
  new DataView(amount.buffer).setBigUint64(0, utxo.amount, true);
7879
8743
  const plaintext = concatBytes([
@@ -7883,21 +8747,38 @@ function encryptNoteOutput(key, utxo) {
7883
8747
  bigintToBytes32(utxo.blinding)
7884
8748
  ]);
7885
8749
  const nonce = nacl__default.default.randomBytes(SECRETBOX_NONCE_BYTES);
7886
- return concatBytes([nonce, nacl__default.default.secretbox(plaintext, nonce, key)]);
8750
+ return concatBytes([nonce, nacl__default.default.secretbox(plaintext, nonce, key2)]);
8751
+ }
8752
+ function encryptSwapNoteOutput(key2, keypair, blinding) {
8753
+ const plaintext = concatBytes([
8754
+ Uint8Array.of(ENCRYPTED_SWAP_OUTPUT_VERSION),
8755
+ new Uint8Array(8),
8756
+ bigintToBytes32(keypair.privKey),
8757
+ bigintToBytes32(blinding)
8758
+ ]);
8759
+ const nonce = nacl__default.default.randomBytes(SECRETBOX_NONCE_BYTES);
8760
+ return concatBytes([nonce, nacl__default.default.secretbox(plaintext, nonce, key2)]);
7887
8761
  }
7888
- function decryptNoteOutput(key, encryptedOutput, mint, index) {
8762
+ function decryptNoteOutput(key2, encryptedOutput, mint, index, onchainAmount = null) {
7889
8763
  if (encryptedOutput.length !== SECRETBOX_NONCE_BYTES + nacl__default.default.secretbox.overheadLength + ENCRYPTED_OUTPUT_PLAINTEXT_BYTES) {
7890
8764
  return null;
7891
8765
  }
7892
8766
  const opened = nacl__default.default.secretbox.open(
7893
8767
  encryptedOutput.subarray(SECRETBOX_NONCE_BYTES),
7894
8768
  encryptedOutput.subarray(0, SECRETBOX_NONCE_BYTES),
7895
- key
8769
+ key2
7896
8770
  );
7897
- if (!opened || opened[0] !== ENCRYPTED_OUTPUT_VERSION) {
8771
+ if (!opened) {
8772
+ return null;
8773
+ }
8774
+ let amount;
8775
+ if (opened[0] === ENCRYPTED_OUTPUT_VERSION) {
8776
+ amount = new DataView(opened.buffer, opened.byteOffset + 1, 8).getBigUint64(0, true);
8777
+ } else if (opened[0] === ENCRYPTED_SWAP_OUTPUT_VERSION && onchainAmount !== null) {
8778
+ amount = onchainAmount;
8779
+ } else {
7898
8780
  return null;
7899
8781
  }
7900
- const amount = new DataView(opened.buffer, opened.byteOffset + 1, 8).getBigUint64(0, true);
7901
8782
  return new Utxo({
7902
8783
  amount,
7903
8784
  keypair: VeilixKeypair.fromPrivateKey(bytesToBigint(opened.subarray(9, 41))),
@@ -16378,6 +17259,7 @@ async function proveTransaction({
16378
17259
  inputs = [],
16379
17260
  outputs = [],
16380
17261
  ext,
17262
+ extDataHashOverride,
16381
17263
  circuit
16382
17264
  }) {
16383
17265
  for (const utxo of [...inputs, ...outputs]) {
@@ -16427,7 +17309,7 @@ async function proveTransaction({
16427
17309
  const input = {
16428
17310
  root: proofRoot.toString(),
16429
17311
  publicAmount: publicAmount.toString(),
16430
- extDataHash: (await extDataHash(ext)).toString(),
17312
+ extDataHash: (extDataHashOverride ?? await extDataHash(ext)).toString(),
16431
17313
  mint: mintToField(ext.mint).toString(),
16432
17314
  inputNullifier: inputNullifiers.map(String),
16433
17315
  outputCommitment: outputCommitments.map(String),
@@ -16568,8 +17450,8 @@ function generateDepositParams(amount, mint = null) {
16568
17450
  if (value <= 0n) {
16569
17451
  throw new Error("veilix-sdk: deposit amount must be positive");
16570
17452
  }
16571
- const mintKey = mint && mint !== WRAPPED_SOL_MINT ? new web3_js.PublicKey(mint) : null;
16572
- const note = encodeNote(new Utxo({ amount: value, mint: mintKey }));
17453
+ const mintKey2 = mint && mint !== WRAPPED_SOL_MINT ? new web3_js.PublicKey(mint) : null;
17454
+ const note = encodeNote(new Utxo({ amount: value, mint: mintKey2 }));
16573
17455
  return { note, params: parseSecretNote(note) };
16574
17456
  }
16575
17457
  function to32ByteBuffer(value) {
@@ -16603,8 +17485,8 @@ function toPublicKey(value) {
16603
17485
  }
16604
17486
  function normalizeTreeMint(mint) {
16605
17487
  if (!mint) return null;
16606
- const key = toPublicKey(mint);
16607
- return key.equals(splToken.NATIVE_MINT) || key.equals(web3_js.PublicKey.default) ? null : key;
17488
+ const key2 = toPublicKey(mint);
17489
+ return key2.equals(splToken.NATIVE_MINT) || key2.equals(web3_js.PublicKey.default) ? null : key2;
16608
17490
  }
16609
17491
  function getTreePDA(mint) {
16610
17492
  const treeMint = normalizeTreeMint(mint);
@@ -16855,8 +17737,8 @@ async function resolveEncryptKey() {
16855
17737
  }
16856
17738
  async function buildBackupNotesInstruction(sender, notes) {
16857
17739
  const { program } = getConfig();
16858
- const key = await resolveEncryptKey();
16859
- return program.methods.backupNotes(notes.map((note) => encryptData(key, note))).accountsPartial({ user: sender }).instruction();
17740
+ const key2 = await resolveEncryptKey();
17741
+ return program.methods.backupNotes(notes.map((note) => encryptData(key2, note))).accountsPartial({ user: sender }).instruction();
16860
17742
  }
16861
17743
  async function isExtendBackupPdaNeeded(walletPubkey, newNotesLength) {
16862
17744
  const account = await fetchNotesAccount(walletPubkey);
@@ -16961,16 +17843,16 @@ async function getEncryptionKey(wallet) {
16961
17843
  }
16962
17844
  return nacl__default.default.hash(signature).slice(0, 32);
16963
17845
  }
16964
- function encryptData(key, plaintext) {
17846
+ function encryptData(key2, plaintext) {
16965
17847
  const nonce = nacl__default.default.randomBytes(24);
16966
- const box = nacl__default.default.secretbox(new TextEncoder().encode(plaintext), nonce, key);
17848
+ const box = nacl__default.default.secretbox(new TextEncoder().encode(plaintext), nonce, key2);
16967
17849
  const combined = new Uint8Array(nonce.length + box.length);
16968
17850
  combined.set(nonce);
16969
17851
  combined.set(box, nonce.length);
16970
17852
  return buffer.Buffer.from(combined);
16971
17853
  }
16972
- function decryptData(key, combined) {
16973
- const decrypted = nacl__default.default.secretbox.open(combined.slice(24), combined.slice(0, 24), key);
17854
+ function decryptData(key2, combined) {
17855
+ const decrypted = nacl__default.default.secretbox.open(combined.slice(24), combined.slice(0, 24), key2);
16974
17856
  if (!decrypted) throw new Error("Decryption failed");
16975
17857
  return new TextDecoder().decode(decrypted);
16976
17858
  }
@@ -17008,8 +17890,8 @@ var COMMITMENTS_PAGE_LIMIT = 8e3;
17008
17890
  var VALIDATE_NULLIFIERS_BATCH = 64;
17009
17891
  async function indexerGet(path, params) {
17010
17892
  const query = new URLSearchParams();
17011
- for (const [key, value] of Object.entries(params)) {
17012
- if (value !== void 0 && value !== "") query.set(key, value);
17893
+ for (const [key2, value] of Object.entries(params)) {
17894
+ if (value !== void 0 && value !== "") query.set(key2, value);
17013
17895
  }
17014
17896
  const qs = query.toString();
17015
17897
  return httpFetch(`${getIndexerUrl()}${path}${qs ? `?${qs}` : ""}`, {
@@ -17224,7 +18106,7 @@ async function scanOwnedNotes({
17224
18106
  mints,
17225
18107
  includeSpent = false
17226
18108
  } = {}) {
17227
- const key = requireEncryptKey();
18109
+ const key2 = requireEncryptKey();
17228
18110
  const explicit = mints !== void 0;
17229
18111
  const tokenMints = getTokenMintsForNetwork(getConfig().network);
17230
18112
  const targets = mints ?? [null, tokenMints.Veilix, tokenMints.Bitcoin, tokenMints.Ethereum, tokenMints.USDC].filter(
@@ -17242,7 +18124,13 @@ async function scanOwnedNotes({
17242
18124
  }
17243
18125
  for (const leaf of leaves) {
17244
18126
  if (!leaf.encryptedOutput || leaf.encryptedOutput.length <= 2) continue;
17245
- const utxo = decryptNoteOutput(key, hexToBytes(leaf.encryptedOutput), treeMint, leaf.index);
18127
+ const utxo = decryptNoteOutput(
18128
+ key2,
18129
+ hexToBytes(leaf.encryptedOutput),
18130
+ treeMint,
18131
+ leaf.index,
18132
+ leaf.amountRaw ? BigInt(leaf.amountRaw) : null
18133
+ );
17246
18134
  if (!utxo || utxo.amount === 0n) continue;
17247
18135
  if (toHex32(utxo.commitment()) !== toHex32(BigInt(leaf.commitment))) continue;
17248
18136
  found.push({ utxo, note: encodeNote(utxo), signature: null });
@@ -17522,6 +18410,364 @@ async function getQuote(params) {
17522
18410
  }
17523
18411
  return data;
17524
18412
  }
18413
+ var SWAP_DOMAIN = new TextEncoder().encode("veilix:swap:v1");
18414
+ async function swapExtDataHash(ext) {
18415
+ const hash = await sha256(
18416
+ concatBytes([
18417
+ SWAP_DOMAIN,
18418
+ (ext.mintIn ?? web3_js.PublicKey.default).toBytes(),
18419
+ (ext.mintOut ?? web3_js.PublicKey.default).toBytes(),
18420
+ ext.relayer.toBytes(),
18421
+ u64le(ext.amountIn),
18422
+ u64le(ext.fee),
18423
+ u64le(ext.minAmountOut),
18424
+ bigintToBytes32(ext.outPubkey),
18425
+ bigintToBytes32(ext.outBlinding),
18426
+ u32le(ext.encryptedOutput1.length),
18427
+ ext.encryptedOutput1,
18428
+ u32le(ext.encryptedOutput2.length),
18429
+ ext.encryptedOutput2,
18430
+ u32le(ext.encryptedNote.length),
18431
+ ext.encryptedNote
18432
+ ])
18433
+ );
18434
+ hash[0] = 0;
18435
+ return bytesToBigint(hash);
18436
+ }
18437
+ var CPMM_PROGRAM_IDS = {
18438
+ devnet: "DRaycpLY18LhpbydsBWbVJtxpNv9oXPgjRSfpF2bWpYb",
18439
+ mainnet: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"
18440
+ };
18441
+ var FEE_RATE_DENOMINATOR = 1000000n;
18442
+ var SWAP_DISABLED_BIT = 2;
18443
+ var key = (data, offset) => new web3_js.PublicKey(data.subarray(offset, offset + 32));
18444
+ var u64 = (data, offset) => new DataView(data.buffer, data.byteOffset + offset, 8).getBigUint64(0, true);
18445
+ var ceilDiv = (a, b) => (a + b - 1n) / b;
18446
+ var feeOf = (amount, rate) => ceilDiv(amount * rate, FEE_RATE_DENOMINATOR);
18447
+ async function quoteCpmm(connection, network, poolAddress, treeMintIn, treeMintOut, amountIn) {
18448
+ const programId = new web3_js.PublicKey(CPMM_PROGRAM_IDS[network]);
18449
+ const poolInfo = await connection.getAccountInfo(poolAddress, "confirmed");
18450
+ if (!poolInfo || !poolInfo.owner.equals(programId) || poolInfo.data.length < 381) {
18451
+ throw new Error("veilix-sdk: swap pool is not a Raydium CPMM pool");
18452
+ }
18453
+ const data = poolInfo.data;
18454
+ const pool = {
18455
+ ammConfig: key(data, 8),
18456
+ vault0: key(data, 72),
18457
+ vault1: key(data, 104),
18458
+ mint0: key(data, 168),
18459
+ mint1: key(data, 200),
18460
+ status: data[329],
18461
+ protocolFees: [u64(data, 341), u64(data, 349)],
18462
+ fundFees: [u64(data, 357), u64(data, 365)],
18463
+ creatorFeeOn: data.length >= 413 ? data[389] : 0,
18464
+ enableCreatorFee: data.length >= 413 ? data[390] === 1 : false,
18465
+ creatorFees: data.length >= 413 ? [u64(data, 397), u64(data, 405)] : [0n, 0n]
18466
+ };
18467
+ if (pool.status >> SWAP_DISABLED_BIT & 1) {
18468
+ throw new Error("veilix-sdk: swaps are disabled on this pool");
18469
+ }
18470
+ const mintIn = treeMintIn ?? splToken.NATIVE_MINT;
18471
+ const mintOut = treeMintOut ?? splToken.NATIVE_MINT;
18472
+ let zeroForOne;
18473
+ if (pool.mint0.equals(mintIn) && pool.mint1.equals(mintOut)) zeroForOne = true;
18474
+ else if (pool.mint1.equals(mintIn) && pool.mint0.equals(mintOut)) zeroForOne = false;
18475
+ else throw new Error("veilix-sdk: swap pool does not trade this pair");
18476
+ const [i, o] = zeroForOne ? [0, 1] : [1, 0];
18477
+ const [configInfo, vaultIn, vaultOut] = await connection.getMultipleAccountsInfo(
18478
+ [pool.ammConfig, zeroForOne ? pool.vault0 : pool.vault1, zeroForOne ? pool.vault1 : pool.vault0],
18479
+ "confirmed"
18480
+ );
18481
+ if (!configInfo || !vaultIn || !vaultOut) {
18482
+ throw new Error("veilix-sdk: swap pool accounts are missing");
18483
+ }
18484
+ const tradeFeeRate = u64(configInfo.data, 12);
18485
+ const creatorFeeRate = pool.enableCreatorFee && configInfo.data.length >= 116 ? u64(configInfo.data, 108) : 0n;
18486
+ const reserveIn = u64(vaultIn.data, 64) - pool.protocolFees[i] - pool.fundFees[i] - pool.creatorFees[i];
18487
+ const reserveOut = u64(vaultOut.data, 64) - pool.protocolFees[o] - pool.fundFees[o] - pool.creatorFees[o];
18488
+ if (reserveIn <= 0n || reserveOut <= 0n) {
18489
+ throw new Error("veilix-sdk: swap pool has no liquidity");
18490
+ }
18491
+ const creatorOnInput = pool.creatorFeeOn === 0 || pool.creatorFeeOn === 1 && zeroForOne || pool.creatorFeeOn === 2 && !zeroForOne;
18492
+ let inLessFees = amountIn - feeOf(amountIn, tradeFeeRate);
18493
+ if (creatorOnInput) inLessFees -= feeOf(amountIn, creatorFeeRate);
18494
+ let amountOut = inLessFees * reserveOut / (reserveIn + inLessFees);
18495
+ if (!creatorOnInput) amountOut -= feeOf(amountOut, creatorFeeRate);
18496
+ if (amountOut <= 0n) {
18497
+ throw new Error("veilix-sdk: swap amount is too small for this pool");
18498
+ }
18499
+ const spotOut = Number(inLessFees) * (Number(reserveOut) / Number(reserveIn));
18500
+ const priceImpact = spotOut > 0 ? Math.max(0, 1 - Number(amountOut) / spotOut) : 1;
18501
+ return { amountOut, priceImpact };
18502
+ }
18503
+
18504
+ // src/swap/execute.ts
18505
+ var SWAP_MAX_WAIT_MS = 18e4;
18506
+ var DEFAULT_SLIPPAGE_BPS = 100;
18507
+ var MAX_SLIPPAGE_BPS = 5e3;
18508
+ var MAX_PRICE_IMPACT = 0.1;
18509
+ var hex = (bytes) => `0x${bytesToHex(bytes)}`;
18510
+ var mintKey = (mint) => mint?.toBase58() ?? null;
18511
+ async function fetchRelayerQuote(relayerUrl, mintIn, mintOut, amountIn) {
18512
+ const params = new URLSearchParams({ amountIn: amountIn.toString() });
18513
+ if (mintIn) params.set("mintIn", mintIn.toBase58());
18514
+ if (mintOut) params.set("mintOut", mintOut.toBase58());
18515
+ const base = relayerUrl.replace(/\/$/, "");
18516
+ const res = await httpFetch(`${base}/v1/swapQuote?${params}`, {
18517
+ headers: { Accept: "application/json" }
18518
+ });
18519
+ const body = await res.json().catch(() => ({}));
18520
+ if (!res.ok) {
18521
+ throw new Error(body.error || `Swap quote failed (${res.status})`);
18522
+ }
18523
+ return { ...body, relayerUrl: base };
18524
+ }
18525
+ function swapCandidates(relayers, relayerUrl) {
18526
+ if (relayerUrl) {
18527
+ const wanted = relayerUrl.replace(/\/$/, "");
18528
+ const match = relayers.find((r) => r.url.replace(/\/$/, "") === wanted);
18529
+ if (!match) throw new Error(`veilix-sdk: relayer ${relayerUrl} is not available`);
18530
+ return [match];
18531
+ }
18532
+ if (!relayers.length) throw new Error("veilix-sdk: no relayer available");
18533
+ const first = getRandomRelayer(relayers);
18534
+ return [first, ...relayers.filter((r) => r !== first)];
18535
+ }
18536
+ async function getSwapQuote(params) {
18537
+ const { relayers } = getConfig();
18538
+ const mintIn = normalizeTreeMint(params.mintIn);
18539
+ const mintOut = normalizeTreeMint(params.mintOut);
18540
+ if (mintKey(mintIn) === mintKey(mintOut)) {
18541
+ throw new Error("veilix-sdk: swap needs two different assets");
18542
+ }
18543
+ const amountIn = BigInt(params.amountIn);
18544
+ if (amountIn <= 0n) throw new Error("veilix-sdk: swap amount must be positive");
18545
+ const { connection, network } = getConfig();
18546
+ const platformWallets = await fetchPlatformFeeWallets();
18547
+ let lastError = null;
18548
+ for (const relayer of swapCandidates(relayers, params.relayerUrl)) {
18549
+ try {
18550
+ const quote = await fetchRelayerQuote(relayer.url, mintIn, mintOut, amountIn);
18551
+ if (quote.relayer !== relayer.value) {
18552
+ throw new Error("Relayer quoted for a different reward account");
18553
+ }
18554
+ const { fee } = computeWithdrawFee(amountIn, relayer.fee, platformWallets);
18555
+ if (fee >= amountIn) throw new Error("Amount is too small to cover the fees");
18556
+ if (BigInt(quote.fee) !== fee) throw new Error("Relayer quoted a different fee");
18557
+ if (quote.dexProgram !== CPMM_PROGRAM_IDS[network]) {
18558
+ throw new Error("Relayer routes through an unsupported DEX");
18559
+ }
18560
+ const own = await quoteCpmm(
18561
+ connection,
18562
+ network,
18563
+ new web3_js.PublicKey(quote.pool),
18564
+ mintIn,
18565
+ mintOut,
18566
+ amountIn - fee
18567
+ );
18568
+ if (own.priceImpact > MAX_PRICE_IMPACT) {
18569
+ throw new Error(
18570
+ `Price impact ${(own.priceImpact * 100).toFixed(1)}% is too high for this pool; swap less`
18571
+ );
18572
+ }
18573
+ return {
18574
+ quote: {
18575
+ ...quote,
18576
+ swapIn: (amountIn - fee).toString(),
18577
+ amountOut: own.amountOut.toString(),
18578
+ priceImpact: own.priceImpact
18579
+ },
18580
+ relayer
18581
+ };
18582
+ } catch (error) {
18583
+ lastError = error;
18584
+ }
18585
+ }
18586
+ const reason = lastError instanceof Error ? lastError.message : "no relayer routes this pair";
18587
+ throw new Error(`veilix-sdk: no swap route for this pair (${reason})`);
18588
+ }
18589
+ async function buildSwapPayload(params, options = {}) {
18590
+ const { encryptKey } = getConfig();
18591
+ const utxo = decodeNote(params.note);
18592
+ const mintIn = utxo.mint;
18593
+ const mintOut = normalizeTreeMint(params.mintOut ?? null);
18594
+ const slippageBps = params.slippageBps ?? DEFAULT_SLIPPAGE_BPS;
18595
+ if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > MAX_SLIPPAGE_BPS) {
18596
+ throw new Error(`veilix-sdk: slippageBps must be an integer between 0 and ${MAX_SLIPPAGE_BPS}`);
18597
+ }
18598
+ const { index } = await locateNote(utxo);
18599
+ if (index === null) {
18600
+ throw new Error("Note is not in the Veilix pool yet (deposit not confirmed or not indexed)");
18601
+ }
18602
+ utxo.index = index;
18603
+ if ((await validateNullifier(toHex32(utxo.nullifier()))).exists) {
18604
+ throw new Error("This note has already been spent");
18605
+ }
18606
+ const amountIn = params.amount === void 0 ? utxo.amount : BigInt(params.amount);
18607
+ if (amountIn <= 0n || amountIn > utxo.amount) {
18608
+ throw new Error(`Swap amount must be between 1 and ${utxo.amount}`);
18609
+ }
18610
+ const { quote, relayer } = await getSwapQuote({
18611
+ mintIn,
18612
+ mintOut,
18613
+ amountIn,
18614
+ relayerUrl: params.relayerUrl
18615
+ });
18616
+ const fee = BigInt(quote.fee);
18617
+ const minAmountOut = BigInt(quote.amountOut) * BigInt(1e4 - slippageBps) / 10000n;
18618
+ if (minAmountOut <= 0n) {
18619
+ throw new Error("Swap amount is too small for this pool");
18620
+ }
18621
+ let tree = options.tree;
18622
+ if (!tree || tree.elements.length <= index) {
18623
+ tree = await fetchAssetTree(mintKey(mintIn));
18624
+ }
18625
+ if (tree.elements.length <= index) {
18626
+ throw new Error("The indexer has not synced this note yet, retry shortly");
18627
+ }
18628
+ const change = utxo.amount - amountIn;
18629
+ const changeUtxo = change > 0n ? new Utxo({ amount: change, mint: mintIn }) : null;
18630
+ const encryptedOutput1 = changeUtxo && encryptKey ? encryptNoteOutput(encryptKey, changeUtxo) : new Uint8Array();
18631
+ const encryptedOutput2 = new Uint8Array();
18632
+ const outKeypair = VeilixKeypair.random();
18633
+ const outBlinding = randomFieldElement();
18634
+ const encryptedNote = encryptKey ? encryptSwapNoteOutput(encryptKey, outKeypair, outBlinding) : new Uint8Array();
18635
+ const relayerKey = new web3_js.PublicKey(relayer.value);
18636
+ const hash = await swapExtDataHash({
18637
+ mintIn,
18638
+ mintOut,
18639
+ relayer: relayerKey,
18640
+ amountIn,
18641
+ fee,
18642
+ minAmountOut,
18643
+ outPubkey: outKeypair.pubKey,
18644
+ outBlinding,
18645
+ encryptedOutput1,
18646
+ encryptedOutput2,
18647
+ encryptedNote
18648
+ });
18649
+ const proved = await withCircuitArtifacts(
18650
+ options.circuitArtifacts,
18651
+ (artifacts) => proveTransaction({
18652
+ tree,
18653
+ inputs: [utxo],
18654
+ outputs: changeUtxo ? [changeUtxo] : [],
18655
+ ext: {
18656
+ mint: mintIn,
18657
+ recipient: web3_js.PublicKey.default,
18658
+ relayer: relayerKey,
18659
+ extAmount: -amountIn,
18660
+ fee,
18661
+ encryptedOutput1,
18662
+ encryptedOutput2
18663
+ },
18664
+ extDataHashOverride: hash,
18665
+ circuit: artifacts
18666
+ })
18667
+ );
18668
+ const { proof } = proved;
18669
+ const payload = {
18670
+ proof: hex(proof.proof),
18671
+ root: hex(proof.root),
18672
+ inputNullifiers: [hex(proof.inputNullifiers[0]), hex(proof.inputNullifiers[1])],
18673
+ outputCommitments: [hex(proof.outputCommitments[0]), hex(proof.outputCommitments[1])],
18674
+ ...mintIn ? { mintIn: mintIn.toBase58() } : {},
18675
+ ...mintOut ? { mintOut: mintOut.toBase58() } : {},
18676
+ amountIn: amountIn.toString(),
18677
+ fee: fee.toString(),
18678
+ minAmountOut: minAmountOut.toString(),
18679
+ outPubkey: hex(bigintToBytes32(outKeypair.pubKey)),
18680
+ outBlinding: hex(bigintToBytes32(outBlinding)),
18681
+ relayer: relayerKey.toBase58(),
18682
+ encryptedOutput1: hex(encryptedOutput1),
18683
+ encryptedOutput2: hex(encryptedOutput2),
18684
+ encryptedNote: hex(encryptedNote)
18685
+ };
18686
+ return {
18687
+ payload,
18688
+ relayerUrl: quote.relayerUrl,
18689
+ quote,
18690
+ amountIn,
18691
+ fee,
18692
+ minAmountOut,
18693
+ changeNote: changeUtxo ? encodeNote(changeUtxo) : null,
18694
+ output: {
18695
+ mint: mintKey(mintOut),
18696
+ privKey: outKeypair.privKey.toString(),
18697
+ blinding: outBlinding.toString()
18698
+ },
18699
+ nullifiers: [...payload.inputNullifiers]
18700
+ };
18701
+ }
18702
+ async function pollSwapJob(relayerUrl, jobId, maxWaitMs) {
18703
+ const start = Date.now();
18704
+ while (Date.now() - start < maxWaitMs) {
18705
+ const res = await httpFetch(`${relayerUrl}/v1/jobs/${encodeURIComponent(jobId)}`, {
18706
+ headers: { Accept: "application/json" }
18707
+ });
18708
+ const job = await res.json().catch(() => ({}));
18709
+ if (!res.ok) throw new Error(job.error || "Failed to poll relayer job");
18710
+ if (job.status === "CONFIRMED" || job.status === "FAILED") return job;
18711
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
18712
+ }
18713
+ throw new Error("Swap timed out");
18714
+ }
18715
+ function swapOutputNote(output, result) {
18716
+ const utxo = new Utxo({
18717
+ amount: BigInt(result.amountOut),
18718
+ keypair: VeilixKeypair.fromPrivateKey(output.privKey),
18719
+ blinding: BigInt(output.blinding),
18720
+ mint: output.mint ? new web3_js.PublicKey(output.mint) : null,
18721
+ index: result.outputIndex
18722
+ });
18723
+ if (toHex32(utxo.commitment()) !== toHex32(BigInt(result.outputCommitment))) {
18724
+ throw new Error("veilix-sdk: swapped note does not match the on-chain commitment");
18725
+ }
18726
+ return encodeNote(utxo);
18727
+ }
18728
+ async function submitSwapPayload(bundle) {
18729
+ const res = await httpFetch(`${bundle.relayerUrl}/v1/veilixSwap`, {
18730
+ method: "POST",
18731
+ headers: { "Content-Type": "application/json" },
18732
+ body: JSON.stringify(bundle.payload)
18733
+ });
18734
+ const body = await res.json().catch(() => ({}));
18735
+ if (!res.ok || !body.id) {
18736
+ throw new Error(body.error || "Swap submission failed");
18737
+ }
18738
+ const job = await pollSwapJob(bundle.relayerUrl, body.id, SWAP_MAX_WAIT_MS);
18739
+ const base = {
18740
+ changeNote: bundle.changeNote,
18741
+ amountIn: bundle.amountIn.toString(),
18742
+ fee: bundle.fee.toString(),
18743
+ minAmountOut: bundle.minAmountOut.toString()
18744
+ };
18745
+ if (job.status === "FAILED") {
18746
+ return {
18747
+ ...base,
18748
+ txHash: job.txHash ?? "",
18749
+ status: "failed",
18750
+ error: job.failedReason || "Swap failed",
18751
+ // A failed swap spends nothing: the original note is still valid.
18752
+ outputNote: null,
18753
+ changeNote: null,
18754
+ amountOut: null
18755
+ };
18756
+ }
18757
+ if (!job.txHash || !job.swapResult) {
18758
+ throw new Error("Swap confirmed but the relayer did not report the swapped note");
18759
+ }
18760
+ return {
18761
+ ...base,
18762
+ txHash: job.txHash,
18763
+ status: "success",
18764
+ outputNote: swapOutputNote(bundle.output, job.swapResult),
18765
+ amountOut: job.swapResult.amountOut
18766
+ };
18767
+ }
18768
+ async function executeSwap(params) {
18769
+ return submitSwapPayload(await buildSwapPayload(params));
18770
+ }
17525
18771
 
17526
18772
  // src/withdraw/assets.ts
17527
18773
  var TOKEN_UNITS = {
@@ -17962,6 +19208,26 @@ var VeilixSDK = class _VeilixSDK {
17962
19208
  submitWithdrawPayload(bundle) {
17963
19209
  return this.runAsync(() => submitWithdrawPayload(bundle));
17964
19210
  }
19211
+ // ── Private swap ─────────────────────────────────────────────────────
19212
+ /** Fee and expected output of swapping `amountIn` of `mintIn` into `mintOut`. */
19213
+ getSwapQuote(params) {
19214
+ return this.runAsync(() => getSwapQuote(params));
19215
+ }
19216
+ /**
19217
+ * Swap a note of asset A into a new shielded note of asset B (`mintOut`, `null` for
19218
+ * SOL) through a relayer and an allowlisted DEX. Funds never leave the pool
19219
+ * unshielded. Returns the asset-B note and any asset-A change note.
19220
+ */
19221
+ swap(params) {
19222
+ return this.runAsync(() => executeSwap(params));
19223
+ }
19224
+ /** Prove a swap without submitting it (see {@link submitSwapPayload}). */
19225
+ buildSwapPayload(params, options) {
19226
+ return this.runAsync(() => buildSwapPayload(params, options));
19227
+ }
19228
+ submitSwapPayload(bundle) {
19229
+ return this.runAsync(() => submitSwapPayload(bundle));
19230
+ }
17965
19231
  /**
17966
19232
  * Private transfer: deposit one note per item, then withdraw each note in full
17967
19233
  * to its recipient through the indexer submission queue.
@@ -18073,15 +19339,15 @@ var VeilixSDK = class _VeilixSDK {
18073
19339
  * Accepts a frontend wallet adapter (`signMessage`) or a backend {@link Keypair}.
18074
19340
  */
18075
19341
  async getEncryptionKey(wallet) {
18076
- const key = await getEncryptionKey(wallet);
18077
- this.config.encryptKey = key;
18078
- return key;
19342
+ const key2 = await getEncryptionKey(wallet);
19343
+ this.config.encryptKey = key2;
19344
+ return key2;
18079
19345
  }
18080
- encryptData(key, plaintext) {
18081
- return encryptData(key, plaintext);
19346
+ encryptData(key2, plaintext) {
19347
+ return encryptData(key2, plaintext);
18082
19348
  }
18083
- decryptData(key, combined) {
18084
- return decryptData(key, combined);
19349
+ decryptData(key2, combined) {
19350
+ return decryptData(key2, combined);
18085
19351
  }
18086
19352
  // ── Utilities ────────────────────────────────────────────────────────
18087
19353
  parseAmountToBaseUnits(amount, decimals) {
@@ -18119,9 +19385,11 @@ var VeilixSDK = class _VeilixSDK {
18119
19385
  * @license MIT
18120
19386
  */
18121
19387
 
19388
+ exports.CPMM_PROGRAM_IDS = CPMM_PROGRAM_IDS;
18122
19389
  exports.FIELD_SIZE = FIELD_SIZE;
18123
19390
  exports.MALICIOUS_RECIPIENT_ERROR = MALICIOUS_RECIPIENT_ERROR;
18124
19391
  exports.NOTE_PREFIX = NOTE_PREFIX;
19392
+ exports.SWAP_DOMAIN = SWAP_DOMAIN;
18125
19393
  exports.TREE_LEVELS = TREE_LEVELS;
18126
19394
  exports.Utxo = Utxo;
18127
19395
  exports.VeilixKeypair = VeilixKeypair;
@@ -18137,6 +19405,7 @@ exports.default = VeilixSDK;
18137
19405
  exports.encodeNote = encodeNote;
18138
19406
  exports.encryptData = encryptData;
18139
19407
  exports.encryptNoteOutput = encryptNoteOutput;
19408
+ exports.encryptSwapNoteOutput = encryptSwapNoteOutput;
18140
19409
  exports.extDataHash = extDataHash;
18141
19410
  exports.formatBaseUnits = formatBaseUnits;
18142
19411
  exports.formatNoteForDisplay = formatNoteForDisplay;
@@ -18147,7 +19416,10 @@ exports.parseAmountToBaseUnits = parseAmountToBaseUnits;
18147
19416
  exports.parseSecretNote = parseSecretNote;
18148
19417
  exports.prepareCircuitArtifacts = prepareCircuitArtifacts;
18149
19418
  exports.proveTransaction = proveTransaction;
19419
+ exports.quoteCpmm = quoteCpmm;
18150
19420
  exports.resolveCircuitPathsFromBase = resolveCircuitPathsFromBase;
18151
19421
  exports.resolveNpmCdnCircuitBase = resolveNpmCdnCircuitBase;
19422
+ exports.swapExtDataHash = swapExtDataHash;
19423
+ exports.swapOutputNote = swapOutputNote;
18152
19424
  //# sourceMappingURL=index.cjs.map
18153
19425
  //# sourceMappingURL=index.cjs.map