Skip to content

Commit

Permalink
feat: organize dlc handler related errors, models and constants
Browse files Browse the repository at this point in the history
  • Loading branch information
Polybius93 committed Dec 6, 2024
1 parent 926327d commit 8b619e2
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 213 deletions.
7 changes: 7 additions & 0 deletions src/constants/dlc-handler.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const DLCHandlers = {
KEYPAIR: 'keypair',
LEATHER: 'leather',
UNISAT_FORDEFI: 'unisat/fordefi',
LEDGER: 'ledger',
DFNS: 'dfns',
} as const;
70 changes: 13 additions & 57 deletions src/dlc-handlers/abstract-dlc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,68 +19,24 @@ import {
createWithdrawTransaction,
} from '../functions/bitcoin/psbt-functions.js';
import { PaymentInformation } from '../models/bitcoin-models.js';
import {
DLCHandlerType,
FundingPaymentType,
PaymentType,
TransactionType,
} from '../models/dlc-handler.models.js';
import {
AddressNotFoundError,
InsufficientFundsError,
InvalidPaymentTypeError,
PaymentNotSetError,
} from '../models/errors/dlc-handler.errors.models.js';
import { RawVault } from '../models/ethereum-models.js';

export type DLCHandlerType = 'browser' | 'ledger' | 'dfns';
export type FundingPaymentType = 'wpkh' | 'tr';
export type PaymentType = 'funding' | 'multisig';
export type TransactionType = 'funding' | 'deposit' | 'withdraw';

export class DLCHandlerError extends Error {
constructor(message: string) {
super(message);
this.name = 'DLCHandlerError';
}
}

export class PaymentNotSetError extends DLCHandlerError {
constructor(
message: string = 'Payment information not initialized. Make sure to create payments before attempting to access them.'
) {
super(message);
this.name = 'PaymentNotSetError';
}
}

export class AddressNotFoundError extends DLCHandlerError {
constructor(paymentType: PaymentType) {
super(`Address not found for ${paymentType} payment`);
this.name = 'AddressNotFoundError';
}
}

export class InvalidPaymentTypeError extends DLCHandlerError {
constructor(paymentType: PaymentType) {
super(`Invalid payment type: ${paymentType}`);
this.name = 'InvalidPaymentTypeError';
}
}

export class InvalidTransactionTypeError extends DLCHandlerError {
constructor(transactionType: TransactionType) {
super(`Invalid transaction type: ${transactionType}`);
this.name = 'InvalidTransactionTypeError';
}
}

export class InsufficientFundsError extends DLCHandlerError {
constructor(available: bigint, required: bigint) {
super(`Insufficient funds: have ${available}, need ${required}`);
this.name = 'InsufficientFundsError';
}
}

export class IncompatibleTransactionArgument extends DLCHandlerError {
constructor() {
super('Incompatible transaction argument');
this.name = 'IncompatibleTransactionArgument';
}
}

export abstract class AbstractDLCHandler {
abstract readonly _dlcHandlerType: DLCHandlerType;
protected fundingPaymentType: FundingPaymentType;
protected abstract _payment?: PaymentInformation;
protected _payment?: PaymentInformation;
protected readonly bitcoinNetwork: Network;
protected readonly bitcoinBlockchainAPI: string;
protected readonly bitcoinBlockchainFeeRecommendationAPI: string;
Expand Down
74 changes: 23 additions & 51 deletions src/dlc-handlers/dfns-dlc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,17 @@ import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
import { Transaction } from '@scure/btc-signer';
import { Network } from 'bitcoinjs-lib';

import { PaymentInformation } from '../models/bitcoin-models.js';
import { FundingPaymentType, TransactionType } from '../models/dlc-handler.models.js';
import {
AbstractDLCHandler,
DLCHandlerError,
FundingPaymentType,
DFNSWalletIDNotSetError,
PaymentNotSetError,
TransactionType,
} from './abstract-dlc-handler.js';

export class DFNSWalletIDNotSetError extends DLCHandlerError {
constructor(
message: string = 'DFNS Wallet ID not set. Make sure to initialize the wallet before attempting to access it.'
) {
super(message);
this.name = 'DFNSWalletIDNotSetError';
}
}

export class TaprootDerivedPublicKeyNotSet extends DLCHandlerError {
constructor(
message: string = 'Taproot Derived Public Key not set. Make sure to initialize the wallet before attempting to access it.'
) {
super(message);
this.name = 'TaprootDerivedPublicKeyNotSet';
}
}

export class SignatureGenerationFailed extends DLCHandlerError {
constructor(
message: string = 'Signature generation failed. Make sure to initialize the wallet before attempting to access it.'
) {
super(message);
this.name = 'SignatureGenerationFailed';
}
}
SignatureGenerationFailed,
TaprootDerivedPublicKeyNotSet,
} from '../models/errors/dlc-handler.errors.models.js';
import { AbstractDLCHandler } from './abstract-dlc-handler.js';

export class DFNSDLCHandler extends AbstractDLCHandler {
readonly _dlcHandlerType = 'dfns' as const;
protected _payment?: PaymentInformation;
private readonly dfnsDelegatedAPIClient: DfnsDelegatedApiClient;
private _taprootDerivedPublicKey?: string;
private _dfnsWalletID?: string;
Expand All @@ -70,6 +42,21 @@ export class DFNSDLCHandler extends AbstractDLCHandler {
});
}

set dfnsWalletID(dfnsWalletID: string) {
this._dfnsWalletID = dfnsWalletID;
}

get dfnsWalletID(): string {
if (!this._dfnsWalletID) {
throw new DFNSWalletIDNotSetError();
}
return this._dfnsWalletID;
}

set taprootDerivedPublicKey(taprootDerivedPublicKey: string) {
this._taprootDerivedPublicKey = taprootDerivedPublicKey;
}

async getWallets(): Promise<ListWalletsResponse> {
try {
return await this.dfnsDelegatedAPIClient.wallets.listWallets();
Expand All @@ -90,27 +77,12 @@ export class DFNSDLCHandler extends AbstractDLCHandler {
}
}

set dfnsWalletID(dfnsWalletID: string) {
this._dfnsWalletID = dfnsWalletID;
}

get dfnsWalletID(): string {
if (!this._dfnsWalletID) {
throw new DFNSWalletIDNotSetError();
}
return this._dfnsWalletID;
}

set taprootDerivedPublicKey(taprootDerivedPublicKey: string) {
this._taprootDerivedPublicKey = taprootDerivedPublicKey;
}

getUserTaprootPublicKey(tweaked: boolean = false): string {
if (!tweaked) {
if (!this._taprootDerivedPublicKey) {
throw new TaprootDerivedPublicKeyNotSet();
}
return this.taprootDerivedPublicKey;
return this._taprootDerivedPublicKey;
}

if (!this.payment) {
Expand All @@ -124,7 +96,7 @@ export class DFNSDLCHandler extends AbstractDLCHandler {
if (!this._taprootDerivedPublicKey) {
throw new TaprootDerivedPublicKeyNotSet();
}
return this.taprootDerivedPublicKey;
return this._taprootDerivedPublicKey;
}

async signPSBT(transaction: Transaction, transactionType: TransactionType): Promise<Transaction> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@ import {
deriveUnhardenedKeyPairFromRootPrivateKey,
getInputIndicesByScript,
} from '../functions/bitcoin/bitcoin-functions.js';
import { PaymentInformation } from '../models/bitcoin-models.js';
import { FundingPaymentType, PaymentType, TransactionType } from '../models/dlc-handler.models.js';
import {
AbstractDLCHandler,
FundingPaymentType,
InvalidTransactionTypeError,
PaymentNotSetError,
PaymentType,
TransactionType,
} from './abstract-dlc-handler.js';
} from '../models/errors/dlc-handler.errors.models.js';
import { AbstractDLCHandler } from './abstract-dlc-handler.js';

export class PrivateKeyDLCHandler extends AbstractDLCHandler {
readonly _dlcHandlerType = 'browser' as const;
protected _payment?: PaymentInformation;
export class KeyPairDLCHandler extends AbstractDLCHandler {
readonly _dlcHandlerType = 'keypair' as const;
private fundingDerivedKeyPair: BIP32Interface;
private taprootDerivedKeyPair: BIP32Interface;

Expand Down
13 changes: 4 additions & 9 deletions src/dlc-handlers/leather-dlc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
import { Transaction } from '@scure/btc-signer';
import { Network } from 'bitcoinjs-lib';

import { PaymentInformation } from '../models/bitcoin-models.js';
import {
AbstractDLCHandler,
FundingPaymentType,
PaymentNotSetError,
TransactionType,
} from './abstract-dlc-handler.js';
import { FundingPaymentType, TransactionType } from '../models/dlc-handler.models.js';
import { PaymentNotSetError } from '../models/errors/dlc-handler.errors.models.js';
import { AbstractDLCHandler } from './abstract-dlc-handler.js';

const networkModes = ['mainnet', 'testnet', 'regtest'] as const;

Expand All @@ -33,8 +29,7 @@ interface SignPsbtRequestParams {
}

export class LeatherDLCHandler extends AbstractDLCHandler {
readonly _dlcHandlerType = 'browser' as const;
protected _payment?: PaymentInformation;
readonly _dlcHandlerType = 'leather' as const;
private taprootDerivedPublicKey: string;
private fundingDerivedPublicKey: string;

Expand Down
45 changes: 9 additions & 36 deletions src/dlc-handlers/ledger-dlc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,53 +25,26 @@ import {
updateNativeSegwitInputs,
updateTaprootInputs,
} from '../functions/bitcoin/psbt-functions.js';
import { ExtendedPaymentInformation, PaymentInformation } from '../models/bitcoin-models.js';
import { RawVault } from '../models/ethereum-models.js';
import { truncateAddress } from '../utilities/index.js';
import { ExtendedPaymentInformation } from '../models/bitcoin-models.js';
import { FundingPaymentType, TransactionType } from '../models/dlc-handler.models.js';
import {
AbstractDLCHandler,
DLCHandlerError,
FundingPaymentType,
FundingDerivedPublicKeyNotSet,
IncompatibleTransactionArgument,
TransactionType,
} from './abstract-dlc-handler.js';
PolicyInformationNotSet,
TaprootDerivedPublicKeyNotSet,
} from '../models/errors/dlc-handler.errors.models.js';
import { RawVault } from '../models/ethereum-models.js';
import { truncateAddress } from '../utilities/index.js';
import { AbstractDLCHandler } from './abstract-dlc-handler.js';

interface LedgerPolicyInformation {
fundingWalletPolicy: DefaultWalletPolicy;
multisigWalletPolicy: WalletPolicy;
multisigWalletPolicyHMac: Buffer;
}

export class PolicyInformationNotSet extends DLCHandlerError {
constructor(
message: string = 'Policy Information not initialized. Make sure to create payments before attempting to access them.'
) {
super(message);
this.name = 'PolicyInformationNotSet';
}
}

export class TaprootDerivedPublicKeyNotSet extends DLCHandlerError {
constructor(
message: string = 'Taproot Derived Public Key not set. Make sure to initialize the wallet before attempting to access it.'
) {
super(message);
this.name = 'TaprootDerivedPublicKeyNotSet';
}
}

export class FundingDerivedPublicKeyNotSet extends DLCHandlerError {
constructor(
message: string = 'Funding Derived Public Key not set. Make sure to initialize the wallet before attempting to access it.'
) {
super(message);
this.name = 'FundingDerivedPublicKeyNotSet';
}
}

export class LedgerDLCHandler extends AbstractDLCHandler {
readonly _dlcHandlerType = 'ledger' as const;
protected _payment?: PaymentInformation;
private ledgerApp: AppClient;
private masterFingerprint: string;
private walletAccountIndex: number;
Expand Down
15 changes: 5 additions & 10 deletions src/dlc-handlers/unisat-fordefi-dlc-handler.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
import { Transaction } from '@scure/btc-signer';
import { Network } from 'bitcoinjs-lib';
import { getInputIndicesByScript } from 'src/functions/bitcoin/bitcoin-functions.js';

import { PaymentInformation } from '../models/bitcoin-models.js';
import {
AbstractDLCHandler,
FundingPaymentType,
PaymentNotSetError,
TransactionType,
} from './abstract-dlc-handler.js';
import { getInputIndicesByScript } from '../functions/bitcoin/bitcoin-functions.js';
import { FundingPaymentType, TransactionType } from '../models/dlc-handler.models.js';
import { PaymentNotSetError } from '../models/errors/dlc-handler.errors.models.js';
import { AbstractDLCHandler } from './abstract-dlc-handler.js';

export interface UnisatToSignInput {
index: number;
Expand All @@ -25,8 +21,7 @@ export interface UnisatSignPsbtRequestOptions {
}

export class UnisatFordefiDLCHandler extends AbstractDLCHandler {
readonly _dlcHandlerType = 'browser' as const;
protected _payment?: PaymentInformation;
readonly _dlcHandlerType = 'unisat/fordefi' as const;
private taprootDerivedPublicKey: string;
private fundingDerivedPublicKey: string;

Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DFNSDLCHandler } from './dlc-handlers/dfns-dlc-handler.js';
import { KeyPairDLCHandler } from './dlc-handlers/keypair-dlc-handler.js';
import { LeatherDLCHandler } from './dlc-handlers/leather-dlc-handler.js';
import { LedgerDLCHandler } from './dlc-handlers/ledger-dlc-handler.js';
import { PrivateKeyDLCHandler } from './dlc-handlers/private-key-dlc-handler.js';
import { UnisatFordefiDLCHandler } from './dlc-handlers/unisat-fordefi-dlc-handler.js';
import { EthereumHandler } from './network-handlers/ethereum-handler.js';
import { RippleHandler } from './network-handlers/ripple-handler.js';
Expand All @@ -10,7 +10,7 @@ import { LedgerXRPHandler } from './network-handlers/xrp-ledger-handler.js';
import { ProofOfReserveHandler } from './proof-of-reserve-handlers/proof-of-reserve-handler.js';

export {
PrivateKeyDLCHandler,
KeyPairDLCHandler,
LedgerDLCHandler,
LeatherDLCHandler,
UnisatFordefiDLCHandler,
Expand Down
6 changes: 6 additions & 0 deletions src/models/dlc-handler.models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DLCHandlers } from '../constants/dlc-handler.constants.js';

export type DLCHandlerType = (typeof DLCHandlers)[keyof typeof DLCHandlers];
export type FundingPaymentType = 'wpkh' | 'tr';
export type PaymentType = 'funding' | 'multisig';
export type TransactionType = 'funding' | 'deposit' | 'withdraw';
Loading

0 comments on commit 8b619e2

Please sign in to comment.