@@ -34,6 +34,7 @@ import {
3434 DISTRIBUTOR_PROGRAM_ID ,
3535 STREAMFLOW_TREASURY_PUBLIC_KEY ,
3636} from "../constants.js" ;
37+ import { MINIMUM_FEE_FALLBACK , resolveAirdropFeeLamportsUsingApi } from "../fees.js" ;
3738import MerkleDistributorIDL from "../descriptor/idl/merkle_distributor.json" ;
3839import type { MerkleDistributor as MerkleDistributorProgramType } from "../descriptor/merkle_distributor.js" ;
3940import { MerkleDistributor } from "../generated/accounts/index.js" ;
@@ -90,6 +91,8 @@ export default abstract class BaseDistributorClient {
9091
9192 public merkleDistributorProgram : Program < MerkleDistributorProgramType > ;
9293
94+ protected cluster : ICluster ;
95+
9396 public constructor ( {
9497 clusterUrl,
9598 cluster = ICluster . Mainnet ,
@@ -99,6 +102,7 @@ export default abstract class BaseDistributorClient {
99102 sendThrottler,
100103 } : IInitOptions ) {
101104 this . commitment = commitment ;
105+ this . cluster = cluster ;
102106 this . connection = new Connection ( clusterUrl , this . commitment ) ;
103107 this . programId = programId !== "" ? new PublicKey ( programId ) : new PublicKey ( DISTRIBUTOR_PROGRAM_ID [ cluster ] ) ;
104108 this . sendThrottler = sendThrottler ?? buildSendThrottler ( sendRate ) ;
@@ -360,12 +364,40 @@ export default abstract class BaseDistributorClient {
360364 ixs . push ( claimLocked ( accounts , this . programId ) ) ;
361365 }
362366
363- ixs . push (
364- this . prepareClaimFeeInstruction (
365- extParams . feePayer ?? extParams . invoker . publicKey ,
366- typeof _serviceTransfer === "bigint" ? _serviceTransfer : undefined ,
367- ) ,
368- ) ;
367+ // Determine fee: prefer service internal (if provided by service), else fetch params from API
368+ // and compute dynamically through resolver, else default minimum
369+ let feeLamports = typeof _serviceTransfer === "bigint" ? _serviceTransfer : undefined ;
370+ if ( ! feeLamports ) {
371+ try {
372+ const { mint : mintAccount } = await getMintAndProgram ( this . connection , distributor . mint ) ;
373+ // Backward-compatible: compute claimable amount if not provided by the caller
374+ // Prefer explicit field if present; otherwise default to unlocked + locked inputs
375+ const claimableAmountRaw = ( data as unknown as {
376+ // optional for legacy callers
377+ claimableAmount ?: BN | bigint | number | string ;
378+ } ) ?. claimableAmount ;
379+ // Default legacy fields to 0 when missing
380+ const unlockedRaw = ( data as unknown as { amountUnlocked ?: BN | number | string } ) ?. amountUnlocked ;
381+ const lockedRaw = ( data as unknown as { amountLocked ?: BN | number | string } ) ?. amountLocked ;
382+ const unlocked = unlockedRaw != null ? new BN ( unlockedRaw ) : new BN ( 0 ) ;
383+ const locked = lockedRaw != null ? new BN ( lockedRaw ) : new BN ( 0 ) ;
384+ const computedFallback = unlocked . add ( locked ) ;
385+ const claimableAmount =
386+ claimableAmountRaw != null
387+ ? BigInt ( claimableAmountRaw . toString ( ) )
388+ : BigInt ( computedFallback . toString ( ) ) ;
389+
390+ feeLamports = await resolveAirdropFeeLamportsUsingApi ( {
391+ distributorAddress : distributorPublicKey . toBase58 ( ) ,
392+ mintAccount,
393+ claimableAmount,
394+ cluster : this . cluster ,
395+ } ) ;
396+ } catch ( _ ) {
397+ feeLamports = MINIMUM_FEE_FALLBACK ;
398+ }
399+ }
400+ ixs . push ( this . prepareClaimFeeInstruction ( extParams . feePayer ?? extParams . invoker . publicKey , feeLamports ) ) ;
369401
370402 return ixs ;
371403 }
0 commit comments