Skip to content

Commit

Permalink
feat: custom fees for referrals
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Dec 22, 2024
1 parent a6d6008 commit 23f1bbd
Show file tree
Hide file tree
Showing 19 changed files with 853 additions and 281 deletions.
34 changes: 28 additions & 6 deletions lib/api/v2/routers/SwapRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Logger from '../../../Logger';
import { getHexString, stringify } from '../../../Utils';
import { SwapUpdateEvent, SwapVersion } from '../../../consts/Enums';
import ChainSwapRepository from '../../../db/repositories/ChainSwapRepository';
import ReferralRepository from '../../../db/repositories/ReferralRepository';
import SwapRepository from '../../../db/repositories/SwapRepository';
import RateProviderTaproot from '../../../rates/providers/RateProviderTaproot';
import CountryCodes from '../../../service/CountryCodes';
Expand Down Expand Up @@ -1654,13 +1655,17 @@ class SwapRouter extends RouterBase {
return router;
};

private getSubmarine = (_req: Request, res: Response) =>
private getSubmarine = async (req: Request, res: Response) => {
const referral = await this.getReferralFromHeader(req);
successResponse(
res,
RateProviderTaproot.serializePairs(
this.service.rateProvider.providers[SwapVersion.Taproot].submarinePairs,
this.service.rateProvider.providers[
SwapVersion.Taproot
].getSubmarinePairs(referral),
),
);
};

private createSubmarine = async (req: Request, res: Response) => {
const { to, from, invoice, webhook, pairHash, refundPublicKey } =
Expand Down Expand Up @@ -1816,13 +1821,17 @@ class SwapRouter extends RouterBase {
successResponse(res, {});
};

private getReverse = (_req: Request, res: Response) =>
private getReverse = async (req: Request, res: Response) => {
const referral = await this.getReferralFromHeader(req);
successResponse(
res,
RateProviderTaproot.serializePairs(
this.service.rateProvider.providers[SwapVersion.Taproot].reversePairs,
this.service.rateProvider.providers[
SwapVersion.Taproot
].getReversePairs(referral),
),
);
};

private createReverse = async (req: Request, res: Response) => {
const {
Expand Down Expand Up @@ -1960,13 +1969,17 @@ class SwapRouter extends RouterBase {
});
};

private getChain = (_req: Request, res: Response) =>
private getChain = async (req: Request, res: Response) => {
const referral = await this.getReferralFromHeader(req);
successResponse(
res,
RateProviderTaproot.serializePairs(
this.service.rateProvider.providers[SwapVersion.Taproot].chainPairs,
this.service.rateProvider.providers[SwapVersion.Taproot].getChainPairs(
referral,
),
),
);
};

// TODO: claim covenant
private createChain = async (req: Request, res: Response) => {
Expand Down Expand Up @@ -2247,6 +2260,15 @@ class SwapRouter extends RouterBase {

return res;
};

private getReferralFromHeader = async (req: Request) => {
const referral = req.header('referral');
if (referral === undefined) {
return null;
}

return ReferralRepository.getReferralById(referral);
};
}

export default SwapRouter;
28 changes: 27 additions & 1 deletion lib/db/Migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const decodeInvoice = (

// TODO: integration tests for actual migrations
class Migration {
private static latestSchemaVersion = 12;
private static latestSchemaVersion = 13;

private toBackFill: number[] = [];

Expand Down Expand Up @@ -574,6 +574,32 @@ class Migration {
break;
}

case 12: {
await this.sequelize
.getQueryInterface()
.addColumn(Referral.tableName, 'submarinePremium', {
type: new DataTypes.INTEGER(),
allowNull: true,
});

await this.sequelize
.getQueryInterface()
.addColumn(Referral.tableName, 'reversePremium', {
type: new DataTypes.INTEGER(),
allowNull: true,
});

await this.sequelize
.getQueryInterface()
.addColumn(Referral.tableName, 'chainPremium', {
type: new DataTypes.INTEGER(),
allowNull: true,
});

await this.finishMigration(versionRow.version, currencies);
break;
}

default:
throw `found unexpected database version ${versionRow.version}`;
}
Expand Down
25 changes: 25 additions & 0 deletions lib/db/models/Referral.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DataTypes, Model, Sequelize } from 'sequelize';
import { SwapType } from '../../consts/Enums';

type ReferralType = {
id: string;
Expand All @@ -8,6 +9,10 @@ type ReferralType = {

feeShare: number;
routingNode?: string;

submarinePremium?: number;
reversePremium?: number;
chainPremium?: number;
};

class Referral extends Model implements ReferralType {
Expand All @@ -19,6 +24,10 @@ class Referral extends Model implements ReferralType {
public feeShare!: number;
public routingNode?: string;

public submarinePremium?: number;
public reversePremium?: number;
public chainPremium?: number;

public static load = (sequelize: Sequelize): void => {
Referral.init(
{
Expand All @@ -43,6 +52,9 @@ class Referral extends Model implements ReferralType {
allowNull: true,
unique: true,
},
submarinePremium: { type: new DataTypes.INTEGER(), allowNull: true },
reversePremium: { type: new DataTypes.INTEGER(), allowNull: true },
chainPremium: { type: new DataTypes.INTEGER(), allowNull: true },
},
{
sequelize,
Expand All @@ -60,6 +72,19 @@ class Referral extends Model implements ReferralType {
},
);
};

public premiumForType = (type: SwapType) => {
switch (type) {
case SwapType.Submarine:
return this.submarinePremium;

case SwapType.ReverseSubmarine:
return this.reversePremium;

case SwapType.Chain:
return this.chainPremium;
}
};
}

export default Referral;
Expand Down
8 changes: 8 additions & 0 deletions lib/db/repositories/ReferralRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ ORDER BY year, month;
return Referral.findAll();
};

public static getReferralById = (id: string): Promise<Referral | null> => {
return Referral.findOne({
where: {
id,
},
});
};

public static getReferralByApiKey = (
apiKey: string,
): Promise<Referral | null> => {
Expand Down
22 changes: 20 additions & 2 deletions lib/rates/FeeProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
swapTypeToString,
} from '../consts/Enums';
import { PairConfig } from '../consts/Types';
import Referral from '../db/models/Referral';
import WalletLiquid from '../wallet/WalletLiquid';
import WalletManager from '../wallet/WalletManager';
import { Ethereum, Rsk } from '../wallet/ethereum/EvmNetworks';
Expand Down Expand Up @@ -132,6 +133,8 @@ class FeeProvider {
},
};

public static percentFeeDecimals = 2;

private static readonly defaultFee = 1;

// A map between the symbols of the pairs and their percentage fees
Expand All @@ -146,6 +149,16 @@ class FeeProvider {
private getFeeEstimation: (symbol: string) => Promise<Map<string, number>>,
) {}

public static addPremium = (fee: number, premium?: number): number => {
if (premium === null || premium === undefined) {
return fee;
}

return parseFloat(
(fee + premium / 100).toFixed(FeeProvider.percentFeeDecimals),
);
};

public init = (pairs: PairConfig[]): void => {
pairs.forEach((pair) => {
const pairId = getPairId(pair);
Expand Down Expand Up @@ -203,17 +216,20 @@ class FeeProvider {
orderSide: OrderSide,
type: SwapType,
feeType: PercentageFeeType = PercentageFeeType.Calculation,
referral: Referral | null,
): number => {
const percentages = this.percentageFees.get(pair);
if (percentages === undefined) {
return 0;
}

const percentageType = percentages[type];
const percentage =
const percentage = FeeProvider.addPremium(
typeof percentageType === 'number'
? percentageType
: percentageType[orderSide];
: percentageType[orderSide],
referral?.premiumForType(type),
);

return feeType === PercentageFeeType.Calculation
? percentage / 100
Expand All @@ -228,6 +244,7 @@ class FeeProvider {
amount: number,
type: SwapType,
feeType: BaseFeeType,
referral: Referral | null,
): {
baseFee: number;
percentageFee: number;
Expand All @@ -237,6 +254,7 @@ class FeeProvider {
orderSide,
type,
PercentageFeeType.Calculation,
referral,
);

if (percentageFee !== 0) {
Expand Down
4 changes: 4 additions & 0 deletions lib/rates/providers/RateProviderLegacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ class RateProviderLegacy extends RateProviderBase<PairTypeLegacy> {
OrderSide.BUY,
SwapType.Submarine,
PercentageFeeType.Display,
null,
),
percentage: this.feeProvider.getPercentageFee(
id,
OrderSide.BUY,
SwapType.ReverseSubmarine,
PercentageFeeType.Display,
null,
),
minerFees: {
baseAsset: emptyMinerFees,
Expand All @@ -98,12 +100,14 @@ class RateProviderLegacy extends RateProviderBase<PairTypeLegacy> {
OrderSide.BUY,
SwapType.Submarine,
PercentageFeeType.Display,
null,
),
percentage: this.feeProvider.getPercentageFee(
pairId,
OrderSide.BUY,
SwapType.ReverseSubmarine,
PercentageFeeType.Display,
null,
),
minerFees: {
baseAsset: this.feeProvider.minerFees.get(base)![SwapVersion.Legacy],
Expand Down
Loading

0 comments on commit 23f1bbd

Please sign in to comment.