Skip to content

Commit

Permalink
feat: use lowball for emitting unconfirmed transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Apr 18, 2024
1 parent c3f6aaa commit 9621376
Show file tree
Hide file tree
Showing 25 changed files with 646 additions and 94 deletions.
52 changes: 40 additions & 12 deletions lib/Boltz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import { formatError, getVersion } from './Utils';
import VersionCheck from './VersionCheck';
import Api from './api/Api';
import BackupScheduler from './backup/BackupScheduler';
import ChainClient from './chain/ChainClient';
import ElementsClient from './chain/ElementsClient';
import ChainClient, {
BlockChainInfoScanned,
IChainClient,
} from './chain/ChainClient';
import ElementsWrapper from './chain/ElementsWrapper';
import { CurrencyType } from './consts/Enums';
import { NetworkInfo } from './consts/Types';
import Database from './db/Database';
import ChainTip from './db/models/ChainTip';
import ChainTipRepository from './db/repositories/ChainTipRepository';
Expand Down Expand Up @@ -281,7 +285,38 @@ class Boltz {
}
};

private connectChainClient = async (client: ChainClient) => {
private connectChainClient = async (client: IChainClient) => {
const formatChainInfo = (
networkInfo: (NetworkInfo & { lowball?: NetworkInfo }) | undefined,
blockchainInfo:
| (BlockChainInfoScanned & {
lowball?: BlockChainInfoScanned;
})
| undefined,
) => {
if (networkInfo === undefined || blockchainInfo === undefined) {
return undefined;
}

const res: any = {
version: networkInfo.version,
protocolversion: networkInfo.protocolversion,
connections: networkInfo.connections,
blocks: blockchainInfo.blocks,
bestblockhash: blockchainInfo.bestblockhash,
verificationprogress: blockchainInfo.verificationprogress,
};

if (networkInfo.lowball && blockchainInfo.lowball) {
res.lowball = formatChainInfo(
networkInfo.lowball,
blockchainInfo.lowball,
);
}

return res;
};

const service = `${client.symbol} chain`;

try {
Expand All @@ -292,14 +327,7 @@ class Boltz {

VersionCheck.checkChainClientVersion(client.symbol, networkInfo.version);

this.logStatus(service, {
version: networkInfo.version,
protocolversion: networkInfo.protocolversion,
connections: networkInfo.connections,
blocks: blockchainInfo.blocks,
bestblockhash: blockchainInfo.bestblockhash,
verificationprogress: blockchainInfo.verificationprogress,
});
this.logStatus(service, formatChainInfo(networkInfo, blockchainInfo));
} catch (error) {
this.logCouldNotConnect(service, error);
}
Expand Down Expand Up @@ -435,7 +463,7 @@ class Boltz {
type: CurrencyType.Liquid,
symbol: symbol,
network: LiquidNetworks[network],
chainClient: new ElementsClient(this.logger, chain),
chainClient: new ElementsWrapper(this.logger, chain),
limits: {
...this.config.liquid,
},
Expand Down
9 changes: 8 additions & 1 deletion lib/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ type ChainConfig = {
mempoolSpace?: string;
};

type LiquidChainConfig = ChainConfig & {
lowball?: ChainConfig;
};

type PreferredWallet = 'lnd' | 'core' | undefined;

type BaseCurrencyConfig = {
Expand Down Expand Up @@ -181,7 +185,9 @@ type ConfigType = {
pairs: PairConfig[];
currencies: CurrencyConfig[];

liquid?: BaseCurrencyConfig;
liquid?: Omit<BaseCurrencyConfig, 'chain'> & {
chain: LiquidChainConfig;
};

rsk?: RskConfig;
ethereum: EthereumConfig;
Expand Down Expand Up @@ -515,6 +521,7 @@ export {
PostgresConfig,
CurrencyConfig,
PreferredWallet,
LiquidChainConfig,
BaseCurrencyConfig,
NotificationConfig,
EthProviderServiceConfig,
Expand Down
4 changes: 2 additions & 2 deletions lib/Core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import {
getHexString,
reverseBuffer,
} from './Utils';
import ChainClient from './chain/ChainClient';
import { IChainClient } from './chain/ChainClient';
import { CurrencyType, SwapVersion } from './consts/Enums';
import { liquidSymbol } from './consts/LiquidTypes';
import Swap from './db/models/Swap';
Expand Down Expand Up @@ -284,7 +284,7 @@ export const constructRefundTransaction = (
};

export const calculateTransactionFee = async (
chainClient: ChainClient,
chainClient: IChainClient,
transaction: Transaction | LiquidTransaction,
) => {
return chainClient.symbol !== liquidSymbol
Expand Down
4 changes: 2 additions & 2 deletions lib/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import os from 'os';
import path from 'path';
import packageJson from '../package.json';
import commitHash from './Version';
import ChainClient from './chain/ChainClient';
import { IChainClient } from './chain/ChainClient';
import { etherDecimals } from './consts/Consts';
import { OrderSide, SwapVersion } from './consts/Enums';

Expand Down Expand Up @@ -553,7 +553,7 @@ export const getUnixTime = (): number => {
* Calculates the miner fee of a transaction on a UTXO based chain
*/
export const calculateUtxoTransactionFee = async (
chainClient: ChainClient,
chainClient: IChainClient,
transaction: Transaction,
): Promise<number> => {
let fee = 0n;
Expand Down
2 changes: 1 addition & 1 deletion lib/api/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import CountryCodes from '../service/CountryCodes';
import ServiceErrors from '../service/Errors';
import Errors from './Errors';

type ApiArgument = {
export type ApiArgument = {
name: string;
type: 'string' | 'number' | 'boolean' | 'object';
hex?: boolean;
Expand Down
68 changes: 55 additions & 13 deletions lib/chain/ChainClient.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Transaction } from 'bitcoinjs-lib';
import { Transaction as LiquidTransaction } from 'liquidjs-lib';
import { Transaction as LiquidTransaction } from 'liquidjs-lib/src/transaction';
import BaseClient from '../BaseClient';
import { ChainConfig } from '../Config';
import Logger from '../Logger';
import { formatError, getHexString } from '../Utils';
import { ClientStatus, CurrencyType } from '../consts/Enums';
import TypedEventEmitter from '../consts/TypedEventEmitter';
import {
Block,
BlockVerbose,
Expand All @@ -26,21 +27,64 @@ enum AddressType {
Taproot = 'bech32m',
}

class ChainClient extends BaseClient<{
type BlockChainInfoScanned = BlockchainInfo & {
scannedBlocks: number;
};

type ChainClientEvents<T extends Transaction | LiquidTransaction> = {
'status.changed': ClientStatus;
block: number;
transaction: {
transaction: Transaction | LiquidTransaction;
transaction: T;
confirmed: boolean;
};
}> {
};

interface IChainClient<
T extends Transaction | LiquidTransaction = Transaction | LiquidTransaction,
> extends TypedEventEmitter<ChainClientEvents<T>> {
get symbol(): string;
get currencyType(): CurrencyType;

connect(): Promise<void>;

rescanChain(startHeight: number): Promise<void>;

addInputFilter(inputHash: Buffer): void;
addOutputFilter(outputScript: Buffer): void;
removeOutputFilter(outputScript: Buffer): void;
removeInputFilter(inputHash: Buffer): void;

getBlockchainInfo(): Promise<BlockChainInfoScanned>;
getNetworkInfo(): Promise<NetworkInfo>;

sendRawTransaction(transactionHex: string): Promise<string>;
getRawTransaction(transactionId: string): Promise<string>;
getRawTransactionVerbose(transactionId: string): Promise<RawTransaction>;

estimateFee(confTarget?: number): Promise<number>;

listUnspent(minimalConfirmations?: number): Promise<UnspentUtxo[]>;
getNewAddress(type: AddressType): Promise<string>;
sendToAddress(
address: string,
amount: number,
satPerVbyte?: number,
subtractFeeFromAmount?: boolean,
): Promise<string>;
}

class ChainClient<T extends Transaction | LiquidTransaction = Transaction>
extends BaseClient<ChainClientEvents<T>>
implements IChainClient<T>
{
public static readonly serviceName = 'Core';
public static readonly decimals = 100000000;

public currencyType: CurrencyType = CurrencyType.BitcoinLike;

protected client: RpcClient;
protected zmqClient: ZmqClient;
protected zmqClient: ZmqClient<T>;
protected feeFloor = 2;

private readonly mempoolSpace?: MempoolSpace;
Expand Down Expand Up @@ -139,11 +183,7 @@ class ChainClient extends BaseClient<{
return this.client.request<NetworkInfo>('getnetworkinfo');
};

public getBlockchainInfo = async (): Promise<
BlockchainInfo & {
scannedBlocks: number;
}
> => {
public getBlockchainInfo = async () => {
const blockchainInfo =
await this.client.request<BlockchainInfo>('getblockchaininfo');

Expand Down Expand Up @@ -254,8 +294,10 @@ class ChainClient extends BaseClient<{
]);
};

public listUnspent = (minconf = 0): Promise<UnspentUtxo[]> => {
return this.client.request<UnspentUtxo[]>('listunspent', [minconf]);
public listUnspent = (minimalConfirmations = 0): Promise<UnspentUtxo[]> => {
return this.client.request<UnspentUtxo[]>('listunspent', [
minimalConfirmations,
]);
};

public generate = async (blocks: number): Promise<string[]> => {
Expand Down Expand Up @@ -341,4 +383,4 @@ class ChainClient extends BaseClient<{
}

export default ChainClient;
export { AddressType };
export { AddressType, BlockChainInfoScanned, ChainClientEvents, IChainClient };
24 changes: 20 additions & 4 deletions lib/chain/ElementsClient.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Transaction } from 'liquidjs-lib';
import { ChainConfig } from '../Config';
import Logger from '../Logger';
import { CurrencyType } from '../consts/Enums';
Expand All @@ -6,16 +7,31 @@ import {
LiquidBalances,
liquidSymbol,
} from '../consts/LiquidTypes';
import ChainClient, { AddressType } from './ChainClient';
import ChainClient, { AddressType, IChainClient } from './ChainClient';

enum LiquidAddressType {
Blech32 = 'blech32',
}

class ElementsClient extends ChainClient {
interface IElementsClient extends IChainClient<Transaction> {
getAddressInfo(address: string): Promise<AddressInfo>;

getBalances(): Promise<LiquidBalances>;
getNewAddress(type?: AddressType | LiquidAddressType): Promise<string>;
dumpBlindingKey(address: string): Promise<string>;
}

class ElementsClient
extends ChainClient<Transaction>
implements IElementsClient
{
public static readonly symbol = liquidSymbol;

constructor(logger: Logger, config: ChainConfig) {
constructor(
logger: Logger,
config: ChainConfig,
public readonly isLowball = false,
) {
super(logger, config, ElementsClient.symbol);
this.currencyType = CurrencyType.Liquid;
this.feeFloor = 0.11;
Expand Down Expand Up @@ -79,4 +95,4 @@ class ElementsClient extends ChainClient {
}

export default ElementsClient;
export { LiquidAddressType };
export { LiquidAddressType, IElementsClient };
Loading

0 comments on commit 9621376

Please sign in to comment.