@liquid-af/sdk 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/accounts/liquid.d.ts +2 -3
  2. package/dist/accounts/liquid.d.ts.map +1 -1
  3. package/dist/accounts/liquid.js +3 -4
  4. package/dist/accounts/liquid.js.map +1 -1
  5. package/dist/client.d.ts +4 -4
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +6 -6
  8. package/dist/client.js.map +1 -1
  9. package/dist/helpers/preview.d.ts.map +1 -1
  10. package/dist/helpers/preview.js +1 -1
  11. package/dist/helpers/preview.js.map +1 -1
  12. package/dist/idl/index.d.ts +1 -0
  13. package/dist/idl/index.d.ts.map +1 -1
  14. package/dist/idl/index.js +15 -4
  15. package/dist/idl/index.js.map +1 -1
  16. package/dist/idl/liquid.d.ts +0 -20
  17. package/dist/idl/liquid.d.ts.map +1 -1
  18. package/dist/idl/liquid.json +0 -20
  19. package/dist/idl/patch-idl.d.ts +10 -0
  20. package/dist/idl/patch-idl.d.ts.map +1 -0
  21. package/dist/idl/patch-idl.js +62 -0
  22. package/dist/idl/patch-idl.js.map +1 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/instructions/liquid.d.ts.map +1 -1
  28. package/dist/instructions/liquid.js +3 -3
  29. package/dist/instructions/liquid.js.map +1 -1
  30. package/dist/instructions/program-cache.d.ts.map +1 -1
  31. package/dist/instructions/program-cache.js +10 -6
  32. package/dist/instructions/program-cache.js.map +1 -1
  33. package/dist/pda/index.d.ts.map +1 -1
  34. package/dist/pda/index.js +1 -1
  35. package/dist/pda/index.js.map +1 -1
  36. package/dist/pda/liquid.d.ts +2 -3
  37. package/dist/pda/liquid.d.ts.map +1 -1
  38. package/dist/pda/liquid.js +3 -4
  39. package/dist/pda/liquid.js.map +1 -1
  40. package/package.json +4 -4
  41. package/src/accounts/liquid-fees.ts +2 -2
  42. package/src/accounts/liquid-state.ts +7 -7
  43. package/src/accounts/liquid-swap.ts +4 -4
  44. package/src/accounts/liquid.ts +7 -10
  45. package/src/client.ts +33 -36
  46. package/src/config.ts +10 -10
  47. package/src/errors.ts +6 -6
  48. package/src/events/parser.ts +5 -5
  49. package/src/helpers/preview.ts +31 -32
  50. package/src/helpers/user.ts +1 -1
  51. package/src/idl/index.ts +31 -8
  52. package/src/idl/liquid.json +0 -20
  53. package/src/idl/liquid.ts +0 -20
  54. package/src/idl/patch-idl.ts +80 -0
  55. package/src/index.ts +1 -0
  56. package/src/instructions/liquid-fees.ts +14 -14
  57. package/src/instructions/liquid-state.ts +4 -4
  58. package/src/instructions/liquid-swap.ts +18 -18
  59. package/src/instructions/liquid.ts +47 -50
  60. package/src/instructions/program-cache.ts +18 -9
  61. package/src/math/amm.ts +3 -3
  62. package/src/math/bonding-curve.ts +6 -6
  63. package/src/math/fees.ts +9 -9
  64. package/src/math/tiered-fees.ts +5 -5
  65. package/src/oracle.ts +3 -3
  66. package/src/pda/index.ts +27 -28
  67. package/src/pda/liquid-fees.ts +6 -6
  68. package/src/pda/liquid-state.ts +13 -13
  69. package/src/pda/liquid-swap.ts +16 -16
  70. package/src/pda/liquid.ts +17 -19
  71. package/src/provider.ts +2 -2
  72. package/src/transaction/builder.ts +4 -4
  73. package/src/transaction/send.ts +4 -4
  74. package/src/types.ts +2 -2
@@ -160,7 +160,7 @@ export interface SwapPrefetchedState {
160
160
  export function calculateBuyCurvePreview(
161
161
  amountInQuote: BN,
162
162
  state: CurvePreviewState,
163
- options?: CurvePreviewOptions
163
+ options?: CurvePreviewOptions,
164
164
  ): BuyCurvePreview {
165
165
  const { globalConfig, bondingCurve } = state;
166
166
 
@@ -176,7 +176,7 @@ export function calculateBuyCurvePreview(
176
176
  bondingCurve,
177
177
  feeConfig,
178
178
  options?.hasCreatorRef ?? false,
179
- options?.hasTraderRef ?? false
179
+ options?.hasTraderRef ?? false,
180
180
  );
181
181
 
182
182
  const priceBefore = bondingCurve.virtualQuoteReserves
@@ -222,7 +222,7 @@ export function calculateBuyCurvePreview(
222
222
  export function calculateSellCurvePreview(
223
223
  amountInTokens: BN,
224
224
  state: CurvePreviewState,
225
- options?: CurvePreviewOptions
225
+ options?: CurvePreviewOptions,
226
226
  ): SellCurvePreview {
227
227
  const { globalConfig, bondingCurve } = state;
228
228
 
@@ -238,7 +238,7 @@ export function calculateSellCurvePreview(
238
238
  bondingCurve,
239
239
  feeConfig,
240
240
  options?.hasCreatorRef ?? false,
241
- options?.hasTraderRef ?? false
241
+ options?.hasTraderRef ?? false,
242
242
  );
243
243
 
244
244
  const priceBefore = bondingCurve.virtualQuoteReserves
@@ -280,7 +280,7 @@ export function calculateSellCurvePreview(
280
280
  */
281
281
  export function calculateSwapBuyPreview(
282
282
  amountOut: BN,
283
- state: SwapPreviewState
283
+ state: SwapPreviewState,
284
284
  ): SwapPreview {
285
285
  const { ammConfig, baseVaultBalance, quoteVaultBalance } = state;
286
286
 
@@ -292,7 +292,7 @@ export function calculateSwapBuyPreview(
292
292
  lpFeeRate: ammConfig.lpFeeRate,
293
293
  creatorFeeRate: ammConfig.creatorFeeRate,
294
294
  protocolFeeRate: ammConfig.protocolFeeRate,
295
- }
295
+ },
296
296
  );
297
297
 
298
298
  const priceBefore = quoteVaultBalance
@@ -331,7 +331,7 @@ export function calculateSwapBuyPreview(
331
331
  */
332
332
  export function calculateSwapSellPreview(
333
333
  amountIn: BN,
334
- state: SwapPreviewState
334
+ state: SwapPreviewState,
335
335
  ): SwapPreview {
336
336
  const { ammConfig, baseVaultBalance, quoteVaultBalance } = state;
337
337
 
@@ -343,7 +343,7 @@ export function calculateSwapSellPreview(
343
343
  lpFeeRate: ammConfig.lpFeeRate,
344
344
  creatorFeeRate: ammConfig.creatorFeeRate,
345
345
  protocolFeeRate: ammConfig.protocolFeeRate,
346
- }
346
+ },
347
347
  );
348
348
 
349
349
  const priceBefore = quoteVaultBalance
@@ -383,7 +383,7 @@ export function calculateSwapSellPreview(
383
383
  */
384
384
  async function fetchCurveGlobalConfig(
385
385
  connection: Connection,
386
- config: LiquidConfig
386
+ config: LiquidConfig,
387
387
  ): Promise<
388
388
  CurvePreviewState["globalConfig"] & { initialVirtualReserveUsd: BN }
389
389
  > {
@@ -414,7 +414,7 @@ async function resolveNativeCurve(
414
414
  connection: Connection,
415
415
  mint: PublicKey,
416
416
  options: NativeCurveOptions,
417
- config: LiquidConfig
417
+ config: LiquidConfig,
418
418
  ): Promise<CurvePreviewState> {
419
419
  const pre = options.prefetched;
420
420
 
@@ -427,7 +427,7 @@ async function resolveNativeCurve(
427
427
 
428
428
  const virtualSolReserves = calculateVirtualSolReserves(
429
429
  BigInt(globalConfig.initialVirtualReserveUsd!.toString()),
430
- BigInt(options.solPriceUsd.toString())
430
+ BigInt(options.solPriceUsd.toString()),
431
431
  );
432
432
 
433
433
  const bondingCurve = pre?.bondingCurve ?? {
@@ -456,7 +456,7 @@ async function resolveStableCurve(
456
456
  connection: Connection,
457
457
  mint: PublicKey,
458
458
  options: StableCurveOptions,
459
- config: LiquidConfig
459
+ config: LiquidConfig,
460
460
  ): Promise<CurvePreviewState> {
461
461
  const pre = options.prefetched;
462
462
 
@@ -467,9 +467,8 @@ async function resolveStableCurve(
467
467
  : fetchStableBondingCurve(
468
468
  connection,
469
469
  mint,
470
- options.quoteMint,
471
- config
472
- ),
470
+ config,
471
+ ),
473
472
  ]);
474
473
 
475
474
  const bondingCurve = pre?.bondingCurve ?? {
@@ -495,21 +494,21 @@ function resolveCurveState(
495
494
  connection: Connection,
496
495
  mint: PublicKey,
497
496
  config: LiquidConfig,
498
- options: CurveAsyncOptions
497
+ options: CurveAsyncOptions,
499
498
  ): Promise<CurvePreviewState> {
500
499
  if (options.quoteMint) {
501
500
  return resolveStableCurve(
502
501
  connection,
503
502
  mint,
504
503
  options as StableCurveOptions,
505
- config
504
+ config,
506
505
  );
507
506
  }
508
507
  return resolveNativeCurve(
509
508
  connection,
510
509
  mint,
511
510
  options as NativeCurveOptions,
512
- config
511
+ config,
513
512
  );
514
513
  }
515
514
 
@@ -548,7 +547,7 @@ export async function previewBuyOnCurve(
548
547
  mint: PublicKey,
549
548
  amountInQuote: BN,
550
549
  config: LiquidConfig,
551
- options: CurveAsyncOptions
550
+ options: CurveAsyncOptions,
552
551
  ): Promise<BuyCurvePreview> {
553
552
  const state = await resolveCurveState(connection, mint, config, options);
554
553
  return calculateBuyCurvePreview(amountInQuote, state, {
@@ -584,7 +583,7 @@ export async function previewSellOnCurve(
584
583
  mint: PublicKey,
585
584
  amountInTokens: BN,
586
585
  config: LiquidConfig,
587
- options: CurveAsyncOptions
586
+ options: CurveAsyncOptions,
588
587
  ): Promise<SellCurvePreview> {
589
588
  const state = await resolveCurveState(connection, mint, config, options);
590
589
  return calculateSellCurvePreview(amountInTokens, state, {
@@ -617,7 +616,7 @@ export async function previewSwapSell(
617
616
  quoteMint: PublicKey,
618
617
  amountIn: BN,
619
618
  config: LiquidConfig,
620
- options?: { prefetched?: SwapPrefetchedState; solPriceUsd?: BN }
619
+ options?: { prefetched?: SwapPrefetchedState; solPriceUsd?: BN },
621
620
  ): Promise<SwapPreview> {
622
621
  const pre = options?.prefetched;
623
622
 
@@ -638,13 +637,13 @@ export async function previewSwapSell(
638
637
  connection,
639
638
  poolState.baseVault,
640
639
  "confirmed",
641
- poolState.baseTokenProgram
640
+ poolState.baseTokenProgram,
642
641
  ),
643
642
  getAccount(
644
643
  connection,
645
644
  poolState.quoteVault,
646
645
  "confirmed",
647
- poolState.quoteTokenProgram
646
+ poolState.quoteTokenProgram,
648
647
  ),
649
648
  ]);
650
649
  baseVaultBalance = new BN(baseVaultAccount.amount.toString());
@@ -668,7 +667,7 @@ export async function previewSwapSell(
668
667
  connection,
669
668
  poolState.baseMint,
670
669
  "confirmed",
671
- poolState.baseTokenProgram
670
+ poolState.baseTokenProgram,
672
671
  );
673
672
  const baseTotalSupply = new BN(baseMintAccount.supply.toString());
674
673
 
@@ -680,13 +679,13 @@ export async function previewSwapSell(
680
679
  baseTotalSupply,
681
680
  options.solPriceUsd,
682
681
  poolState.quoteMint,
683
- tiers
682
+ tiers,
684
683
  );
685
684
 
686
685
  feeRates = { lpFeeRate, protocolFeeRate, creatorFeeRate };
687
686
  } else {
688
687
  throw new Error(
689
- "Either prefetched.feeRates or solPriceUsd must be provided for tiered fee calculations"
688
+ "Either prefetched.feeRates or solPriceUsd must be provided for tiered fee calculations",
690
689
  );
691
690
  }
692
691
 
@@ -721,7 +720,7 @@ export async function previewSwapBuy(
721
720
  quoteMint: PublicKey,
722
721
  amountOut: BN,
723
722
  config: LiquidConfig,
724
- options?: { prefetched?: SwapPrefetchedState; solPriceUsd?: BN }
723
+ options?: { prefetched?: SwapPrefetchedState; solPriceUsd?: BN },
725
724
  ): Promise<SwapPreview> {
726
725
  const pre = options?.prefetched;
727
726
 
@@ -742,13 +741,13 @@ export async function previewSwapBuy(
742
741
  connection,
743
742
  poolState.baseVault,
744
743
  "confirmed",
745
- poolState.baseTokenProgram
744
+ poolState.baseTokenProgram,
746
745
  ),
747
746
  getAccount(
748
747
  connection,
749
748
  poolState.quoteVault,
750
749
  "confirmed",
751
- poolState.quoteTokenProgram
750
+ poolState.quoteTokenProgram,
752
751
  ),
753
752
  ]);
754
753
  baseVaultBalance = new BN(baseVaultAccount.amount.toString());
@@ -772,7 +771,7 @@ export async function previewSwapBuy(
772
771
  connection,
773
772
  poolState.baseMint,
774
773
  "confirmed",
775
- poolState.baseTokenProgram
774
+ poolState.baseTokenProgram,
776
775
  );
777
776
  const baseTotalSupply = new BN(baseMintAccount.supply.toString());
778
777
 
@@ -784,13 +783,13 @@ export async function previewSwapBuy(
784
783
  baseTotalSupply,
785
784
  options.solPriceUsd,
786
785
  poolState.quoteMint,
787
- tiers
786
+ tiers,
788
787
  );
789
788
 
790
789
  feeRates = { lpFeeRate, protocolFeeRate, creatorFeeRate };
791
790
  } else {
792
791
  throw new Error(
793
- "Either prefetched.feeRates or solPriceUsd must be provided for tiered fee calculations"
792
+ "Either prefetched.feeRates or solPriceUsd must be provided for tiered fee calculations",
794
793
  );
795
794
  }
796
795
 
@@ -11,7 +11,7 @@ import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
11
11
  */
12
12
  export const resolveTokenProgram = async (
13
13
  connection: Connection,
14
- mint: PublicKey
14
+ mint: PublicKey,
15
15
  ): Promise<PublicKey> => {
16
16
  const account = await connection.getAccountInfo(mint);
17
17
  if (!account) {
package/src/idl/index.ts CHANGED
@@ -2,6 +2,7 @@ import { Program } from "@coral-xyz/anchor";
2
2
  import { Connection } from "@solana/web3.js";
3
3
  import type { LiquidConfig } from "../config.js";
4
4
  import { createReadonlyProvider } from "../provider.js";
5
+ import { patchIdl } from "./patch-idl.js";
5
6
 
6
7
  import liquidIdl from "./liquid.json" with { type: "json" };
7
8
  import liquidSwapIdl from "./liquid_swap.json" with { type: "json" };
@@ -9,6 +10,7 @@ import liquidFeesIdl from "./liquid_fees.json" with { type: "json" };
9
10
  import liquidStateIdl from "./liquid_state.json" with { type: "json" };
10
11
 
11
12
  export { liquidIdl, liquidSwapIdl, liquidFeesIdl, liquidStateIdl };
13
+ export { patchIdl } from "./patch-idl.js";
12
14
 
13
15
  // Re-export Anchor-generated IDL types
14
16
  export type { Liquid } from "./liquid.js";
@@ -31,10 +33,13 @@ import type { LiquidState } from "./liquid_state.js";
31
33
  */
32
34
  export function getLiquidProgram(
33
35
  connection: Connection,
34
- config?: LiquidConfig
36
+ config?: LiquidConfig,
35
37
  ): Program<Liquid> {
36
38
  const idl = config
37
- ? { ...liquidIdl, address: config.liquidProgramId.toBase58() }
39
+ ? patchIdl(
40
+ { ...liquidIdl, address: config.liquidProgramId.toBase58() },
41
+ config,
42
+ )
38
43
  : liquidIdl;
39
44
  return new Program(idl as Liquid, createReadonlyProvider(connection));
40
45
  }
@@ -49,10 +54,16 @@ export function getLiquidProgram(
49
54
  */
50
55
  export function getLiquidSwapProgram(
51
56
  connection: Connection,
52
- config?: LiquidConfig
57
+ config?: LiquidConfig,
53
58
  ): Program<LiquidSwap> {
54
59
  const idl = config
55
- ? { ...liquidSwapIdl, address: config.liquidSwapProgramId.toBase58() }
60
+ ? patchIdl(
61
+ {
62
+ ...liquidSwapIdl,
63
+ address: config.liquidSwapProgramId.toBase58(),
64
+ },
65
+ config,
66
+ )
56
67
  : liquidSwapIdl;
57
68
  return new Program(idl as LiquidSwap, createReadonlyProvider(connection));
58
69
  }
@@ -67,10 +78,16 @@ export function getLiquidSwapProgram(
67
78
  */
68
79
  export function getLiquidFeesProgram(
69
80
  connection: Connection,
70
- config?: LiquidConfig
81
+ config?: LiquidConfig,
71
82
  ): Program<LiquidFees> {
72
83
  const idl = config
73
- ? { ...liquidFeesIdl, address: config.liquidFeesProgramId.toBase58() }
84
+ ? patchIdl(
85
+ {
86
+ ...liquidFeesIdl,
87
+ address: config.liquidFeesProgramId.toBase58(),
88
+ },
89
+ config,
90
+ )
74
91
  : liquidFeesIdl;
75
92
  return new Program(idl as LiquidFees, createReadonlyProvider(connection));
76
93
  }
@@ -85,10 +102,16 @@ export function getLiquidFeesProgram(
85
102
  */
86
103
  export function getLiquidStateProgram(
87
104
  connection: Connection,
88
- config?: LiquidConfig
105
+ config?: LiquidConfig,
89
106
  ): Program<LiquidState> {
90
107
  const idl = config
91
- ? { ...liquidStateIdl, address: config.liquidStateProgramId.toBase58() }
108
+ ? patchIdl(
109
+ {
110
+ ...liquidStateIdl,
111
+ address: config.liquidStateProgramId.toBase58(),
112
+ },
113
+ config,
114
+ )
92
115
  : liquidStateIdl;
93
116
  return new Program(idl as LiquidState, createReadonlyProvider(connection));
94
117
  }
@@ -1108,10 +1108,6 @@
1108
1108
  {
1109
1109
  "kind": "account",
1110
1110
  "path": "mint"
1111
- },
1112
- {
1113
- "kind": "account",
1114
- "path": "quote_mint"
1115
1111
  }
1116
1112
  ]
1117
1113
  }
@@ -2851,10 +2847,6 @@
2851
2847
  {
2852
2848
  "kind": "account",
2853
2849
  "path": "mint"
2854
- },
2855
- {
2856
- "kind": "account",
2857
- "path": "quote_mint"
2858
2850
  }
2859
2851
  ]
2860
2852
  }
@@ -3814,10 +3806,6 @@
3814
3806
  {
3815
3807
  "kind": "account",
3816
3808
  "path": "mint"
3817
- },
3818
- {
3819
- "kind": "account",
3820
- "path": "quote_mint"
3821
3809
  }
3822
3810
  ]
3823
3811
  }
@@ -5609,10 +5597,6 @@
5609
5597
  {
5610
5598
  "kind": "account",
5611
5599
  "path": "mint"
5612
- },
5613
- {
5614
- "kind": "account",
5615
- "path": "quote_mint"
5616
5600
  }
5617
5601
  ]
5618
5602
  }
@@ -7076,10 +7060,6 @@
7076
7060
  {
7077
7061
  "kind": "account",
7078
7062
  "path": "mint"
7079
- },
7080
- {
7081
- "kind": "account",
7082
- "path": "quote_mint"
7083
7063
  }
7084
7064
  ]
7085
7065
  }
package/src/idl/liquid.ts CHANGED
@@ -1114,10 +1114,6 @@ export type Liquid = {
1114
1114
  {
1115
1115
  "kind": "account",
1116
1116
  "path": "mint"
1117
- },
1118
- {
1119
- "kind": "account",
1120
- "path": "quoteMint"
1121
1117
  }
1122
1118
  ]
1123
1119
  }
@@ -2857,10 +2853,6 @@ export type Liquid = {
2857
2853
  {
2858
2854
  "kind": "account",
2859
2855
  "path": "mint"
2860
- },
2861
- {
2862
- "kind": "account",
2863
- "path": "quoteMint"
2864
2856
  }
2865
2857
  ]
2866
2858
  }
@@ -3820,10 +3812,6 @@ export type Liquid = {
3820
3812
  {
3821
3813
  "kind": "account",
3822
3814
  "path": "mint"
3823
- },
3824
- {
3825
- "kind": "account",
3826
- "path": "quoteMint"
3827
3815
  }
3828
3816
  ]
3829
3817
  }
@@ -5615,10 +5603,6 @@ export type Liquid = {
5615
5603
  {
5616
5604
  "kind": "account",
5617
5605
  "path": "mint"
5618
- },
5619
- {
5620
- "kind": "account",
5621
- "path": "quoteMint"
5622
5606
  }
5623
5607
  ]
5624
5608
  }
@@ -7082,10 +7066,6 @@ export type Liquid = {
7082
7066
  {
7083
7067
  "kind": "account",
7084
7068
  "path": "mint"
7085
- },
7086
- {
7087
- "kind": "account",
7088
- "path": "quoteMint"
7089
7069
  }
7090
7070
  ]
7091
7071
  }
@@ -0,0 +1,80 @@
1
+ import { PublicKey } from "@solana/web3.js";
2
+ import { MAINNET_CONFIG, type LiquidConfig } from "../config.js";
3
+
4
+ interface ProgramReplacement {
5
+ mainnetAddress: string;
6
+ mainnetBytes: number[];
7
+ targetAddress: string;
8
+ targetBytes: number[];
9
+ }
10
+
11
+ function buildReplacementMap(config: LiquidConfig): ProgramReplacement[] {
12
+ const pairs: [PublicKey, PublicKey][] = [
13
+ [MAINNET_CONFIG.liquidProgramId, config.liquidProgramId],
14
+ [MAINNET_CONFIG.liquidSwapProgramId, config.liquidSwapProgramId],
15
+ [MAINNET_CONFIG.liquidFeesProgramId, config.liquidFeesProgramId],
16
+ [MAINNET_CONFIG.liquidStateProgramId, config.liquidStateProgramId],
17
+ ];
18
+ return pairs
19
+ .filter(([mainnet, target]) => !mainnet.equals(target))
20
+ .map(([mainnet, target]) => ({
21
+ mainnetAddress: mainnet.toBase58(),
22
+ mainnetBytes: Array.from(mainnet.toBytes()),
23
+ targetAddress: target.toBase58(),
24
+ targetBytes: Array.from(target.toBytes()),
25
+ }));
26
+ }
27
+
28
+ function deepPatch(
29
+ node: unknown,
30
+ stringMap: Map<string, string>,
31
+ byteMap: Map<string, number[]>,
32
+ ): unknown {
33
+ if (node === null || node === undefined) return node;
34
+ if (typeof node !== "object") return node;
35
+
36
+ if (Array.isArray(node)) {
37
+ if (node.length === 32 && typeof node[0] === "number") {
38
+ const key = JSON.stringify(node);
39
+ const replacement = byteMap.get(key);
40
+ if (replacement) return replacement;
41
+ }
42
+ return node.map((item) => deepPatch(item, stringMap, byteMap));
43
+ }
44
+
45
+ const result: Record<string, unknown> = {};
46
+ for (const [key, value] of Object.entries(
47
+ node as Record<string, unknown>,
48
+ )) {
49
+ if (key === "address" && typeof value === "string") {
50
+ result[key] = stringMap.get(value) ?? value;
51
+ } else {
52
+ result[key] = deepPatch(value, stringMap, byteMap);
53
+ }
54
+ }
55
+ return result;
56
+ }
57
+
58
+ /**
59
+ * Deep-patches an Anchor IDL JSON object, replacing all embedded mainnet
60
+ * program addresses (both string and byte-array forms) with the addresses
61
+ * from the provided config.
62
+ *
63
+ * Returns the original IDL unchanged if config matches mainnet.
64
+ */
65
+ export function patchIdl<T extends Record<string, unknown>>(
66
+ idl: T,
67
+ config: LiquidConfig,
68
+ ): T {
69
+ const replacements = buildReplacementMap(config);
70
+ if (replacements.length === 0) return idl;
71
+
72
+ const stringMap = new Map<string, string>();
73
+ const byteMap = new Map<string, number[]>();
74
+ for (const r of replacements) {
75
+ stringMap.set(r.mainnetAddress, r.targetAddress);
76
+ byteMap.set(JSON.stringify(r.mainnetBytes), r.targetBytes);
77
+ }
78
+
79
+ return deepPatch(idl, stringMap, byteMap) as T;
80
+ }
package/src/index.ts CHANGED
@@ -100,4 +100,5 @@ export {
100
100
  liquidSwapIdl,
101
101
  liquidFeesIdl,
102
102
  liquidStateIdl,
103
+ patchIdl,
103
104
  } from "./idl/index.js";
@@ -27,7 +27,7 @@ export interface BuildUpdateFeeConfigParams {
27
27
  * @returns Transaction instruction
28
28
  */
29
29
  export function buildUpdateFeeConfig(
30
- params: BuildUpdateFeeConfigParams
30
+ params: BuildUpdateFeeConfigParams,
31
31
  ): Promise<TransactionInstruction> {
32
32
  const {
33
33
  authority,
@@ -50,16 +50,16 @@ export function buildUpdateFeeConfig(
50
50
  if (recipients && quoteMint) {
51
51
  const [feeConfig] = getFeeConfigPDA(
52
52
  tokenMint,
53
- config.liquidFeesProgramId
53
+ config.liquidFeesProgramId,
54
54
  );
55
55
  const [feeVault] = getFeeVaultPDA(
56
56
  feeConfig,
57
- config.liquidFeesProgramId
57
+ config.liquidFeesProgramId,
58
58
  );
59
59
  tokenFeeVault = getAssociatedTokenAddressSync(
60
60
  quoteMint,
61
61
  feeVault,
62
- true
62
+ true,
63
63
  );
64
64
  }
65
65
 
@@ -92,7 +92,7 @@ export interface BuildRevokeFeeConfigParams {
92
92
  * @returns Transaction instruction
93
93
  */
94
94
  export function buildRevokeFeeConfig(
95
- params: BuildRevokeFeeConfigParams
95
+ params: BuildRevokeFeeConfigParams,
96
96
  ): Promise<TransactionInstruction> {
97
97
  const { authority, tokenMint, quoteMint, config } = params;
98
98
  const program = getCachedFeesProgram(config);
@@ -103,7 +103,7 @@ export function buildRevokeFeeConfig(
103
103
  const tokenFeeVault = getAssociatedTokenAddressSync(
104
104
  quoteMint,
105
105
  feeVault,
106
- true
106
+ true,
107
107
  );
108
108
 
109
109
  return program.methods
@@ -133,7 +133,7 @@ export interface BuildDistributeFeesParams {
133
133
  * @returns Transaction instruction
134
134
  */
135
135
  export function buildDistributeFees(
136
- params: BuildDistributeFeesParams
136
+ params: BuildDistributeFeesParams,
137
137
  ): Promise<TransactionInstruction> {
138
138
  const { payer, tokenMint, recipientVaults, config } = params;
139
139
  const program = getCachedFeesProgram(config);
@@ -149,7 +149,7 @@ export function buildDistributeFees(
149
149
  pubkey: vault,
150
150
  isSigner: false,
151
151
  isWritable: true,
152
- }))
152
+ })),
153
153
  )
154
154
  .instruction();
155
155
  }
@@ -177,7 +177,7 @@ export interface BuildDistributeTokenFeesParams {
177
177
  * @returns Transaction instruction
178
178
  */
179
179
  export function buildDistributeTokenFees(
180
- params: BuildDistributeTokenFeesParams
180
+ params: BuildDistributeTokenFeesParams,
181
181
  ): Promise<TransactionInstruction> {
182
182
  const { payer, tokenMint, quoteMint, recipientVaultPairs, config } = params;
183
183
  const program = getCachedFeesProgram(config);
@@ -213,7 +213,7 @@ export interface BuildClaimFeesParams {
213
213
  * @returns Transaction instruction
214
214
  */
215
215
  export function buildClaimFees(
216
- params: BuildClaimFeesParams
216
+ params: BuildClaimFeesParams,
217
217
  ): Promise<TransactionInstruction> {
218
218
  const { recipient, tokenMint, config } = params;
219
219
  const program = getCachedFeesProgram(config);
@@ -244,7 +244,7 @@ export interface BuildClaimTokenFeesParams {
244
244
  * @returns Transaction instruction
245
245
  */
246
246
  export function buildClaimTokenFees(
247
- params: BuildClaimTokenFeesParams
247
+ params: BuildClaimTokenFeesParams,
248
248
  ): Promise<TransactionInstruction> {
249
249
  const { recipient, tokenMint, quoteMint, config } = params;
250
250
  const program = getCachedFeesProgram(config);
@@ -273,19 +273,19 @@ export function deriveRecipientVaultPairs(
273
273
  tokenMint: PublicKey,
274
274
  recipients: PublicKey[],
275
275
  quoteMint: PublicKey,
276
- config: LiquidConfig
276
+ config: LiquidConfig,
277
277
  ): RecipientVaultPair[] {
278
278
  const [feeConfig] = getFeeConfigPDA(tokenMint, config.liquidFeesProgramId);
279
279
  return recipients.map((recipient) => {
280
280
  const [vaultPda] = getRecipientVaultPDA(
281
281
  feeConfig,
282
282
  recipient,
283
- config.liquidFeesProgramId
283
+ config.liquidFeesProgramId,
284
284
  );
285
285
  const vaultAta = getAssociatedTokenAddressSync(
286
286
  quoteMint,
287
287
  vaultPda,
288
- true
288
+ true,
289
289
  );
290
290
  return { vaultPda, vaultAta };
291
291
  });
@@ -16,7 +16,7 @@ export interface BuildInitializeUserParams {
16
16
  * @returns Transaction instruction
17
17
  */
18
18
  export function buildInitializeUser(
19
- params: BuildInitializeUserParams
19
+ params: BuildInitializeUserParams,
20
20
  ): Promise<TransactionInstruction> {
21
21
  const { user, config } = params;
22
22
  const program = getCachedStateProgram(config);
@@ -38,7 +38,7 @@ export interface BuildSetReferrerParams {
38
38
  * @returns Transaction instruction
39
39
  */
40
40
  export function buildSetReferrer(
41
- params: BuildSetReferrerParams
41
+ params: BuildSetReferrerParams,
42
42
  ): Promise<TransactionInstruction> {
43
43
  const { user, referrer, config } = params;
44
44
  const program = getCachedStateProgram(config);
@@ -62,7 +62,7 @@ export interface BuildSetCashbackModeParams {
62
62
  * @returns Transaction instruction
63
63
  */
64
64
  export function buildSetCashbackMode(
65
- params: BuildSetCashbackModeParams
65
+ params: BuildSetCashbackModeParams,
66
66
  ): Promise<TransactionInstruction> {
67
67
  const { user, config } = params;
68
68
  const program = getCachedStateProgram(config);
@@ -84,7 +84,7 @@ export interface BuildRedeemDealParams {
84
84
  * @returns Transaction instruction
85
85
  */
86
86
  export function buildRedeemDeal(
87
- params: BuildRedeemDealParams
87
+ params: BuildRedeemDealParams,
88
88
  ): Promise<TransactionInstruction> {
89
89
  const { user, dealOwner, config } = params;
90
90
  const program = getCachedStateProgram(config);