Skip to content

Commit

Permalink
feat: marked swaps (#477)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Feb 1, 2024
1 parent 2027c13 commit 57ee9a5
Show file tree
Hide file tree
Showing 17 changed files with 407 additions and 13 deletions.
11 changes: 10 additions & 1 deletion lib/Boltz.ts
Expand Up @@ -23,6 +23,7 @@ import LndClient from './lightning/LndClient';
import ClnClient from './lightning/cln/ClnClient';
import MpayClient from './lightning/cln/MpayClient';
import NotificationProvider from './notifications/NotificationProvider';
import CountryCodes from './service/CountryCodes';
import Service from './service/Service';
import NodeSwitch from './swap/NodeSwitch';
import WalletManager, { Currency } from './wallet/WalletManager';
Expand All @@ -43,6 +44,7 @@ class Boltz {
private readonly notifications!: NotificationProvider;

private readonly api!: Api;
private readonly countryCodes: CountryCodes;
private readonly grpcServer!: GrpcServer;
private readonly prometheus: Prometheus;

Expand Down Expand Up @@ -152,7 +154,13 @@ class Boltz {
this.config.pairs,
);

this.api = new Api(this.logger, this.config.api, this.service);
this.countryCodes = new CountryCodes(this.logger, this.config.marking);
this.api = new Api(
this.logger,
this.config.api,
this.service,
this.countryCodes,
);
} catch (error) {
this.logger.error(`Could not start Boltz: ${formatError(error)}`);
// eslint-disable-next-line no-process-exit
Expand Down Expand Up @@ -206,6 +214,7 @@ class Boltz {

await this.grpcServer.listen();

await this.countryCodes.downloadRanges();
await this.api.init();

// Rescan chains after everything else was initialized to avoid race conditions
Expand Down
10 changes: 10 additions & 0 deletions lib/Config.ts
Expand Up @@ -11,6 +11,7 @@ import Errors from './consts/Errors';
import { PairConfig } from './consts/Types';
import { LndConfig } from './lightning/LndClient';
import { ClnConfig } from './lightning/cln/ClnClient';
import { MarkingsConfig } from './service/CountryCodes';
import { NodeSwitchConfig } from './swap/NodeSwitch';

type PostgresConfig = {
Expand Down Expand Up @@ -162,6 +163,8 @@ type ConfigType = {
prepayminerfee: boolean;
swapwitnessaddress: boolean;

marking: MarkingsConfig;

api: ApiConfig;
grpc: GrpcConfig;
rates: RatesConfig;
Expand Down Expand Up @@ -218,6 +221,13 @@ class Config {
prepayminerfee: false,
swapwitnessaddress: false,

marking: {
ipV4Ranges:
'https://cdn.jsdelivr.net/npm/@ip-location-db/asn-country/asn-country-ipv4-num.csv',
ipV6Ranges:
'https://cdn.jsdelivr.net/npm/@ip-location-db/asn-country/asn-country-ipv6-num.csv',
},

api: {
host: '127.0.0.1',
port: 9001,
Expand Down
18 changes: 13 additions & 5 deletions lib/api/Api.ts
Expand Up @@ -2,6 +2,7 @@ import cors from 'cors';
import express, { Application, NextFunction, Request, Response } from 'express';
import { ApiConfig } from '../Config';
import Logger from '../Logger';
import CountryCodes from '../service/CountryCodes';
import Service from '../service/Service';
import Controller from './Controller';
import { errorResponse } from './Utils';
Expand All @@ -12,13 +13,13 @@ class Api {
private readonly controller: Controller;

constructor(
private logger: Logger,
private config: ApiConfig,
private readonly logger: Logger,
private readonly config: ApiConfig,
service: Service,
countryCodes: CountryCodes,
) {
this.app = express();
this.controller = new Controller(logger, service);

this.app.set('trust proxy', 'loopback');
this.app.use(cors());
this.app.use(
express.json({
Expand All @@ -44,7 +45,14 @@ class Api {
},
);

new ApiV2(this.logger, service, this.controller).registerRoutes(this.app);
this.controller = new Controller(logger, service, countryCodes);

new ApiV2(
this.logger,
service,
this.controller,
countryCodes,
).registerRoutes(this.app);
this.registerRoutes(this.controller);
}

Expand Down
11 changes: 9 additions & 2 deletions lib/api/Controller.ts
Expand Up @@ -16,6 +16,7 @@ import ReverseSwapRepository from '../db/repositories/ReverseSwapRepository';
import SwapRepository from '../db/repositories/SwapRepository';
import LndClient from '../lightning/LndClient';
import ClnClient from '../lightning/cln/ClnClient';
import CountryCodes from '../service/CountryCodes';
import ServiceErrors from '../service/Errors';
import { SwapUpdate } from '../service/EventHandler';
import NodeInfo from '../service/NodeInfo';
Expand All @@ -26,6 +27,7 @@ import {
checkPreimageHashLength,
createdResponse,
errorResponse,
markSwap,
successResponse,
validateRequest,
} from './Utils';
Expand All @@ -39,8 +41,9 @@ class Controller {
private pendingSwapStreams = new Map<string, Response>();

constructor(
private logger: Logger,
private service: Service,
private readonly logger: Logger,
private readonly service: Service,
private readonly countryCodes: CountryCodes,
) {
this.service.eventHandler.on('swap.update', (id, message) => {
this.logger.debug(`Swap ${id} update: ${saneStringify(message)}`);
Expand Down Expand Up @@ -448,6 +451,8 @@ class Controller {
});
}

await markSwap(this.countryCodes, req.ip, response.id);

this.logger.verbose(`Created new Swap with id: ${response.id}`);
this.logger.silly(`Swap ${response.id}: ${stringify(response)}`);

Expand Down Expand Up @@ -503,6 +508,8 @@ class Controller {
version: SwapVersion.Legacy,
});

await markSwap(this.countryCodes, req.ip, response.id);

this.logger.verbose(`Created Reverse Swap with id: ${response.id}`);
this.logger.silly(`Reverse swap ${response.id}: ${stringify(response)}`);

Expand Down
14 changes: 14 additions & 0 deletions lib/api/Utils.ts
@@ -1,6 +1,8 @@
import { Request, Response } from 'express';
import Logger from '../Logger';
import { getHexBuffer } from '../Utils';
import MarkedSwapRepository from '../db/repositories/MarkedSwapRepository';
import CountryCodes from '../service/CountryCodes';
import ServiceErrors from '../service/Errors';
import Errors from './Errors';

Expand Down Expand Up @@ -129,3 +131,15 @@ export const checkPreimageHashLength = (preimageHash: Buffer) => {
throw `invalid preimage hash length: ${preimageHash.length}`;
}
};

export const markSwap = async (
countryCodes: CountryCodes,
ip: string,
swapId: string,
) => {
if (!countryCodes.isRelevantCountry(countryCodes.getCountryCode(ip))) {
return;
}

await MarkedSwapRepository.addMarkedSwap(swapId);
};
4 changes: 3 additions & 1 deletion lib/api/v2/ApiV2.ts
@@ -1,5 +1,6 @@
import { Application } from 'express';
import Logger from '../../Logger';
import CountryCodes from '../../service/CountryCodes';
import Service from '../../service/Service';
import Controller from '../Controller';
import { apiPrefix } from './Consts';
Expand All @@ -17,10 +18,11 @@ class ApiV2 {
private readonly logger: Logger,
service: Service,
controller: Controller,
countryCodes: CountryCodes,
) {
this.routers = [
new InfoRouter(this.logger, service),
new SwapRouter(this.logger, service, controller),
new SwapRouter(this.logger, service, controller, countryCodes),
new ChainRouter(this.logger, service),
new NodesRouter(this.logger, service),
new ReferralRouter(this.logger),
Expand Down
7 changes: 7 additions & 0 deletions lib/api/v2/routers/SwapRouter.ts
Expand Up @@ -3,12 +3,14 @@ import Logger from '../../../Logger';
import { getHexString, stringify } from '../../../Utils';
import { SwapVersion } from '../../../consts/Enums';
import RateProviderTaproot from '../../../rates/providers/RateProviderTaproot';
import CountryCodes from '../../../service/CountryCodes';
import Service from '../../../service/Service';
import Controller from '../../Controller';
import {
checkPreimageHashLength,
createdResponse,
errorResponse,
markSwap,
successResponse,
validateRequest,
} from '../../Utils';
Expand All @@ -19,6 +21,7 @@ class SwapRouter extends RouterBase {
logger: Logger,
private readonly service: Service,
private readonly controller: Controller,
private readonly countryCodes: CountryCodes,
) {
super(logger, 'swap');
}
Expand Down Expand Up @@ -664,6 +667,8 @@ class SwapRouter extends RouterBase {
SwapVersion.Taproot,
);

await markSwap(this.countryCodes, req.ip, response.id);

this.logger.verbose(`Created new Swap with id: ${response.id}`);
this.logger.silly(`Swap ${response.id}: ${stringify(response)}`);

Expand Down Expand Up @@ -754,6 +759,8 @@ class SwapRouter extends RouterBase {
version: SwapVersion.Taproot,
});

await markSwap(this.countryCodes, req.ip, response.id);

this.logger.verbose(`Created Reverse Swap with id: ${response.id}`);
this.logger.silly(`Reverse swap ${response.id}: ${stringify(response)}`);

Expand Down
5 changes: 3 additions & 2 deletions lib/db/Database.ts
Expand Up @@ -8,6 +8,7 @@ import ChainTip from './models/ChainTip';
import ChannelCreation from './models/ChannelCreation';
import DatabaseVersion from './models/DatabaseVersion';
import KeyProvider from './models/KeyProvider';
import MarkedSwap from './models/MarkedSwap';
import Pair from './models/Pair';
import PendingEthereumTransaction from './models/PendingEthereumTransaction';
import Referral from './models/Referral';
Expand Down Expand Up @@ -110,8 +111,7 @@ class Database {
]);

await Promise.all([Swap.sync(), ReverseSwap.sync()]);

await ChannelCreation.sync();
await Promise.all([ChannelCreation.sync(), MarkedSwap.sync()]);
};

public migrate = async (currencies: Map<string, Currency>): Promise<void> => {
Expand All @@ -128,6 +128,7 @@ class Database {
Swap.load(Database.sequelize);
ChainTip.load(Database.sequelize);
ReverseSwap.load(Database.sequelize);
MarkedSwap.load(Database.sequelize);
KeyProvider.load(Database.sequelize);
ChannelCreation.load(Database.sequelize);
DatabaseVersion.load(Database.sequelize);
Expand Down
30 changes: 30 additions & 0 deletions lib/db/models/MarkedSwap.ts
@@ -0,0 +1,30 @@
import { DataTypes, Model, Sequelize } from 'sequelize';

type SwapType = {
id: string;
};

class MarkedSwap extends Model implements SwapType {
public id!: string;

public createdAt!: Date;
public updatedAt!: Date;

public static load = (sequelize: Sequelize): void => {
MarkedSwap.init(
{
id: {
type: new DataTypes.STRING(255),
primaryKey: true,
allowNull: false,
},
},
{
sequelize,
tableName: 'markedSwaps',
},
);
};
}

export default MarkedSwap;
11 changes: 11 additions & 0 deletions lib/db/repositories/MarkedSwapRepository.ts
@@ -0,0 +1,11 @@
import MarkedSwap from '../models/MarkedSwap';

class MarkedSwapRepository {
public static addMarkedSwap = (id: string) => {
return MarkedSwap.create({
id,
});
};
}

export default MarkedSwapRepository;

0 comments on commit 57ee9a5

Please sign in to comment.