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.js CHANGED
@@ -36,7 +36,7 @@ function formatBaseUnits(value, decimals) {
36
36
 
37
37
  // src/idl/veilix-devnet.json
38
38
  var veilix_devnet_default = {
39
- address: "HbatG5gpfs2g3N4gc2Qkfmmeu4zaBEVxzrDdYtWNLyyA",
39
+ address: "Vxi1QK84Akv4yGngjvkWNmEsK7XpsSrpDaPBoiyXGPG",
40
40
  metadata: {
41
41
  name: "veilix",
42
42
  version: "0.2.0",
@@ -637,6 +637,38 @@ var veilix_devnet_default = {
637
637
  {
638
638
  name: "system_program",
639
639
  address: "11111111111111111111111111111111"
640
+ },
641
+ {
642
+ name: "event_authority",
643
+ pda: {
644
+ seeds: [
645
+ {
646
+ kind: "const",
647
+ value: [
648
+ 95,
649
+ 95,
650
+ 101,
651
+ 118,
652
+ 101,
653
+ 110,
654
+ 116,
655
+ 95,
656
+ 97,
657
+ 117,
658
+ 116,
659
+ 104,
660
+ 111,
661
+ 114,
662
+ 105,
663
+ 116,
664
+ 121
665
+ ]
666
+ }
667
+ ]
668
+ }
669
+ },
670
+ {
671
+ name: "program"
640
672
  }
641
673
  ],
642
674
  args: [
@@ -699,6 +731,91 @@ var veilix_devnet_default = {
699
731
  ]
700
732
  }
701
733
  },
734
+ {
735
+ name: "program_data",
736
+ docs: [
737
+ "This program's ProgramData. Only its upgrade authority may initialize the network,",
738
+ "so nobody can claim the config authority between deploy and setup."
739
+ ],
740
+ pda: {
741
+ seeds: [
742
+ {
743
+ kind: "const",
744
+ value: [
745
+ 7,
746
+ 107,
747
+ 64,
748
+ 50,
749
+ 251,
750
+ 172,
751
+ 47,
752
+ 215,
753
+ 89,
754
+ 179,
755
+ 92,
756
+ 125,
757
+ 67,
758
+ 162,
759
+ 96,
760
+ 45,
761
+ 239,
762
+ 91,
763
+ 223,
764
+ 168,
765
+ 251,
766
+ 138,
767
+ 165,
768
+ 133,
769
+ 253,
770
+ 74,
771
+ 152,
772
+ 142,
773
+ 6,
774
+ 85,
775
+ 93,
776
+ 119
777
+ ]
778
+ }
779
+ ],
780
+ program: {
781
+ kind: "const",
782
+ value: [
783
+ 2,
784
+ 168,
785
+ 246,
786
+ 145,
787
+ 78,
788
+ 136,
789
+ 161,
790
+ 176,
791
+ 226,
792
+ 16,
793
+ 21,
794
+ 62,
795
+ 247,
796
+ 99,
797
+ 174,
798
+ 43,
799
+ 0,
800
+ 194,
801
+ 185,
802
+ 61,
803
+ 22,
804
+ 193,
805
+ 36,
806
+ 210,
807
+ 192,
808
+ 83,
809
+ 122,
810
+ 16,
811
+ 4,
812
+ 128,
813
+ 0,
814
+ 0
815
+ ]
816
+ }
817
+ }
818
+ },
702
819
  {
703
820
  name: "system_program",
704
821
  address: "11111111111111111111111111111111"
@@ -1027,6 +1144,31 @@ var veilix_devnet_default = {
1027
1144
  ]
1028
1145
  }
1029
1146
  },
1147
+ {
1148
+ name: "treasury",
1149
+ docs: [
1150
+ "Holds the SOL pool. Funded with its rent-exempt reserve here so that no withdrawal",
1151
+ "can fail for leaving it below that reserve."
1152
+ ],
1153
+ writable: true,
1154
+ pda: {
1155
+ seeds: [
1156
+ {
1157
+ kind: "const",
1158
+ value: [
1159
+ 116,
1160
+ 114,
1161
+ 101,
1162
+ 97,
1163
+ 115,
1164
+ 117,
1165
+ 114,
1166
+ 121
1167
+ ]
1168
+ }
1169
+ ]
1170
+ }
1171
+ },
1030
1172
  {
1031
1173
  name: "system_program",
1032
1174
  address: "11111111111111111111111111111111"
@@ -1435,25 +1577,355 @@ var veilix_devnet_default = {
1435
1577
  value: [
1436
1578
  114,
1437
1579
  101,
1438
- 108,
1439
- 97,
1440
- 121,
1580
+ 108,
1581
+ 97,
1582
+ 121,
1583
+ 101,
1584
+ 114
1585
+ ]
1586
+ },
1587
+ {
1588
+ kind: "account",
1589
+ path: "user"
1590
+ }
1591
+ ]
1592
+ }
1593
+ }
1594
+ ],
1595
+ args: [
1596
+ {
1597
+ name: "worker",
1598
+ type: "pubkey"
1599
+ }
1600
+ ]
1601
+ },
1602
+ {
1603
+ name: "swap",
1604
+ docs: [
1605
+ "Private swap. Remaining accounts: the protocol fee wallets for the input asset (SOL",
1606
+ "accounts or their token accounts, in config order), then the DEX instruction's accounts."
1607
+ ],
1608
+ discriminator: [
1609
+ 248,
1610
+ 198,
1611
+ 158,
1612
+ 145,
1613
+ 225,
1614
+ 117,
1615
+ 135,
1616
+ 200
1617
+ ],
1618
+ accounts: [
1619
+ {
1620
+ name: "relayer",
1621
+ writable: true,
1622
+ signer: true
1623
+ },
1624
+ {
1625
+ name: "relayer_account",
1626
+ writable: true,
1627
+ pda: {
1628
+ seeds: [
1629
+ {
1630
+ kind: "const",
1631
+ value: [
1632
+ 114,
1633
+ 101,
1634
+ 108,
1635
+ 97,
1636
+ 121,
1637
+ 101,
1638
+ 114
1639
+ ]
1640
+ },
1641
+ {
1642
+ kind: "account",
1643
+ path: "relayer_account.owner",
1644
+ account: "RelayerAccount"
1645
+ }
1646
+ ]
1647
+ }
1648
+ },
1649
+ {
1650
+ name: "network_state",
1651
+ pda: {
1652
+ seeds: [
1653
+ {
1654
+ kind: "const",
1655
+ value: [
1656
+ 99,
1657
+ 111,
1658
+ 110,
1659
+ 102,
1660
+ 105,
1661
+ 103
1662
+ ]
1663
+ }
1664
+ ]
1665
+ }
1666
+ },
1667
+ {
1668
+ name: "swap_config",
1669
+ pda: {
1670
+ seeds: [
1671
+ {
1672
+ kind: "const",
1673
+ value: [
1674
+ 115,
1675
+ 119,
1676
+ 97,
1677
+ 112,
1678
+ 95,
1679
+ 99,
1680
+ 111,
1681
+ 110,
1682
+ 102,
1683
+ 105,
1684
+ 103
1685
+ ]
1686
+ }
1687
+ ]
1688
+ }
1689
+ },
1690
+ {
1691
+ name: "tree_in",
1692
+ docs: [
1693
+ "Tree of the asset being spent. The handler checks it is the PDA for its mint."
1694
+ ],
1695
+ writable: true
1696
+ },
1697
+ {
1698
+ name: "tree_out",
1699
+ docs: [
1700
+ "Tree that receives the swapped note."
1701
+ ],
1702
+ writable: true
1703
+ },
1704
+ {
1705
+ name: "treasury",
1706
+ writable: true,
1707
+ pda: {
1708
+ seeds: [
1709
+ {
1710
+ kind: "const",
1711
+ value: [
1712
+ 116,
1713
+ 114,
1714
+ 101,
1715
+ 97,
1716
+ 115,
1717
+ 117,
1718
+ 114,
1719
+ 121
1720
+ ]
1721
+ }
1722
+ ]
1723
+ }
1724
+ },
1725
+ {
1726
+ name: "escrow",
1727
+ docs: [
1728
+ "Signs the DEX call. Holds nothing between transactions."
1729
+ ],
1730
+ writable: true,
1731
+ pda: {
1732
+ seeds: [
1733
+ {
1734
+ kind: "const",
1735
+ value: [
1736
+ 115,
1737
+ 119,
1738
+ 97,
1739
+ 112,
1740
+ 95,
1741
+ 101,
1742
+ 115,
1743
+ 99,
1744
+ 114,
1745
+ 111,
1746
+ 119
1747
+ ]
1748
+ }
1749
+ ]
1750
+ }
1751
+ },
1752
+ {
1753
+ name: "treasury_ata_in",
1754
+ docs: [
1755
+ "Treasury ATA for `mint_in`. `None` when spending SOL."
1756
+ ],
1757
+ writable: true,
1758
+ optional: true
1759
+ },
1760
+ {
1761
+ name: "treasury_ata_out",
1762
+ docs: [
1763
+ "Treasury ATA for `mint_out`. `None` when receiving SOL."
1764
+ ],
1765
+ writable: true,
1766
+ optional: true
1767
+ },
1768
+ {
1769
+ name: "escrow_ata_in",
1770
+ docs: [
1771
+ "Escrow ATA for `mint_in` (wrapped SOL when spending SOL). Must exist: prepend an",
1772
+ "idempotent ATA create. A wrapped-SOL escrow account is closed at the end of the swap."
1773
+ ],
1774
+ writable: true
1775
+ },
1776
+ {
1777
+ name: "escrow_ata_out",
1778
+ docs: [
1779
+ "Escrow ATA for `mint_out` (wrapped SOL when receiving SOL). Must exist, as above."
1780
+ ],
1781
+ writable: true
1782
+ },
1783
+ {
1784
+ name: "relayer_ata",
1785
+ docs: [
1786
+ "Relayer ATA for `mint_in`, paid the relayer fee. `None` when spending SOL."
1787
+ ],
1788
+ writable: true,
1789
+ optional: true
1790
+ },
1791
+ {
1792
+ name: "nullifier0",
1793
+ writable: true,
1794
+ pda: {
1795
+ seeds: [
1796
+ {
1797
+ kind: "const",
1798
+ value: [
1799
+ 110,
1800
+ 117,
1801
+ 108,
1802
+ 108,
1803
+ 105,
1804
+ 102,
1805
+ 105,
1806
+ 101,
1807
+ 114
1808
+ ]
1809
+ },
1810
+ {
1811
+ kind: "arg",
1812
+ path: "proof.input_nullifiers [0]"
1813
+ }
1814
+ ]
1815
+ }
1816
+ },
1817
+ {
1818
+ name: "nullifier1",
1819
+ writable: true,
1820
+ pda: {
1821
+ seeds: [
1822
+ {
1823
+ kind: "const",
1824
+ value: [
1825
+ 110,
1826
+ 117,
1827
+ 108,
1828
+ 108,
1829
+ 105,
1830
+ 102,
1831
+ 105,
1832
+ 101,
1833
+ 114
1834
+ ]
1835
+ },
1836
+ {
1837
+ kind: "arg",
1838
+ path: "proof.input_nullifiers [1]"
1839
+ }
1840
+ ]
1841
+ }
1842
+ },
1843
+ {
1844
+ name: "mint_in",
1845
+ docs: [
1846
+ "Mint of the spent asset (the native mint when spending SOL)."
1847
+ ]
1848
+ },
1849
+ {
1850
+ name: "mint_out",
1851
+ docs: [
1852
+ "Mint of the received asset (the native mint when receiving SOL)."
1853
+ ]
1854
+ },
1855
+ {
1856
+ name: "token_program_in"
1857
+ },
1858
+ {
1859
+ name: "token_program_out"
1860
+ },
1861
+ {
1862
+ name: "dex_program"
1863
+ },
1864
+ {
1865
+ name: "system_program",
1866
+ address: "11111111111111111111111111111111"
1867
+ },
1868
+ {
1869
+ name: "event_authority",
1870
+ pda: {
1871
+ seeds: [
1872
+ {
1873
+ kind: "const",
1874
+ value: [
1875
+ 95,
1876
+ 95,
1877
+ 101,
1878
+ 118,
1441
1879
  101,
1442
- 114
1880
+ 110,
1881
+ 116,
1882
+ 95,
1883
+ 97,
1884
+ 117,
1885
+ 116,
1886
+ 104,
1887
+ 111,
1888
+ 114,
1889
+ 105,
1890
+ 116,
1891
+ 121
1443
1892
  ]
1444
- },
1445
- {
1446
- kind: "account",
1447
- path: "user"
1448
1893
  }
1449
1894
  ]
1450
1895
  }
1896
+ },
1897
+ {
1898
+ name: "program"
1451
1899
  }
1452
1900
  ],
1453
1901
  args: [
1454
1902
  {
1455
- name: "worker",
1456
- type: "pubkey"
1903
+ name: "proof",
1904
+ type: {
1905
+ defined: {
1906
+ name: "TransactionProof"
1907
+ }
1908
+ }
1909
+ },
1910
+ {
1911
+ name: "params",
1912
+ type: {
1913
+ defined: {
1914
+ name: "SwapParams"
1915
+ }
1916
+ }
1917
+ },
1918
+ {
1919
+ name: "encrypted_output1",
1920
+ type: "bytes"
1921
+ },
1922
+ {
1923
+ name: "encrypted_output2",
1924
+ type: "bytes"
1925
+ },
1926
+ {
1927
+ name: "route_data",
1928
+ type: "bytes"
1457
1929
  }
1458
1930
  ]
1459
1931
  },
@@ -1691,6 +2163,38 @@ var veilix_devnet_default = {
1691
2163
  {
1692
2164
  name: "system_program",
1693
2165
  address: "11111111111111111111111111111111"
2166
+ },
2167
+ {
2168
+ name: "event_authority",
2169
+ pda: {
2170
+ seeds: [
2171
+ {
2172
+ kind: "const",
2173
+ value: [
2174
+ 95,
2175
+ 95,
2176
+ 101,
2177
+ 118,
2178
+ 101,
2179
+ 110,
2180
+ 116,
2181
+ 95,
2182
+ 97,
2183
+ 117,
2184
+ 116,
2185
+ 104,
2186
+ 111,
2187
+ 114,
2188
+ 105,
2189
+ 116,
2190
+ 121
2191
+ ]
2192
+ }
2193
+ ]
2194
+ }
2195
+ },
2196
+ {
2197
+ name: "program"
1694
2198
  }
1695
2199
  ],
1696
2200
  args: [
@@ -2057,6 +2561,38 @@ var veilix_devnet_default = {
2057
2561
  {
2058
2562
  name: "system_program",
2059
2563
  address: "11111111111111111111111111111111"
2564
+ },
2565
+ {
2566
+ name: "event_authority",
2567
+ pda: {
2568
+ seeds: [
2569
+ {
2570
+ kind: "const",
2571
+ value: [
2572
+ 95,
2573
+ 95,
2574
+ 101,
2575
+ 118,
2576
+ 101,
2577
+ 110,
2578
+ 116,
2579
+ 95,
2580
+ 97,
2581
+ 117,
2582
+ 116,
2583
+ 104,
2584
+ 111,
2585
+ 114,
2586
+ 105,
2587
+ 116,
2588
+ 121
2589
+ ]
2590
+ }
2591
+ ]
2592
+ }
2593
+ },
2594
+ {
2595
+ name: "program"
2060
2596
  }
2061
2597
  ],
2062
2598
  args: [
@@ -2505,6 +3041,83 @@ var veilix_devnet_default = {
2505
3041
  }
2506
3042
  ]
2507
3043
  },
3044
+ {
3045
+ name: "update_swap_config",
3046
+ docs: [
3047
+ "Replaces the list of DEX programs the swap escrow may call. Config authority only."
3048
+ ],
3049
+ discriminator: [
3050
+ 123,
3051
+ 172,
3052
+ 158,
3053
+ 60,
3054
+ 104,
3055
+ 133,
3056
+ 39,
3057
+ 13
3058
+ ],
3059
+ accounts: [
3060
+ {
3061
+ name: "authority",
3062
+ writable: true,
3063
+ signer: true
3064
+ },
3065
+ {
3066
+ name: "network_state",
3067
+ pda: {
3068
+ seeds: [
3069
+ {
3070
+ kind: "const",
3071
+ value: [
3072
+ 99,
3073
+ 111,
3074
+ 110,
3075
+ 102,
3076
+ 105,
3077
+ 103
3078
+ ]
3079
+ }
3080
+ ]
3081
+ }
3082
+ },
3083
+ {
3084
+ name: "swap_config",
3085
+ writable: true,
3086
+ pda: {
3087
+ seeds: [
3088
+ {
3089
+ kind: "const",
3090
+ value: [
3091
+ 115,
3092
+ 119,
3093
+ 97,
3094
+ 112,
3095
+ 95,
3096
+ 99,
3097
+ 111,
3098
+ 110,
3099
+ 102,
3100
+ 105,
3101
+ 103
3102
+ ]
3103
+ }
3104
+ ]
3105
+ }
3106
+ },
3107
+ {
3108
+ name: "system_program",
3109
+ address: "11111111111111111111111111111111"
3110
+ }
3111
+ ],
3112
+ args: [
3113
+ {
3114
+ name: "allowed_programs",
3115
+ type: {
3116
+ vec: "pubkey"
3117
+ }
3118
+ }
3119
+ ]
3120
+ },
2508
3121
  {
2509
3122
  name: "withdraw",
2510
3123
  discriminator: [
@@ -2663,6 +3276,38 @@ var veilix_devnet_default = {
2663
3276
  {
2664
3277
  name: "system_program",
2665
3278
  address: "11111111111111111111111111111111"
3279
+ },
3280
+ {
3281
+ name: "event_authority",
3282
+ pda: {
3283
+ seeds: [
3284
+ {
3285
+ kind: "const",
3286
+ value: [
3287
+ 95,
3288
+ 95,
3289
+ 101,
3290
+ 118,
3291
+ 101,
3292
+ 110,
3293
+ 116,
3294
+ 95,
3295
+ 97,
3296
+ 117,
3297
+ 116,
3298
+ 104,
3299
+ 111,
3300
+ 114,
3301
+ 105,
3302
+ 116,
3303
+ 121
3304
+ ]
3305
+ }
3306
+ ]
3307
+ }
3308
+ },
3309
+ {
3310
+ name: "program"
2666
3311
  }
2667
3312
  ],
2668
3313
  args: [
@@ -2772,6 +3417,19 @@ var veilix_devnet_default = {
2772
3417
  20
2773
3418
  ]
2774
3419
  },
3420
+ {
3421
+ name: "SwapConfig",
3422
+ discriminator: [
3423
+ 212,
3424
+ 45,
3425
+ 70,
3426
+ 222,
3427
+ 245,
3428
+ 122,
3429
+ 125,
3430
+ 166
3431
+ ]
3432
+ },
2775
3433
  {
2776
3434
  name: "TreeAccount",
2777
3435
  discriminator: [
@@ -2813,6 +3471,19 @@ var veilix_devnet_default = {
2813
3471
  159
2814
3472
  ]
2815
3473
  },
3474
+ {
3475
+ name: "PrivateSwapEvent",
3476
+ discriminator: [
3477
+ 150,
3478
+ 165,
3479
+ 138,
3480
+ 189,
3481
+ 123,
3482
+ 86,
3483
+ 117,
3484
+ 39
3485
+ ]
3486
+ },
2816
3487
  {
2817
3488
  name: "RelayerCancelled",
2818
3489
  discriminator: [
@@ -3057,24 +3728,74 @@ var veilix_devnet_default = {
3057
3728
  msg: "Too many workers"
3058
3729
  },
3059
3730
  {
3060
- code: 6030,
3061
- name: "AlreadyRegistered",
3062
- msg: "Already registered"
3731
+ code: 6030,
3732
+ name: "AlreadyRegistered",
3733
+ msg: "Already registered"
3734
+ },
3735
+ {
3736
+ code: 6031,
3737
+ name: "NotRegistered",
3738
+ msg: "Not registered"
3739
+ },
3740
+ {
3741
+ code: 6032,
3742
+ name: "TooManyFeeAssets",
3743
+ msg: "Relayer has earned fees in too many assets"
3744
+ },
3745
+ {
3746
+ code: 6033,
3747
+ name: "FeeRepaymentAccounts",
3748
+ msg: "Fee repayment accounts do not match earned fees"
3749
+ },
3750
+ {
3751
+ code: 6034,
3752
+ name: "DexProgramNotAllowed",
3753
+ msg: "DEX program is not on the swap allowlist"
3754
+ },
3755
+ {
3756
+ code: 6035,
3757
+ name: "TooManyDexPrograms",
3758
+ msg: "Too many allowlisted DEX programs"
3759
+ },
3760
+ {
3761
+ code: 6036,
3762
+ name: "SlippageExceeded",
3763
+ msg: "Swap output is below the minimum amount"
3764
+ },
3765
+ {
3766
+ code: 6037,
3767
+ name: "SwapInputMismatch",
3768
+ msg: "DEX did not use exactly the escrowed swap input"
3769
+ },
3770
+ {
3771
+ code: 6038,
3772
+ name: "InvalidSwapAccounts",
3773
+ msg: "Swap accounts do not match the trees"
3774
+ },
3775
+ {
3776
+ code: 6039,
3777
+ name: "EscrowTampered",
3778
+ msg: "Swap escrow was modified by the DEX"
3779
+ },
3780
+ {
3781
+ code: 6040,
3782
+ name: "InvalidNoteKey",
3783
+ msg: "Note public key or blinding is not a valid field element"
3063
3784
  },
3064
3785
  {
3065
- code: 6031,
3066
- name: "NotRegistered",
3067
- msg: "Not registered"
3786
+ code: 6041,
3787
+ name: "NotUpgradeAuthority",
3788
+ msg: "Only the program upgrade authority can initialize the network"
3068
3789
  },
3069
3790
  {
3070
- code: 6032,
3071
- name: "TooManyFeeAssets",
3072
- msg: "Relayer has earned fees in too many assets"
3791
+ code: 6042,
3792
+ name: "InvalidFeeSplit",
3793
+ msg: "Fee wallets must be distinct, non-default and split at most the allowed total"
3073
3794
  },
3074
3795
  {
3075
- code: 6033,
3076
- name: "FeeRepaymentAccounts",
3077
- msg: "Fee repayment accounts do not match earned fees"
3796
+ code: 6043,
3797
+ name: "UnsupportedMintExtension",
3798
+ msg: "Token mint has an extension the pool does not support"
3078
3799
  }
3079
3800
  ],
3080
3801
  types: [
@@ -3255,6 +3976,68 @@ var veilix_devnet_default = {
3255
3976
  kind: "struct"
3256
3977
  }
3257
3978
  },
3979
+ {
3980
+ name: "PrivateSwapEvent",
3981
+ docs: [
3982
+ "Emitted once per swap. The asset-B note is `commitment` at `index` in the `mint_out` tree."
3983
+ ],
3984
+ type: {
3985
+ kind: "struct",
3986
+ fields: [
3987
+ {
3988
+ name: "mint_in",
3989
+ type: "pubkey"
3990
+ },
3991
+ {
3992
+ name: "mint_out",
3993
+ type: "pubkey"
3994
+ },
3995
+ {
3996
+ name: "amount_in",
3997
+ type: "u64"
3998
+ },
3999
+ {
4000
+ name: "fee",
4001
+ type: "u64"
4002
+ },
4003
+ {
4004
+ name: "amount_out",
4005
+ type: "u64"
4006
+ },
4007
+ {
4008
+ name: "input_nullifiers",
4009
+ type: {
4010
+ array: [
4011
+ {
4012
+ array: [
4013
+ "u8",
4014
+ 32
4015
+ ]
4016
+ },
4017
+ 2
4018
+ ]
4019
+ }
4020
+ },
4021
+ {
4022
+ name: "relayer",
4023
+ type: "pubkey"
4024
+ },
4025
+ {
4026
+ name: "commitment",
4027
+ type: {
4028
+ array: [
4029
+ "u8",
4030
+ 32
4031
+ ]
4032
+ }
4033
+ },
4034
+ {
4035
+ name: "index",
4036
+ type: "u64"
4037
+ }
4038
+ ]
4039
+ }
4040
+ },
3258
4041
  {
3259
4042
  name: "RelayerAccount",
3260
4043
  docs: [
@@ -3449,6 +4232,86 @@ var veilix_devnet_default = {
3449
4232
  ]
3450
4233
  }
3451
4234
  },
4235
+ {
4236
+ name: "SwapConfig",
4237
+ docs: [
4238
+ 'Programs the swap escrow is allowed to call. PDA seeds: `["swap_config"]`.'
4239
+ ],
4240
+ type: {
4241
+ kind: "struct",
4242
+ fields: [
4243
+ {
4244
+ name: "allowed_programs",
4245
+ type: {
4246
+ vec: "pubkey"
4247
+ }
4248
+ }
4249
+ ]
4250
+ }
4251
+ },
4252
+ {
4253
+ name: "SwapParams",
4254
+ docs: [
4255
+ "Swap parameters. All of them are bound into the proof's `extDataHash`."
4256
+ ],
4257
+ type: {
4258
+ kind: "struct",
4259
+ fields: [
4260
+ {
4261
+ name: "amount_in",
4262
+ docs: [
4263
+ "Asset-A amount spent from the pool, fee included."
4264
+ ],
4265
+ type: "u64"
4266
+ },
4267
+ {
4268
+ name: "fee",
4269
+ docs: [
4270
+ "Asset-A fee: protocol wallets get their split of `amount_in`, the relayer the rest."
4271
+ ],
4272
+ type: "u64"
4273
+ },
4274
+ {
4275
+ name: "min_amount_out",
4276
+ docs: [
4277
+ "Minimum asset-B amount that must reach the treasury."
4278
+ ],
4279
+ type: "u64"
4280
+ },
4281
+ {
4282
+ name: "out_pubkey",
4283
+ docs: [
4284
+ "One-time shielded public key of the asset-B note (32-byte big-endian field element)."
4285
+ ],
4286
+ type: {
4287
+ array: [
4288
+ "u8",
4289
+ 32
4290
+ ]
4291
+ }
4292
+ },
4293
+ {
4294
+ name: "out_blinding",
4295
+ docs: [
4296
+ "Blinding of the asset-B note (32-byte big-endian field element)."
4297
+ ],
4298
+ type: {
4299
+ array: [
4300
+ "u8",
4301
+ 32
4302
+ ]
4303
+ }
4304
+ },
4305
+ {
4306
+ name: "encrypted_note",
4307
+ docs: [
4308
+ "Optional encrypted recovery data for the asset-B note."
4309
+ ],
4310
+ type: "bytes"
4311
+ }
4312
+ ]
4313
+ }
4314
+ },
3452
4315
  {
3453
4316
  name: "TransactionProof",
3454
4317
  docs: [
@@ -7347,7 +8210,7 @@ var MAINNET_TOKEN_MINTS = {
7347
8210
  USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
7348
8211
  };
7349
8212
  var DEVNET_TOKEN_MINTS = {
7350
- Veilix: "GAFN64LvtCBoc5BHncVn3JEJGpq42rUzQjPmvMK2UhZH",
8213
+ Veilix: "Gmo636w21RBZX9ySVtPYcuYP6f1E5bdW5eBYhvK1bc8J",
7351
8214
  Bitcoin: "",
7352
8215
  Ethereum: "",
7353
8216
  USDC: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
@@ -7397,7 +8260,7 @@ function getDepositQueueForNetwork(network) {
7397
8260
  // package.json
7398
8261
  var package_default = {
7399
8262
  name: "veilix-sdk",
7400
- version: "0.2.3"};
8263
+ version: "0.3.0"};
7401
8264
 
7402
8265
  // src/circuits/constants.ts
7403
8266
  var PACKAGE_NAME = package_default.name;
@@ -7640,10 +8503,10 @@ var DEPOSIT_COMPUTE_UNIT_LIMIT = 35e4;
7640
8503
  function bytesToHex(bytes) {
7641
8504
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
7642
8505
  }
7643
- function hexToBytes(hex) {
7644
- const clean = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
8506
+ function hexToBytes(hex2) {
8507
+ const clean = hex2.startsWith("0x") || hex2.startsWith("0X") ? hex2.slice(2) : hex2;
7645
8508
  if (clean.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(clean)) {
7646
- throw new Error(`veilix-sdk: invalid hex string "${hex}"`);
8509
+ throw new Error(`veilix-sdk: invalid hex string "${hex2}"`);
7647
8510
  }
7648
8511
  const out = new Uint8Array(clean.length / 2);
7649
8512
  for (let i = 0; i < out.length; i++) {
@@ -7652,15 +8515,15 @@ function hexToBytes(hex) {
7652
8515
  return out;
7653
8516
  }
7654
8517
  function bigintToBytes32(value) {
7655
- const hex = BigInt(value).toString(16).padStart(64, "0");
7656
- if (hex.length > 64) {
8518
+ const hex2 = BigInt(value).toString(16).padStart(64, "0");
8519
+ if (hex2.length > 64) {
7657
8520
  throw new Error("veilix-sdk: value does not fit in 32 bytes");
7658
8521
  }
7659
- return hexToBytes(hex);
8522
+ return hexToBytes(hex2);
7660
8523
  }
7661
8524
  function bytesToBigint(bytes) {
7662
- const hex = bytesToHex(bytes);
7663
- return hex ? BigInt(`0x${hex}`) : 0n;
8525
+ const hex2 = bytesToHex(bytes);
8526
+ return hex2 ? BigInt(`0x${hex2}`) : 0n;
7664
8527
  }
7665
8528
  function toHex32(value) {
7666
8529
  return `0x${BigInt(value).toString(16).padStart(64, "0")}`;
@@ -7778,6 +8641,7 @@ var Utxo = class _Utxo {
7778
8641
  // src/core/note.ts
7779
8642
  var NOTE_PREFIX = "vx2";
7780
8643
  var ENCRYPTED_OUTPUT_VERSION = 1;
8644
+ var ENCRYPTED_SWAP_OUTPUT_VERSION = 2;
7781
8645
  var ENCRYPTED_OUTPUT_PLAINTEXT_BYTES = 1 + 8 + 32 + 32;
7782
8646
  var SECRETBOX_NONCE_BYTES = nacl.secretbox.nonceLength;
7783
8647
  function encodeNote(utxo) {
@@ -7810,14 +8674,14 @@ function decodeNote(note) {
7810
8674
  throw new Error("veilix-sdk: invalid note format");
7811
8675
  }
7812
8676
  const [, amountHex, privKeyHex, blindingHex, mint] = parts;
7813
- const hex = /^[0-9a-f]+$/i;
7814
- if (!hex.test(amountHex) || !hex.test(privKeyHex) || !hex.test(blindingHex)) {
8677
+ const hex2 = /^[0-9a-f]+$/i;
8678
+ if (!hex2.test(amountHex) || !hex2.test(privKeyHex) || !hex2.test(blindingHex)) {
7815
8679
  throw new Error("veilix-sdk: invalid note format");
7816
8680
  }
7817
- let mintKey = null;
8681
+ let mintKey2 = null;
7818
8682
  if (mint) {
7819
8683
  try {
7820
- mintKey = new PublicKey(mint);
8684
+ mintKey2 = new PublicKey(mint);
7821
8685
  } catch {
7822
8686
  throw new Error("veilix-sdk: invalid note mint");
7823
8687
  }
@@ -7826,7 +8690,7 @@ function decodeNote(note) {
7826
8690
  amount: BigInt(`0x${amountHex}`),
7827
8691
  keypair: VeilixKeypair.fromPrivateKey(BigInt(`0x${privKeyHex}`)),
7828
8692
  blinding: BigInt(`0x${blindingHex}`),
7829
- mint: mintKey
8693
+ mint: mintKey2
7830
8694
  });
7831
8695
  }
7832
8696
  function describeUtxo(utxo) {
@@ -7844,7 +8708,7 @@ function describeUtxo(utxo) {
7844
8708
  function parseSecretNote(note) {
7845
8709
  return describeUtxo(decodeNote(note));
7846
8710
  }
7847
- function encryptNoteOutput(key, utxo) {
8711
+ function encryptNoteOutput(key2, utxo) {
7848
8712
  const amount = new Uint8Array(8);
7849
8713
  new DataView(amount.buffer).setBigUint64(0, utxo.amount, true);
7850
8714
  const plaintext = concatBytes([
@@ -7854,21 +8718,38 @@ function encryptNoteOutput(key, utxo) {
7854
8718
  bigintToBytes32(utxo.blinding)
7855
8719
  ]);
7856
8720
  const nonce = nacl.randomBytes(SECRETBOX_NONCE_BYTES);
7857
- return concatBytes([nonce, nacl.secretbox(plaintext, nonce, key)]);
8721
+ return concatBytes([nonce, nacl.secretbox(plaintext, nonce, key2)]);
8722
+ }
8723
+ function encryptSwapNoteOutput(key2, keypair, blinding) {
8724
+ const plaintext = concatBytes([
8725
+ Uint8Array.of(ENCRYPTED_SWAP_OUTPUT_VERSION),
8726
+ new Uint8Array(8),
8727
+ bigintToBytes32(keypair.privKey),
8728
+ bigintToBytes32(blinding)
8729
+ ]);
8730
+ const nonce = nacl.randomBytes(SECRETBOX_NONCE_BYTES);
8731
+ return concatBytes([nonce, nacl.secretbox(plaintext, nonce, key2)]);
7858
8732
  }
7859
- function decryptNoteOutput(key, encryptedOutput, mint, index) {
8733
+ function decryptNoteOutput(key2, encryptedOutput, mint, index, onchainAmount = null) {
7860
8734
  if (encryptedOutput.length !== SECRETBOX_NONCE_BYTES + nacl.secretbox.overheadLength + ENCRYPTED_OUTPUT_PLAINTEXT_BYTES) {
7861
8735
  return null;
7862
8736
  }
7863
8737
  const opened = nacl.secretbox.open(
7864
8738
  encryptedOutput.subarray(SECRETBOX_NONCE_BYTES),
7865
8739
  encryptedOutput.subarray(0, SECRETBOX_NONCE_BYTES),
7866
- key
8740
+ key2
7867
8741
  );
7868
- if (!opened || opened[0] !== ENCRYPTED_OUTPUT_VERSION) {
8742
+ if (!opened) {
8743
+ return null;
8744
+ }
8745
+ let amount;
8746
+ if (opened[0] === ENCRYPTED_OUTPUT_VERSION) {
8747
+ amount = new DataView(opened.buffer, opened.byteOffset + 1, 8).getBigUint64(0, true);
8748
+ } else if (opened[0] === ENCRYPTED_SWAP_OUTPUT_VERSION && onchainAmount !== null) {
8749
+ amount = onchainAmount;
8750
+ } else {
7869
8751
  return null;
7870
8752
  }
7871
- const amount = new DataView(opened.buffer, opened.byteOffset + 1, 8).getBigUint64(0, true);
7872
8753
  return new Utxo({
7873
8754
  amount,
7874
8755
  keypair: VeilixKeypair.fromPrivateKey(bytesToBigint(opened.subarray(9, 41))),
@@ -16349,6 +17230,7 @@ async function proveTransaction({
16349
17230
  inputs = [],
16350
17231
  outputs = [],
16351
17232
  ext,
17233
+ extDataHashOverride,
16352
17234
  circuit
16353
17235
  }) {
16354
17236
  for (const utxo of [...inputs, ...outputs]) {
@@ -16398,7 +17280,7 @@ async function proveTransaction({
16398
17280
  const input = {
16399
17281
  root: proofRoot.toString(),
16400
17282
  publicAmount: publicAmount.toString(),
16401
- extDataHash: (await extDataHash(ext)).toString(),
17283
+ extDataHash: (extDataHashOverride ?? await extDataHash(ext)).toString(),
16402
17284
  mint: mintToField(ext.mint).toString(),
16403
17285
  inputNullifier: inputNullifiers.map(String),
16404
17286
  outputCommitment: outputCommitments.map(String),
@@ -16539,8 +17421,8 @@ function generateDepositParams(amount, mint = null) {
16539
17421
  if (value <= 0n) {
16540
17422
  throw new Error("veilix-sdk: deposit amount must be positive");
16541
17423
  }
16542
- const mintKey = mint && mint !== WRAPPED_SOL_MINT ? new PublicKey(mint) : null;
16543
- const note = encodeNote(new Utxo({ amount: value, mint: mintKey }));
17424
+ const mintKey2 = mint && mint !== WRAPPED_SOL_MINT ? new PublicKey(mint) : null;
17425
+ const note = encodeNote(new Utxo({ amount: value, mint: mintKey2 }));
16544
17426
  return { note, params: parseSecretNote(note) };
16545
17427
  }
16546
17428
  function to32ByteBuffer(value) {
@@ -16574,8 +17456,8 @@ function toPublicKey(value) {
16574
17456
  }
16575
17457
  function normalizeTreeMint(mint) {
16576
17458
  if (!mint) return null;
16577
- const key = toPublicKey(mint);
16578
- return key.equals(NATIVE_MINT) || key.equals(PublicKey.default) ? null : key;
17459
+ const key2 = toPublicKey(mint);
17460
+ return key2.equals(NATIVE_MINT) || key2.equals(PublicKey.default) ? null : key2;
16579
17461
  }
16580
17462
  function getTreePDA(mint) {
16581
17463
  const treeMint = normalizeTreeMint(mint);
@@ -16826,8 +17708,8 @@ async function resolveEncryptKey() {
16826
17708
  }
16827
17709
  async function buildBackupNotesInstruction(sender, notes) {
16828
17710
  const { program } = getConfig();
16829
- const key = await resolveEncryptKey();
16830
- return program.methods.backupNotes(notes.map((note) => encryptData(key, note))).accountsPartial({ user: sender }).instruction();
17711
+ const key2 = await resolveEncryptKey();
17712
+ return program.methods.backupNotes(notes.map((note) => encryptData(key2, note))).accountsPartial({ user: sender }).instruction();
16831
17713
  }
16832
17714
  async function isExtendBackupPdaNeeded(walletPubkey, newNotesLength) {
16833
17715
  const account = await fetchNotesAccount(walletPubkey);
@@ -16932,16 +17814,16 @@ async function getEncryptionKey(wallet) {
16932
17814
  }
16933
17815
  return nacl.hash(signature).slice(0, 32);
16934
17816
  }
16935
- function encryptData(key, plaintext) {
17817
+ function encryptData(key2, plaintext) {
16936
17818
  const nonce = nacl.randomBytes(24);
16937
- const box = nacl.secretbox(new TextEncoder().encode(plaintext), nonce, key);
17819
+ const box = nacl.secretbox(new TextEncoder().encode(plaintext), nonce, key2);
16938
17820
  const combined = new Uint8Array(nonce.length + box.length);
16939
17821
  combined.set(nonce);
16940
17822
  combined.set(box, nonce.length);
16941
17823
  return Buffer.from(combined);
16942
17824
  }
16943
- function decryptData(key, combined) {
16944
- const decrypted = nacl.secretbox.open(combined.slice(24), combined.slice(0, 24), key);
17825
+ function decryptData(key2, combined) {
17826
+ const decrypted = nacl.secretbox.open(combined.slice(24), combined.slice(0, 24), key2);
16945
17827
  if (!decrypted) throw new Error("Decryption failed");
16946
17828
  return new TextDecoder().decode(decrypted);
16947
17829
  }
@@ -16979,8 +17861,8 @@ var COMMITMENTS_PAGE_LIMIT = 8e3;
16979
17861
  var VALIDATE_NULLIFIERS_BATCH = 64;
16980
17862
  async function indexerGet(path, params) {
16981
17863
  const query = new URLSearchParams();
16982
- for (const [key, value] of Object.entries(params)) {
16983
- if (value !== void 0 && value !== "") query.set(key, value);
17864
+ for (const [key2, value] of Object.entries(params)) {
17865
+ if (value !== void 0 && value !== "") query.set(key2, value);
16984
17866
  }
16985
17867
  const qs = query.toString();
16986
17868
  return httpFetch(`${getIndexerUrl()}${path}${qs ? `?${qs}` : ""}`, {
@@ -17195,7 +18077,7 @@ async function scanOwnedNotes({
17195
18077
  mints,
17196
18078
  includeSpent = false
17197
18079
  } = {}) {
17198
- const key = requireEncryptKey();
18080
+ const key2 = requireEncryptKey();
17199
18081
  const explicit = mints !== void 0;
17200
18082
  const tokenMints = getTokenMintsForNetwork(getConfig().network);
17201
18083
  const targets = mints ?? [null, tokenMints.Veilix, tokenMints.Bitcoin, tokenMints.Ethereum, tokenMints.USDC].filter(
@@ -17213,7 +18095,13 @@ async function scanOwnedNotes({
17213
18095
  }
17214
18096
  for (const leaf of leaves) {
17215
18097
  if (!leaf.encryptedOutput || leaf.encryptedOutput.length <= 2) continue;
17216
- const utxo = decryptNoteOutput(key, hexToBytes(leaf.encryptedOutput), treeMint, leaf.index);
18098
+ const utxo = decryptNoteOutput(
18099
+ key2,
18100
+ hexToBytes(leaf.encryptedOutput),
18101
+ treeMint,
18102
+ leaf.index,
18103
+ leaf.amountRaw ? BigInt(leaf.amountRaw) : null
18104
+ );
17217
18105
  if (!utxo || utxo.amount === 0n) continue;
17218
18106
  if (toHex32(utxo.commitment()) !== toHex32(BigInt(leaf.commitment))) continue;
17219
18107
  found.push({ utxo, note: encodeNote(utxo), signature: null });
@@ -17493,6 +18381,364 @@ async function getQuote(params) {
17493
18381
  }
17494
18382
  return data;
17495
18383
  }
18384
+ var SWAP_DOMAIN = new TextEncoder().encode("veilix:swap:v1");
18385
+ async function swapExtDataHash(ext) {
18386
+ const hash = await sha256(
18387
+ concatBytes([
18388
+ SWAP_DOMAIN,
18389
+ (ext.mintIn ?? PublicKey.default).toBytes(),
18390
+ (ext.mintOut ?? PublicKey.default).toBytes(),
18391
+ ext.relayer.toBytes(),
18392
+ u64le(ext.amountIn),
18393
+ u64le(ext.fee),
18394
+ u64le(ext.minAmountOut),
18395
+ bigintToBytes32(ext.outPubkey),
18396
+ bigintToBytes32(ext.outBlinding),
18397
+ u32le(ext.encryptedOutput1.length),
18398
+ ext.encryptedOutput1,
18399
+ u32le(ext.encryptedOutput2.length),
18400
+ ext.encryptedOutput2,
18401
+ u32le(ext.encryptedNote.length),
18402
+ ext.encryptedNote
18403
+ ])
18404
+ );
18405
+ hash[0] = 0;
18406
+ return bytesToBigint(hash);
18407
+ }
18408
+ var CPMM_PROGRAM_IDS = {
18409
+ devnet: "DRaycpLY18LhpbydsBWbVJtxpNv9oXPgjRSfpF2bWpYb",
18410
+ mainnet: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"
18411
+ };
18412
+ var FEE_RATE_DENOMINATOR = 1000000n;
18413
+ var SWAP_DISABLED_BIT = 2;
18414
+ var key = (data, offset) => new PublicKey(data.subarray(offset, offset + 32));
18415
+ var u64 = (data, offset) => new DataView(data.buffer, data.byteOffset + offset, 8).getBigUint64(0, true);
18416
+ var ceilDiv = (a, b) => (a + b - 1n) / b;
18417
+ var feeOf = (amount, rate) => ceilDiv(amount * rate, FEE_RATE_DENOMINATOR);
18418
+ async function quoteCpmm(connection, network, poolAddress, treeMintIn, treeMintOut, amountIn) {
18419
+ const programId = new PublicKey(CPMM_PROGRAM_IDS[network]);
18420
+ const poolInfo = await connection.getAccountInfo(poolAddress, "confirmed");
18421
+ if (!poolInfo || !poolInfo.owner.equals(programId) || poolInfo.data.length < 381) {
18422
+ throw new Error("veilix-sdk: swap pool is not a Raydium CPMM pool");
18423
+ }
18424
+ const data = poolInfo.data;
18425
+ const pool = {
18426
+ ammConfig: key(data, 8),
18427
+ vault0: key(data, 72),
18428
+ vault1: key(data, 104),
18429
+ mint0: key(data, 168),
18430
+ mint1: key(data, 200),
18431
+ status: data[329],
18432
+ protocolFees: [u64(data, 341), u64(data, 349)],
18433
+ fundFees: [u64(data, 357), u64(data, 365)],
18434
+ creatorFeeOn: data.length >= 413 ? data[389] : 0,
18435
+ enableCreatorFee: data.length >= 413 ? data[390] === 1 : false,
18436
+ creatorFees: data.length >= 413 ? [u64(data, 397), u64(data, 405)] : [0n, 0n]
18437
+ };
18438
+ if (pool.status >> SWAP_DISABLED_BIT & 1) {
18439
+ throw new Error("veilix-sdk: swaps are disabled on this pool");
18440
+ }
18441
+ const mintIn = treeMintIn ?? NATIVE_MINT;
18442
+ const mintOut = treeMintOut ?? NATIVE_MINT;
18443
+ let zeroForOne;
18444
+ if (pool.mint0.equals(mintIn) && pool.mint1.equals(mintOut)) zeroForOne = true;
18445
+ else if (pool.mint1.equals(mintIn) && pool.mint0.equals(mintOut)) zeroForOne = false;
18446
+ else throw new Error("veilix-sdk: swap pool does not trade this pair");
18447
+ const [i, o] = zeroForOne ? [0, 1] : [1, 0];
18448
+ const [configInfo, vaultIn, vaultOut] = await connection.getMultipleAccountsInfo(
18449
+ [pool.ammConfig, zeroForOne ? pool.vault0 : pool.vault1, zeroForOne ? pool.vault1 : pool.vault0],
18450
+ "confirmed"
18451
+ );
18452
+ if (!configInfo || !vaultIn || !vaultOut) {
18453
+ throw new Error("veilix-sdk: swap pool accounts are missing");
18454
+ }
18455
+ const tradeFeeRate = u64(configInfo.data, 12);
18456
+ const creatorFeeRate = pool.enableCreatorFee && configInfo.data.length >= 116 ? u64(configInfo.data, 108) : 0n;
18457
+ const reserveIn = u64(vaultIn.data, 64) - pool.protocolFees[i] - pool.fundFees[i] - pool.creatorFees[i];
18458
+ const reserveOut = u64(vaultOut.data, 64) - pool.protocolFees[o] - pool.fundFees[o] - pool.creatorFees[o];
18459
+ if (reserveIn <= 0n || reserveOut <= 0n) {
18460
+ throw new Error("veilix-sdk: swap pool has no liquidity");
18461
+ }
18462
+ const creatorOnInput = pool.creatorFeeOn === 0 || pool.creatorFeeOn === 1 && zeroForOne || pool.creatorFeeOn === 2 && !zeroForOne;
18463
+ let inLessFees = amountIn - feeOf(amountIn, tradeFeeRate);
18464
+ if (creatorOnInput) inLessFees -= feeOf(amountIn, creatorFeeRate);
18465
+ let amountOut = inLessFees * reserveOut / (reserveIn + inLessFees);
18466
+ if (!creatorOnInput) amountOut -= feeOf(amountOut, creatorFeeRate);
18467
+ if (amountOut <= 0n) {
18468
+ throw new Error("veilix-sdk: swap amount is too small for this pool");
18469
+ }
18470
+ const spotOut = Number(inLessFees) * (Number(reserveOut) / Number(reserveIn));
18471
+ const priceImpact = spotOut > 0 ? Math.max(0, 1 - Number(amountOut) / spotOut) : 1;
18472
+ return { amountOut, priceImpact };
18473
+ }
18474
+
18475
+ // src/swap/execute.ts
18476
+ var SWAP_MAX_WAIT_MS = 18e4;
18477
+ var DEFAULT_SLIPPAGE_BPS = 100;
18478
+ var MAX_SLIPPAGE_BPS = 5e3;
18479
+ var MAX_PRICE_IMPACT = 0.1;
18480
+ var hex = (bytes) => `0x${bytesToHex(bytes)}`;
18481
+ var mintKey = (mint) => mint?.toBase58() ?? null;
18482
+ async function fetchRelayerQuote(relayerUrl, mintIn, mintOut, amountIn) {
18483
+ const params = new URLSearchParams({ amountIn: amountIn.toString() });
18484
+ if (mintIn) params.set("mintIn", mintIn.toBase58());
18485
+ if (mintOut) params.set("mintOut", mintOut.toBase58());
18486
+ const base = relayerUrl.replace(/\/$/, "");
18487
+ const res = await httpFetch(`${base}/v1/swapQuote?${params}`, {
18488
+ headers: { Accept: "application/json" }
18489
+ });
18490
+ const body = await res.json().catch(() => ({}));
18491
+ if (!res.ok) {
18492
+ throw new Error(body.error || `Swap quote failed (${res.status})`);
18493
+ }
18494
+ return { ...body, relayerUrl: base };
18495
+ }
18496
+ function swapCandidates(relayers, relayerUrl) {
18497
+ if (relayerUrl) {
18498
+ const wanted = relayerUrl.replace(/\/$/, "");
18499
+ const match = relayers.find((r) => r.url.replace(/\/$/, "") === wanted);
18500
+ if (!match) throw new Error(`veilix-sdk: relayer ${relayerUrl} is not available`);
18501
+ return [match];
18502
+ }
18503
+ if (!relayers.length) throw new Error("veilix-sdk: no relayer available");
18504
+ const first = getRandomRelayer(relayers);
18505
+ return [first, ...relayers.filter((r) => r !== first)];
18506
+ }
18507
+ async function getSwapQuote(params) {
18508
+ const { relayers } = getConfig();
18509
+ const mintIn = normalizeTreeMint(params.mintIn);
18510
+ const mintOut = normalizeTreeMint(params.mintOut);
18511
+ if (mintKey(mintIn) === mintKey(mintOut)) {
18512
+ throw new Error("veilix-sdk: swap needs two different assets");
18513
+ }
18514
+ const amountIn = BigInt(params.amountIn);
18515
+ if (amountIn <= 0n) throw new Error("veilix-sdk: swap amount must be positive");
18516
+ const { connection, network } = getConfig();
18517
+ const platformWallets = await fetchPlatformFeeWallets();
18518
+ let lastError = null;
18519
+ for (const relayer of swapCandidates(relayers, params.relayerUrl)) {
18520
+ try {
18521
+ const quote = await fetchRelayerQuote(relayer.url, mintIn, mintOut, amountIn);
18522
+ if (quote.relayer !== relayer.value) {
18523
+ throw new Error("Relayer quoted for a different reward account");
18524
+ }
18525
+ const { fee } = computeWithdrawFee(amountIn, relayer.fee, platformWallets);
18526
+ if (fee >= amountIn) throw new Error("Amount is too small to cover the fees");
18527
+ if (BigInt(quote.fee) !== fee) throw new Error("Relayer quoted a different fee");
18528
+ if (quote.dexProgram !== CPMM_PROGRAM_IDS[network]) {
18529
+ throw new Error("Relayer routes through an unsupported DEX");
18530
+ }
18531
+ const own = await quoteCpmm(
18532
+ connection,
18533
+ network,
18534
+ new PublicKey(quote.pool),
18535
+ mintIn,
18536
+ mintOut,
18537
+ amountIn - fee
18538
+ );
18539
+ if (own.priceImpact > MAX_PRICE_IMPACT) {
18540
+ throw new Error(
18541
+ `Price impact ${(own.priceImpact * 100).toFixed(1)}% is too high for this pool; swap less`
18542
+ );
18543
+ }
18544
+ return {
18545
+ quote: {
18546
+ ...quote,
18547
+ swapIn: (amountIn - fee).toString(),
18548
+ amountOut: own.amountOut.toString(),
18549
+ priceImpact: own.priceImpact
18550
+ },
18551
+ relayer
18552
+ };
18553
+ } catch (error) {
18554
+ lastError = error;
18555
+ }
18556
+ }
18557
+ const reason = lastError instanceof Error ? lastError.message : "no relayer routes this pair";
18558
+ throw new Error(`veilix-sdk: no swap route for this pair (${reason})`);
18559
+ }
18560
+ async function buildSwapPayload(params, options = {}) {
18561
+ const { encryptKey } = getConfig();
18562
+ const utxo = decodeNote(params.note);
18563
+ const mintIn = utxo.mint;
18564
+ const mintOut = normalizeTreeMint(params.mintOut ?? null);
18565
+ const slippageBps = params.slippageBps ?? DEFAULT_SLIPPAGE_BPS;
18566
+ if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > MAX_SLIPPAGE_BPS) {
18567
+ throw new Error(`veilix-sdk: slippageBps must be an integer between 0 and ${MAX_SLIPPAGE_BPS}`);
18568
+ }
18569
+ const { index } = await locateNote(utxo);
18570
+ if (index === null) {
18571
+ throw new Error("Note is not in the Veilix pool yet (deposit not confirmed or not indexed)");
18572
+ }
18573
+ utxo.index = index;
18574
+ if ((await validateNullifier(toHex32(utxo.nullifier()))).exists) {
18575
+ throw new Error("This note has already been spent");
18576
+ }
18577
+ const amountIn = params.amount === void 0 ? utxo.amount : BigInt(params.amount);
18578
+ if (amountIn <= 0n || amountIn > utxo.amount) {
18579
+ throw new Error(`Swap amount must be between 1 and ${utxo.amount}`);
18580
+ }
18581
+ const { quote, relayer } = await getSwapQuote({
18582
+ mintIn,
18583
+ mintOut,
18584
+ amountIn,
18585
+ relayerUrl: params.relayerUrl
18586
+ });
18587
+ const fee = BigInt(quote.fee);
18588
+ const minAmountOut = BigInt(quote.amountOut) * BigInt(1e4 - slippageBps) / 10000n;
18589
+ if (minAmountOut <= 0n) {
18590
+ throw new Error("Swap amount is too small for this pool");
18591
+ }
18592
+ let tree = options.tree;
18593
+ if (!tree || tree.elements.length <= index) {
18594
+ tree = await fetchAssetTree(mintKey(mintIn));
18595
+ }
18596
+ if (tree.elements.length <= index) {
18597
+ throw new Error("The indexer has not synced this note yet, retry shortly");
18598
+ }
18599
+ const change = utxo.amount - amountIn;
18600
+ const changeUtxo = change > 0n ? new Utxo({ amount: change, mint: mintIn }) : null;
18601
+ const encryptedOutput1 = changeUtxo && encryptKey ? encryptNoteOutput(encryptKey, changeUtxo) : new Uint8Array();
18602
+ const encryptedOutput2 = new Uint8Array();
18603
+ const outKeypair = VeilixKeypair.random();
18604
+ const outBlinding = randomFieldElement();
18605
+ const encryptedNote = encryptKey ? encryptSwapNoteOutput(encryptKey, outKeypair, outBlinding) : new Uint8Array();
18606
+ const relayerKey = new PublicKey(relayer.value);
18607
+ const hash = await swapExtDataHash({
18608
+ mintIn,
18609
+ mintOut,
18610
+ relayer: relayerKey,
18611
+ amountIn,
18612
+ fee,
18613
+ minAmountOut,
18614
+ outPubkey: outKeypair.pubKey,
18615
+ outBlinding,
18616
+ encryptedOutput1,
18617
+ encryptedOutput2,
18618
+ encryptedNote
18619
+ });
18620
+ const proved = await withCircuitArtifacts(
18621
+ options.circuitArtifacts,
18622
+ (artifacts) => proveTransaction({
18623
+ tree,
18624
+ inputs: [utxo],
18625
+ outputs: changeUtxo ? [changeUtxo] : [],
18626
+ ext: {
18627
+ mint: mintIn,
18628
+ recipient: PublicKey.default,
18629
+ relayer: relayerKey,
18630
+ extAmount: -amountIn,
18631
+ fee,
18632
+ encryptedOutput1,
18633
+ encryptedOutput2
18634
+ },
18635
+ extDataHashOverride: hash,
18636
+ circuit: artifacts
18637
+ })
18638
+ );
18639
+ const { proof } = proved;
18640
+ const payload = {
18641
+ proof: hex(proof.proof),
18642
+ root: hex(proof.root),
18643
+ inputNullifiers: [hex(proof.inputNullifiers[0]), hex(proof.inputNullifiers[1])],
18644
+ outputCommitments: [hex(proof.outputCommitments[0]), hex(proof.outputCommitments[1])],
18645
+ ...mintIn ? { mintIn: mintIn.toBase58() } : {},
18646
+ ...mintOut ? { mintOut: mintOut.toBase58() } : {},
18647
+ amountIn: amountIn.toString(),
18648
+ fee: fee.toString(),
18649
+ minAmountOut: minAmountOut.toString(),
18650
+ outPubkey: hex(bigintToBytes32(outKeypair.pubKey)),
18651
+ outBlinding: hex(bigintToBytes32(outBlinding)),
18652
+ relayer: relayerKey.toBase58(),
18653
+ encryptedOutput1: hex(encryptedOutput1),
18654
+ encryptedOutput2: hex(encryptedOutput2),
18655
+ encryptedNote: hex(encryptedNote)
18656
+ };
18657
+ return {
18658
+ payload,
18659
+ relayerUrl: quote.relayerUrl,
18660
+ quote,
18661
+ amountIn,
18662
+ fee,
18663
+ minAmountOut,
18664
+ changeNote: changeUtxo ? encodeNote(changeUtxo) : null,
18665
+ output: {
18666
+ mint: mintKey(mintOut),
18667
+ privKey: outKeypair.privKey.toString(),
18668
+ blinding: outBlinding.toString()
18669
+ },
18670
+ nullifiers: [...payload.inputNullifiers]
18671
+ };
18672
+ }
18673
+ async function pollSwapJob(relayerUrl, jobId, maxWaitMs) {
18674
+ const start = Date.now();
18675
+ while (Date.now() - start < maxWaitMs) {
18676
+ const res = await httpFetch(`${relayerUrl}/v1/jobs/${encodeURIComponent(jobId)}`, {
18677
+ headers: { Accept: "application/json" }
18678
+ });
18679
+ const job = await res.json().catch(() => ({}));
18680
+ if (!res.ok) throw new Error(job.error || "Failed to poll relayer job");
18681
+ if (job.status === "CONFIRMED" || job.status === "FAILED") return job;
18682
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
18683
+ }
18684
+ throw new Error("Swap timed out");
18685
+ }
18686
+ function swapOutputNote(output, result) {
18687
+ const utxo = new Utxo({
18688
+ amount: BigInt(result.amountOut),
18689
+ keypair: VeilixKeypair.fromPrivateKey(output.privKey),
18690
+ blinding: BigInt(output.blinding),
18691
+ mint: output.mint ? new PublicKey(output.mint) : null,
18692
+ index: result.outputIndex
18693
+ });
18694
+ if (toHex32(utxo.commitment()) !== toHex32(BigInt(result.outputCommitment))) {
18695
+ throw new Error("veilix-sdk: swapped note does not match the on-chain commitment");
18696
+ }
18697
+ return encodeNote(utxo);
18698
+ }
18699
+ async function submitSwapPayload(bundle) {
18700
+ const res = await httpFetch(`${bundle.relayerUrl}/v1/veilixSwap`, {
18701
+ method: "POST",
18702
+ headers: { "Content-Type": "application/json" },
18703
+ body: JSON.stringify(bundle.payload)
18704
+ });
18705
+ const body = await res.json().catch(() => ({}));
18706
+ if (!res.ok || !body.id) {
18707
+ throw new Error(body.error || "Swap submission failed");
18708
+ }
18709
+ const job = await pollSwapJob(bundle.relayerUrl, body.id, SWAP_MAX_WAIT_MS);
18710
+ const base = {
18711
+ changeNote: bundle.changeNote,
18712
+ amountIn: bundle.amountIn.toString(),
18713
+ fee: bundle.fee.toString(),
18714
+ minAmountOut: bundle.minAmountOut.toString()
18715
+ };
18716
+ if (job.status === "FAILED") {
18717
+ return {
18718
+ ...base,
18719
+ txHash: job.txHash ?? "",
18720
+ status: "failed",
18721
+ error: job.failedReason || "Swap failed",
18722
+ // A failed swap spends nothing: the original note is still valid.
18723
+ outputNote: null,
18724
+ changeNote: null,
18725
+ amountOut: null
18726
+ };
18727
+ }
18728
+ if (!job.txHash || !job.swapResult) {
18729
+ throw new Error("Swap confirmed but the relayer did not report the swapped note");
18730
+ }
18731
+ return {
18732
+ ...base,
18733
+ txHash: job.txHash,
18734
+ status: "success",
18735
+ outputNote: swapOutputNote(bundle.output, job.swapResult),
18736
+ amountOut: job.swapResult.amountOut
18737
+ };
18738
+ }
18739
+ async function executeSwap(params) {
18740
+ return submitSwapPayload(await buildSwapPayload(params));
18741
+ }
17496
18742
 
17497
18743
  // src/withdraw/assets.ts
17498
18744
  var TOKEN_UNITS = {
@@ -17933,6 +19179,26 @@ var VeilixSDK = class _VeilixSDK {
17933
19179
  submitWithdrawPayload(bundle) {
17934
19180
  return this.runAsync(() => submitWithdrawPayload(bundle));
17935
19181
  }
19182
+ // ── Private swap ─────────────────────────────────────────────────────
19183
+ /** Fee and expected output of swapping `amountIn` of `mintIn` into `mintOut`. */
19184
+ getSwapQuote(params) {
19185
+ return this.runAsync(() => getSwapQuote(params));
19186
+ }
19187
+ /**
19188
+ * Swap a note of asset A into a new shielded note of asset B (`mintOut`, `null` for
19189
+ * SOL) through a relayer and an allowlisted DEX. Funds never leave the pool
19190
+ * unshielded. Returns the asset-B note and any asset-A change note.
19191
+ */
19192
+ swap(params) {
19193
+ return this.runAsync(() => executeSwap(params));
19194
+ }
19195
+ /** Prove a swap without submitting it (see {@link submitSwapPayload}). */
19196
+ buildSwapPayload(params, options) {
19197
+ return this.runAsync(() => buildSwapPayload(params, options));
19198
+ }
19199
+ submitSwapPayload(bundle) {
19200
+ return this.runAsync(() => submitSwapPayload(bundle));
19201
+ }
17936
19202
  /**
17937
19203
  * Private transfer: deposit one note per item, then withdraw each note in full
17938
19204
  * to its recipient through the indexer submission queue.
@@ -18044,15 +19310,15 @@ var VeilixSDK = class _VeilixSDK {
18044
19310
  * Accepts a frontend wallet adapter (`signMessage`) or a backend {@link Keypair}.
18045
19311
  */
18046
19312
  async getEncryptionKey(wallet) {
18047
- const key = await getEncryptionKey(wallet);
18048
- this.config.encryptKey = key;
18049
- return key;
19313
+ const key2 = await getEncryptionKey(wallet);
19314
+ this.config.encryptKey = key2;
19315
+ return key2;
18050
19316
  }
18051
- encryptData(key, plaintext) {
18052
- return encryptData(key, plaintext);
19317
+ encryptData(key2, plaintext) {
19318
+ return encryptData(key2, plaintext);
18053
19319
  }
18054
- decryptData(key, combined) {
18055
- return decryptData(key, combined);
19320
+ decryptData(key2, combined) {
19321
+ return decryptData(key2, combined);
18056
19322
  }
18057
19323
  // ── Utilities ────────────────────────────────────────────────────────
18058
19324
  parseAmountToBaseUnits(amount, decimals) {
@@ -18090,6 +19356,6 @@ var VeilixSDK = class _VeilixSDK {
18090
19356
  * @license MIT
18091
19357
  */
18092
19358
 
18093
- export { FIELD_SIZE, MALICIOUS_RECIPIENT_ERROR, NOTE_PREFIX, TREE_LEVELS, Utxo, VeilixKeypair, VeilixSDK, WITHDRAW_CIRCUIT_WASM, WITHDRAW_CIRCUIT_ZKEY, ZERO_LEAF, buildMerkleTree, decodeNote, decryptData, decryptNoteOutput, VeilixSDK as default, encodeNote, encryptData, encryptNoteOutput, extDataHash, formatBaseUnits, formatNoteForDisplay, getQuote, isLegacyNote, mintToField, parseAmountToBaseUnits, parseSecretNote, prepareCircuitArtifacts, proveTransaction, resolveCircuitPathsFromBase, resolveNpmCdnCircuitBase };
19359
+ export { CPMM_PROGRAM_IDS, FIELD_SIZE, MALICIOUS_RECIPIENT_ERROR, NOTE_PREFIX, SWAP_DOMAIN, TREE_LEVELS, Utxo, VeilixKeypair, VeilixSDK, WITHDRAW_CIRCUIT_WASM, WITHDRAW_CIRCUIT_ZKEY, ZERO_LEAF, buildMerkleTree, decodeNote, decryptData, decryptNoteOutput, VeilixSDK as default, encodeNote, encryptData, encryptNoteOutput, encryptSwapNoteOutput, extDataHash, formatBaseUnits, formatNoteForDisplay, getQuote, isLegacyNote, mintToField, parseAmountToBaseUnits, parseSecretNote, prepareCircuitArtifacts, proveTransaction, quoteCpmm, resolveCircuitPathsFromBase, resolveNpmCdnCircuitBase, swapExtDataHash, swapOutputNote };
18094
19360
  //# sourceMappingURL=index.js.map
18095
19361
  //# sourceMappingURL=index.js.map