@hadron-fi/sdk 0.4.0 → 0.4.2

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.mjs CHANGED
@@ -1,3 +1,6 @@
1
+ // src/hadron.ts
2
+ import { TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3 } from "@solana/spl-token";
3
+
1
4
  // src/helpers/sol.ts
2
5
  import {
3
6
  SystemProgram
@@ -43,9 +46,38 @@ function createWsolAtaInstruction(user) {
43
46
  TOKEN_PROGRAM_ID
44
47
  );
45
48
  }
46
- function unwrapSolInstruction(user) {
49
+ function unwrapSolInstructions(user) {
47
50
  const ata = getAssociatedTokenAddressSync(NATIVE_MINT, user, false, TOKEN_PROGRAM_ID);
48
- return createCloseAccountInstruction(ata, user, user, [], TOKEN_PROGRAM_ID);
51
+ return [
52
+ createCloseAccountInstruction(ata, user, user, [], TOKEN_PROGRAM_ID),
53
+ createAssociatedTokenAccountIdempotentInstruction(
54
+ user,
55
+ ata,
56
+ user,
57
+ NATIVE_MINT,
58
+ TOKEN_PROGRAM_ID
59
+ )
60
+ ];
61
+ }
62
+ function buildFeeRecipientAtaIxs(payer, feeRecipient, mintX, mintY, tokenProgramX = TOKEN_PROGRAM_ID, tokenProgramY = TOKEN_PROGRAM_ID) {
63
+ const ataX = getAssociatedTokenAddressSync(mintX, feeRecipient, false, tokenProgramX);
64
+ const ataY = getAssociatedTokenAddressSync(mintY, feeRecipient, false, tokenProgramY);
65
+ return [
66
+ createAssociatedTokenAccountIdempotentInstruction(
67
+ payer,
68
+ ataX,
69
+ feeRecipient,
70
+ mintX,
71
+ tokenProgramX
72
+ ),
73
+ createAssociatedTokenAccountIdempotentInstruction(
74
+ payer,
75
+ ataY,
76
+ feeRecipient,
77
+ mintY,
78
+ tokenProgramY
79
+ )
80
+ ];
49
81
  }
50
82
 
51
83
  // src/constants/index.ts
@@ -99,7 +131,9 @@ var Discriminator = {
99
131
  SetPoolState: 21,
100
132
  AllocateCurvePrefabs: 22,
101
133
  SetQuotingAuthority: 23,
102
- RotateFeeAdmin: 24
134
+ RotateFeeAdmin: 24,
135
+ InitializePoolFeeConfig: 25,
136
+ UpdatePoolFeeConfig: 26
103
137
  };
104
138
  var POINT_DATA_SIZE = 21;
105
139
  var CURVE_UPDATE_OP_SIZE = 24;
@@ -163,6 +197,12 @@ function getCurveUpdatesAddress(seed, mintX, mintY, programId = HADRON_PROGRAM_I
163
197
  function getFeeConfigAddress(programId = HADRON_PROGRAM_ID) {
164
198
  return PublicKey3.findProgramAddressSync([FEE_CONFIG_SEED], programId);
165
199
  }
200
+ function getPoolFeeConfigAddress(configPda, programId = HADRON_PROGRAM_ID) {
201
+ return PublicKey3.findProgramAddressSync(
202
+ [FEE_CONFIG_SEED, configPda.toBuffer()],
203
+ programId
204
+ );
205
+ }
166
206
  function getSpreadConfigAddress(configPda, programId = HADRON_PROGRAM_ID) {
167
207
  return PublicKey3.findProgramAddressSync(
168
208
  [SPREAD_CONFIG_SEED, configPda.toBuffer()],
@@ -301,7 +341,9 @@ function decodeConfig(data) {
301
341
  offset += 1;
302
342
  const oracleMode = buf.readUInt8(offset);
303
343
  offset += 1;
304
- offset += 3;
344
+ const hasPoolFee = buf.readUInt8(offset) !== 0;
345
+ offset += 1;
346
+ offset += 2;
305
347
  const pendingAuthority = new PublicKey4(buf.subarray(offset, offset + 32));
306
348
  offset += 32;
307
349
  const nominationExpiry = buf.readBigUInt64LE(offset);
@@ -320,6 +362,7 @@ function decodeConfig(data) {
320
362
  spreadConfigInitialized,
321
363
  deltaStaleness,
322
364
  oracleMode,
365
+ hasPoolFee,
323
366
  pendingAuthority,
324
367
  nominationExpiry,
325
368
  tokenProgramX,
@@ -541,7 +584,7 @@ function buildInitialize(payer, params, programId = HADRON_PROGRAM_ID) {
541
584
  function buildAllocateCurvePrefabs(payer, params, programId = HADRON_PROGRAM_ID) {
542
585
  const maxPrefabSlots = params.maxPrefabSlots ?? DEFAULT_MAX_PREFAB_SLOTS;
543
586
  const maxCurvePoints = params.maxCurvePoints ?? DEFAULT_MAX_CURVE_POINTS;
544
- const data = Buffer.alloc(1 + 8 + 32 + 32 + 1 + 1);
587
+ const data = Buffer.alloc(1 + 8 + 32 + 32 + 1 + 1 + 32);
545
588
  let offset = 0;
546
589
  data.writeUInt8(Discriminator.AllocateCurvePrefabs, offset);
547
590
  offset += 1;
@@ -554,6 +597,8 @@ function buildAllocateCurvePrefabs(payer, params, programId = HADRON_PROGRAM_ID)
554
597
  data.writeUInt8(maxPrefabSlots, offset);
555
598
  offset += 1;
556
599
  data.writeUInt8(maxCurvePoints, offset);
600
+ offset += 1;
601
+ params.authority.toBuffer().copy(data, offset);
557
602
  const [curvePrefabsPda] = PublicKey5.findProgramAddressSync(
558
603
  [
559
604
  Buffer.from("hadron-curve-prefabs"),
@@ -653,7 +698,7 @@ import {
653
698
  TransactionInstruction as TransactionInstruction5
654
699
  } from "@solana/web3.js";
655
700
  import { getAssociatedTokenAddressSync as getAssociatedTokenAddressSync5 } from "@solana/spl-token";
656
- function buildSwapExactIn(user, poolAddresses, mintX, mintY, tokenProgramX, tokenProgramY, params, programId = HADRON_PROGRAM_ID, spreadConfigInitialized = false) {
701
+ function buildSwapExactIn(user, poolAddresses, mintX, mintY, tokenProgramX, tokenProgramY, params, programId = HADRON_PROGRAM_ID, spreadConfigInitialized = false, feeConfigOverride) {
657
702
  const data = Buffer.alloc(1 + 1 + 8 + 8 + 8);
658
703
  let offset = 0;
659
704
  data.writeUInt8(Discriminator.SwapExactIn, offset);
@@ -669,7 +714,7 @@ function buildSwapExactIn(user, poolAddresses, mintX, mintY, tokenProgramX, toke
669
714
  const userX = getAssociatedTokenAddressSync5(mintX, user, false, tokenProgramX);
670
715
  const userY = getAssociatedTokenAddressSync5(mintY, user, false, tokenProgramY);
671
716
  const [userSource, vaultSource, vaultDest, userDest] = params.isX ? [userX, poolAddresses.vaultX, poolAddresses.vaultY, userY] : [userY, poolAddresses.vaultY, poolAddresses.vaultX, userX];
672
- const [feeConfigPda] = getFeeConfigAddress(programId);
717
+ const feeConfigPda = feeConfigOverride ?? getFeeConfigAddress(programId)[0];
673
718
  const inputMint = params.isX ? mintX : mintY;
674
719
  const inputMintProgram = params.isX ? tokenProgramX : tokenProgramY;
675
720
  const feeRecipientAta = getAssociatedTokenAddressSync5(
@@ -1137,6 +1182,52 @@ function buildRotateFeeAdmin(feeAdmin, params, programId = HADRON_PROGRAM_ID) {
1137
1182
  data
1138
1183
  });
1139
1184
  }
1185
+ function buildInitializePoolFeeConfig(payer, feeAdmin, configPda, params, programId = HADRON_PROGRAM_ID) {
1186
+ const [poolFeeConfigPda] = getPoolFeeConfigAddress(configPda, programId);
1187
+ const [globalFeeConfigPda] = getFeeConfigAddress(programId);
1188
+ const data = Buffer.alloc(1 + 4 + 32 + 32);
1189
+ let offset = 0;
1190
+ data.writeUInt8(Discriminator.InitializePoolFeeConfig, offset);
1191
+ offset += 1;
1192
+ data.writeUInt32LE(params.feePpm, offset);
1193
+ offset += 4;
1194
+ params.feeAdmin.toBuffer().copy(data, offset);
1195
+ offset += 32;
1196
+ params.feeRecipient.toBuffer().copy(data, offset);
1197
+ return new TransactionInstruction11({
1198
+ programId,
1199
+ keys: [
1200
+ { pubkey: payer, isSigner: true, isWritable: true },
1201
+ { pubkey: feeAdmin, isSigner: true, isWritable: false },
1202
+ { pubkey: configPda, isSigner: false, isWritable: true },
1203
+ { pubkey: poolFeeConfigPda, isSigner: false, isWritable: true },
1204
+ { pubkey: globalFeeConfigPda, isSigner: false, isWritable: false },
1205
+ { pubkey: SystemProgram3.programId, isSigner: false, isWritable: false }
1206
+ ],
1207
+ data
1208
+ });
1209
+ }
1210
+ function buildUpdatePoolFeeConfig(feeAdmin, configPda, params, programId = HADRON_PROGRAM_ID) {
1211
+ const [poolFeeConfigPda] = getPoolFeeConfigAddress(configPda, programId);
1212
+ const data = Buffer.alloc(1 + 4 + 32);
1213
+ let offset = 0;
1214
+ data.writeUInt8(Discriminator.UpdatePoolFeeConfig, offset);
1215
+ offset += 1;
1216
+ data.writeUInt32LE(params.feePpm !== null ? params.feePpm : 4294967295, offset);
1217
+ offset += 4;
1218
+ if (params.feeRecipient) {
1219
+ params.feeRecipient.toBuffer().copy(data, offset);
1220
+ }
1221
+ return new TransactionInstruction11({
1222
+ programId,
1223
+ keys: [
1224
+ { pubkey: feeAdmin, isSigner: true, isWritable: false },
1225
+ { pubkey: configPda, isSigner: false, isWritable: false },
1226
+ { pubkey: poolFeeConfigPda, isSigner: false, isWritable: true }
1227
+ ],
1228
+ data
1229
+ });
1230
+ }
1140
1231
 
1141
1232
  // src/instructions/spreadConfig.ts
1142
1233
  import {
@@ -1216,7 +1307,7 @@ function buildUpdateDeltaStaleness(authority, configPda, params, programId = HAD
1216
1307
  data
1217
1308
  });
1218
1309
  }
1219
- function buildClosePool(authority, configPda, midpriceOraclePda, curveMetaPda, curvePrefabsPda, curveUpdatesPda, vaultX, vaultY, tokenProgramX, tokenProgramY, spreadConfigInitialized = false, programId = HADRON_PROGRAM_ID) {
1310
+ function buildClosePool(authority, configPda, midpriceOraclePda, curveMetaPda, curvePrefabsPda, curveUpdatesPda, vaultX, vaultY, tokenProgramX, tokenProgramY, spreadConfigInitialized = false, authorityAtaX, authorityAtaY, programId = HADRON_PROGRAM_ID) {
1220
1311
  const data = Buffer.alloc(1);
1221
1312
  data.writeUInt8(Discriminator.ClosePool, 0);
1222
1313
  const keys = [
@@ -1239,6 +1330,12 @@ function buildClosePool(authority, configPda, midpriceOraclePda, curveMetaPda, c
1239
1330
  isWritable: true
1240
1331
  });
1241
1332
  }
1333
+ if (authorityAtaX) {
1334
+ keys.push({ pubkey: authorityAtaX, isSigner: false, isWritable: true });
1335
+ }
1336
+ if (authorityAtaY) {
1337
+ keys.push({ pubkey: authorityAtaY, isSigner: false, isWritable: true });
1338
+ }
1242
1339
  return new TransactionInstruction13({ programId, keys, data });
1243
1340
  }
1244
1341
 
@@ -1340,7 +1437,8 @@ var Hadron = class _Hadron {
1340
1437
  mintX: params.mintX,
1341
1438
  mintY: params.mintY,
1342
1439
  maxPrefabSlots,
1343
- maxCurvePoints
1440
+ maxCurvePoints,
1441
+ authority: params.authority
1344
1442
  };
1345
1443
  const instructions = [];
1346
1444
  const size = curvePrefabsSize(maxPrefabSlots, maxCurvePoints);
@@ -1351,6 +1449,22 @@ var Hadron = class _Hadron {
1351
1449
  instructions.push(buildInitialize(payer, resolvedParams, programId));
1352
1450
  return { instructions, poolAddress, seed };
1353
1451
  }
1452
+ /**
1453
+ * Build idempotent create-ATA instructions for the fee recipient for both mints.
1454
+ *
1455
+ * These are no-ops on-chain if the ATAs already exist. Include them alongside
1456
+ * initialize or first deposit to ensure swaps don't fail due to missing fee ATAs.
1457
+ */
1458
+ static buildFeeRecipientAtaIxs(payer, feeRecipient, mintX, mintY, tokenProgramX, tokenProgramY) {
1459
+ return buildFeeRecipientAtaIxs(
1460
+ payer,
1461
+ feeRecipient,
1462
+ mintX,
1463
+ mintY,
1464
+ tokenProgramX ?? TOKEN_PROGRAM_ID3,
1465
+ tokenProgramY ?? TOKEN_PROGRAM_ID3
1466
+ );
1467
+ }
1354
1468
  /** Generate a random u64 seed. */
1355
1469
  static randomSeed() {
1356
1470
  const buf = new Uint8Array(8);
@@ -1683,7 +1797,7 @@ var Hadron = class _Hadron {
1683
1797
  return decoded.triggers;
1684
1798
  }
1685
1799
  /** Build close pool instruction. */
1686
- closePool(authority) {
1800
+ closePool(authority, authorityAtaX, authorityAtaY) {
1687
1801
  return buildClosePool(
1688
1802
  authority,
1689
1803
  this.poolAddress,
@@ -1696,6 +1810,8 @@ var Hadron = class _Hadron {
1696
1810
  this.config.tokenProgramX,
1697
1811
  this.config.tokenProgramY,
1698
1812
  this.config.spreadConfigInitialized,
1813
+ authorityAtaX,
1814
+ authorityAtaY,
1699
1815
  this.programId
1700
1816
  );
1701
1817
  }
@@ -1729,7 +1845,7 @@ var Hadron = class _Hadron {
1729
1845
  }
1730
1846
  ixs.push(this.withdraw(user, params));
1731
1847
  if (hasSol) {
1732
- ixs.push(unwrapSolInstruction(user));
1848
+ ixs.push(...unwrapSolInstructions(user));
1733
1849
  }
1734
1850
  return ixs;
1735
1851
  }
@@ -1750,7 +1866,7 @@ var Hadron = class _Hadron {
1750
1866
  }
1751
1867
  ixs.push(this.swap(user, params));
1752
1868
  if (isNativeMint(outputMint)) {
1753
- ixs.push(unwrapSolInstruction(user));
1869
+ ixs.push(...unwrapSolInstructions(user));
1754
1870
  }
1755
1871
  return ixs;
1756
1872
  }
@@ -2319,9 +2435,9 @@ var HadronOrderbook = class _HadronOrderbook {
2319
2435
  import {
2320
2436
  getAssociatedTokenAddressSync as getAssociatedTokenAddressSync6,
2321
2437
  createAssociatedTokenAccountInstruction,
2322
- TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3
2438
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4
2323
2439
  } from "@solana/spl-token";
2324
- async function getOrCreateAta(connection, mint, owner, payer, tokenProgram = TOKEN_PROGRAM_ID3, allowOwnerOffCurve = false) {
2440
+ async function getOrCreateAta(connection, mint, owner, payer, tokenProgram = TOKEN_PROGRAM_ID4, allowOwnerOffCurve = false) {
2325
2441
  const address = getAssociatedTokenAddressSync6(
2326
2442
  mint,
2327
2443
  owner,
@@ -2383,8 +2499,10 @@ export {
2383
2499
  buildApplyCurveUpdates,
2384
2500
  buildClosePool,
2385
2501
  buildDeposit,
2502
+ buildFeeRecipientAtaIxs,
2386
2503
  buildInitialize,
2387
2504
  buildInitializeFeeConfig,
2505
+ buildInitializePoolFeeConfig,
2388
2506
  buildInitializeSpreadConfig,
2389
2507
  buildNominateAuthority,
2390
2508
  buildRotateFeeAdmin,
@@ -2405,6 +2523,7 @@ export {
2405
2523
  buildUpdateFeeConfig,
2406
2524
  buildUpdateMidprice,
2407
2525
  buildUpdateMidpriceAndBaseSpread,
2526
+ buildUpdatePoolFeeConfig,
2408
2527
  buildUpdateSpreadConfig,
2409
2528
  buildWithdraw,
2410
2529
  createWsolAtaInstruction,
@@ -2426,6 +2545,7 @@ export {
2426
2545
  getFeeConfigAddress,
2427
2546
  getMidpriceOracleAddress,
2428
2547
  getOrCreateAta,
2548
+ getPoolFeeConfigAddress,
2429
2549
  getSpreadConfigAddress,
2430
2550
  isNativeMint,
2431
2551
  isSlotInitialized,
@@ -2433,7 +2553,7 @@ export {
2433
2553
  spreadBpsToQ32,
2434
2554
  spreadQ32ToBps,
2435
2555
  toQ32,
2436
- unwrapSolInstruction,
2556
+ unwrapSolInstructions,
2437
2557
  wrapSolInstructions
2438
2558
  };
2439
2559
  //# sourceMappingURL=index.mjs.map