From 623aff9a643d3b2fddb71ab869c2bdd2e03f3487 Mon Sep 17 00:00:00 2001 From: maybeast <78227110+maybeast@users.noreply.github.com> Date: Tue, 4 Mar 2025 23:30:23 -0600 Subject: [PATCH] fixup! feat: directional premiums for referrals --- lib/db/models/Referral.ts | 6 +-- lib/db/repositories/ReferralRepository.ts | 50 ++++++++++++------- lib/rates/FeeProvider.ts | 4 +- lib/rates/providers/RateProviderTaproot.ts | 13 ++--- .../providers/RateProviderTaproot.spec.ts | 17 ++----- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/lib/db/models/Referral.ts b/lib/db/models/Referral.ts index c6133f12..e666e4ce 100644 --- a/lib/db/models/Referral.ts +++ b/lib/db/models/Referral.ts @@ -142,14 +142,14 @@ class Referral extends Model implements ReferralType { public premium = ( pair: string, type: SwapType, - orderSide?: OrderSide, + orderSide: OrderSide, ): number | undefined => { const premium = this.config?.pairs?.[pair]?.premiums?.[type] || this.config?.premiums?.[type]; - if (type === SwapType.Chain && orderSide !== undefined) { - return premium ? premium[orderSide] : undefined; + if (type === SwapType.Chain) { + return premium !== undefined ? premium[orderSide] : undefined; } return premium as number | undefined; diff --git a/lib/db/repositories/ReferralRepository.ts b/lib/db/repositories/ReferralRepository.ts index e743beed..fcaad6e2 100644 --- a/lib/db/repositories/ReferralRepository.ts +++ b/lib/db/repositories/ReferralRepository.ts @@ -43,6 +43,13 @@ class ReferralRepository { ORDER BY year, month; `; + private static readonly maxPremiumPercentage = 100; + private static readonly minPremiumPercentage = -100; + private static readonly minExpiration = 120; + private static readonly maxExpiration = 60 * 60 * 24; + private static readonly minRoutingFee = 0; + private static readonly maxRoutingFee = 0.005; + public static addReferral = async ( referral: ReferralType, ): Promise => { @@ -117,16 +124,11 @@ class ReferralRepository { private static sanityCheckConfig = ( config: ReferralConfig | null | undefined, ) => { - const MAX_PREMIUM_PERCENTAGE = 100; - const MIN_PREMIUM_PERCENTAGE = -100; - const MIN_EXPIRATION = 120; - const MAX_EXPIRATION = 60 * 60 * 24; - const MAX_ROUTING_FEE = 0.005; - const sanityCheckPairConfig = (cfg: ReferralPairConfig) => { if ( - cfg.maxRoutingFee && - (cfg.maxRoutingFee < 0 || cfg.maxRoutingFee > MAX_ROUTING_FEE) + cfg.maxRoutingFee !== undefined && + (cfg.maxRoutingFee < ReferralRepository.minRoutingFee || + cfg.maxRoutingFee > ReferralRepository.maxRoutingFee) ) { throw 'maxRoutingFee out of range'; } @@ -146,19 +148,27 @@ class ReferralRepository { } if ( - directionalPremium[OrderSide.BUY] < MIN_PREMIUM_PERCENTAGE || - directionalPremium[OrderSide.BUY] > MAX_PREMIUM_PERCENTAGE || - directionalPremium[OrderSide.SELL] < MIN_PREMIUM_PERCENTAGE || - directionalPremium[OrderSide.SELL] > MAX_PREMIUM_PERCENTAGE + [ + directionalPremium[OrderSide.BUY], + directionalPremium[OrderSide.SELL], + ].some( + (p) => + p < ReferralRepository.minPremiumPercentage || + p > ReferralRepository.maxPremiumPercentage, + ) + ) { + throw 'premium out of range'; + } + } else { + if (typeof premium !== 'number') { + throw 'premium must be a number'; + } + if ( + premium < ReferralRepository.minPremiumPercentage || + premium > ReferralRepository.maxPremiumPercentage ) { throw 'premium out of range'; } - } else if ( - typeof premium === 'number' && - (premium < MIN_PREMIUM_PERCENTAGE || - premium > MAX_PREMIUM_PERCENTAGE) - ) { - throw 'premium out of range'; } } } @@ -166,7 +176,9 @@ class ReferralRepository { if (cfg.expirations) { if ( Object.values(cfg.expirations).some( - (e) => e < MIN_EXPIRATION || e > MAX_EXPIRATION, + (e) => + e < ReferralRepository.minExpiration || + e > ReferralRepository.maxExpiration, ) ) { throw 'expiration out of range'; diff --git a/lib/rates/FeeProvider.ts b/lib/rates/FeeProvider.ts index c9107800..b7422c66 100644 --- a/lib/rates/FeeProvider.ts +++ b/lib/rates/FeeProvider.ts @@ -242,9 +242,7 @@ class FeeProvider { typeof percentageType === 'number' ? percentageType : percentageType[orderSide], - type === SwapType.Chain - ? referral?.premium(pair, type, orderSide) - : referral?.premium(pair, type), + referral?.premium(pair, type, orderSide), ); return feeType === PercentageFeeType.Calculation diff --git a/lib/rates/providers/RateProviderTaproot.ts b/lib/rates/providers/RateProviderTaproot.ts index 20922c4b..fe56213e 100644 --- a/lib/rates/providers/RateProviderTaproot.ts +++ b/lib/rates/providers/RateProviderTaproot.ts @@ -522,14 +522,11 @@ class RateProviderTaproot extends RateProviderBase { const { quote } = splitPairId(getConfigPairId(pairIds)); - const premium = - type === SwapType.Chain - ? referral?.premiumForPairs( - pairIds, - type, - to === quote ? OrderSide.SELL : OrderSide.BUY, - ) - : referral?.premiumForPairs(pairIds, type); + const premium = referral?.premiumForPairs( + pairIds, + type, + to === quote ? OrderSide.SELL : OrderSide.BUY, + ); const limits = referral?.limitsForPairs(pairIds, type); const result = { diff --git a/test/unit/rates/providers/RateProviderTaproot.spec.ts b/test/unit/rates/providers/RateProviderTaproot.spec.ts index ac0965d6..756cfb19 100644 --- a/test/unit/rates/providers/RateProviderTaproot.spec.ts +++ b/test/unit/rates/providers/RateProviderTaproot.spec.ts @@ -140,18 +140,11 @@ describe('RateProviderTaproot', () => { getPairs.call(provider, referral).get(from)!.get(to)!.fees.percentage, ).toEqual(expectedFee); - if (type === SwapType.Chain) { - expect(referral.premiumForPairs).toHaveBeenCalledWith( - expect.arrayContaining(['L-BTC/BTC', 'BTC/L-BTC']), - type, - expect.any(Number), - ); - } else { - expect(referral.premiumForPairs).toHaveBeenCalledWith( - expect.arrayContaining(['L-BTC/BTC', 'BTC/L-BTC']), - type, - ); - } + expect(referral.premiumForPairs).toHaveBeenCalledWith( + expect.arrayContaining(['L-BTC/BTC', 'BTC/L-BTC']), + type, + expect.any(Number), + ); expect( getPairs.call(provider).get(from)!.get(to)!.fees.percentage,