Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions core/api/galoy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,38 @@ bria:
queueName: dev-queue
displayName: Priority
description: Estimated broadcast ~10 minutes
feeMethodConfig:
exponentialDecay:
minRate: 0.0075
maxRate: 0.04
divisor: 30000
targetRate: 0.005
offset: 1.3
factor: 2
- speed: medium
queueName: dev-medium-queue
displayName: Standard
description: Estimated broadcast ~1 hour
feeMethodConfig:
exponentialDecay:
minRate: 0.005
maxRate: 0.03
divisor: 20000
targetRate: 0.0025
offset: 1.1
factor: 1
- speed: slow
queueName: dev-slow-queue
displayName: Flexible
description: Estimated broadcast ~24 hours
feeMethodConfig:
exponentialDecay:
minRate: 0.003125
maxRate: 0.02
divisor: 12500
targetRate: 0.001
offset: 1.1
factor: 2
rebalances:
hotToCold:
threshold: 200000000
Expand Down Expand Up @@ -172,6 +196,13 @@ fees:
defaultMin: 3000
threshold: 1000000
ratioAsBasisPoints: 30
exponentialDecay:
threshold: 4000000
minSats: 21000
exponentialFactor: 21
networkFeeRange:
min: 1
max: 2000
merchantDeposit:
defaultMin: 3000
threshold: 1000000
Expand Down
10 changes: 7 additions & 3 deletions core/api/src/app/wallets/get-on-chain-fee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,18 @@ export const getMinerFeeAndPaymentFlow = async <
const address = await builder.addressForFlow()
if (address instanceof Error) return address

const minerFee = await onChainService.estimateFeeForPayout({
const estimateRes = await onChainService.estimateFeeForPayout({
amount: proposedBtcAmount,
address,
speed,
})
if (minerFee instanceof Error) return minerFee
if (estimateRes instanceof Error) return estimateRes

return builder.withMinerFee(minerFee)
return builder.withMinerFee({
minerFee: estimateRes.fee,
feeRate: estimateRes.feeRate,
speed,
})
}

export const getOnChainFeeForBtcWallet = async <S extends WalletCurrency>(
Expand Down
89 changes: 86 additions & 3 deletions core/api/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,27 @@ const rateLimitConfigSchema = {
additionalProperties: false,
}

const feeMethodConfigSchema = {
type: "object",
properties: {
exponentialDecay: {
type: "object",
properties: {
minRate: { type: "number" },
maxRate: { type: "number" },
divisor: { type: "integer" },
targetRate: { type: "number" },
offset: { type: "number" },
factor: { type: "number" },
},
required: ["minRate", "maxRate", "divisor", "targetRate", "offset", "factor"],
additionalProperties: false,
},
},
required: ["exponentialDecay"],
additionalProperties: false,
}

export const configSchema = {
type: "object",
properties: {
Expand Down Expand Up @@ -181,8 +202,15 @@ export const configSchema = {
queueName: { type: "string" },
displayName: { type: "string" },
description: { type: "string" },
feeMethodConfig: feeMethodConfigSchema,
},
required: ["speed", "queueName", "displayName", "description"],
required: [
"speed",
"queueName",
"displayName",
"description",
"feeMethodConfig",
],
additionalProperties: false,
},
default: [
Expand All @@ -191,18 +219,48 @@ export const configSchema = {
queueName: "dev-queue",
displayName: "Priority",
description: "Estimated broadcast ~10 minutes",
feeMethodConfig: {
exponentialDecay: {
minRate: 0.0075,
maxRate: 0.04,
divisor: 30000,
targetRate: 0.005,
offset: 1.3,
factor: 2,
},
},
},
{
speed: "medium",
queueName: "dev-medium-queue",
displayName: "Standard",
description: "Estimated broadcast ~1 hour",
feeMethodConfig: {
exponentialDecay: {
minRate: 0.005,
maxRate: 0.03,
divisor: 20000,
targetRate: 0.0025,
offset: 1.1,
factor: 1,
},
},
},
{
speed: "slow",
queueName: "dev-slow-queue",
displayName: "Flexible",
description: "Estimated broadcast ~24 hours",
feeMethodConfig: {
exponentialDecay: {
minRate: 0.003125,
maxRate: 0.02,
divisor: 12500,
targetRate: 0.001,
offset: 1.1,
factor: 2,
},
},
},
],
},
Expand Down Expand Up @@ -599,7 +657,7 @@ export const configSchema = {
properties: {
method: {
type: "string",
enum: ["flat", "proportionalOnImbalance"],
enum: ["flat", "proportionalOnImbalance", "exponentialDecay"],
},
ratioAsBasisPoints: { type: "integer" },
threshold: { type: "integer" },
Expand All @@ -622,8 +680,27 @@ export const configSchema = {
daysLookback: 30,
},
},
exponentialDecay: {
type: "object",
properties: {
threshold: { type: "integer" },
minSats: { type: "integer" },
exponentialFactor: { type: "integer" },
networkFeeRange: {
type: "object",
properties: {
min: { type: "integer" },
max: { type: "integer" },
},
required: ["min", "max"],
additionalProperties: false,
},
},
required: ["threshold", "minSats", "exponentialFactor", "networkFeeRange"],
additionalProperties: false,
},
},
required: ["withdraw", "deposit"],
required: ["withdraw", "deposit", "exponentialDecay"],
additionalProperties: false,
default: {
withdraw: {
Expand All @@ -634,6 +711,12 @@ export const configSchema = {
daysLookback: 30,
},
deposit: { defaultMin: 3000, threshold: 1000000, ratioAsBasisPoints: 30 },
exponentialDecay: {
threshold: 4000000,
minSats: 21000,
exponentialFactor: 21,
networkFeeRange: { min: 1, max: 2000 },
},
},
},
onChainWallet: {
Expand Down
22 changes: 22 additions & 0 deletions core/api/src/config/schema.types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,25 @@ type AccountLimitsConfig = {
}
}

type ExponentialDecayConfig = {
minRate: number
maxRate: number
divisor: number
targetRate: number
offset: number
factor: number
}

type FeeMethodConfig = {
exponentialDecay: ExponentialDecayConfig
}

type PayoutQueueConfig = {
speed: PayoutSpeed
queueName: string
displayName: string
description: string
feeMethodConfig: FeeMethodConfig
}

type RebalanceConfig = {
Expand All @@ -31,6 +45,13 @@ type RebalanceConfig = {
payoutQueueName: string
}

type ExponentialDecayFeesConfig = {
threshold: number
minSats: number
exponentialFactor: number
networkFeeRange: { min: number; max: number }
}

type YamlSchema = {
name: string
lightningAddressDomain: string
Expand Down Expand Up @@ -142,6 +163,7 @@ type YamlSchema = {
daysLookback: number
defaultMin: number
}
exponentialDecay: ExponentialDecayFeesConfig
}
onChainWallet: {
dustThreshold: number
Expand Down
1 change: 1 addition & 0 deletions core/api/src/config/yaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export const getFeesConfig = (feesConfig = yamlConfig.fees): FeesConfig => {
withdrawThreshold: toSats(feesConfig.withdraw.threshold),
withdrawDaysLookback: toDays(feesConfig.withdraw.daysLookback),
withdrawDefaultMin: toSats(feesConfig.withdraw.defaultMin),
exponentialDecayMethod: feesConfig.exponentialDecay,
}
}

Expand Down
1 change: 1 addition & 0 deletions core/api/src/domain/accounts/index.types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,5 @@ type FeesConfig = {
withdrawThreshold: Satoshis
withdrawDaysLookback: Days
withdrawDefaultMin: Satoshis
exponentialDecayMethod: ExponentialDecayFeesConfig
}
2 changes: 1 addition & 1 deletion core/api/src/domain/bitcoin/onchain/index.types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ interface IOnChainService {
}): Promise<PayoutId | OnChainServiceError>
estimateFeeForPayout(
args: EstimatePayoutFeeArgs,
): Promise<BtcPaymentAmount | OnChainServiceError>
): Promise<EstimateFeeForPayoutRes | OnChainServiceError>
listPayoutQueues(): Promise<PayoutQueue[] | OnChainServiceError>
}

Expand Down
5 changes: 4 additions & 1 deletion core/api/src/domain/ledger/imbalance-calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ export const ImbalanceCalculator = ({
const getSwapOutImbalanceAmount = async <T extends WalletCurrency>(
wallet: WalletDescriptor<T>,
): Promise<PaymentAmount<T> | LedgerServiceError | ValidationError> => {
if (method === WithdrawalFeePriceMethod.flat) {
if (
method === WithdrawalFeePriceMethod.flat ||
method === WithdrawalFeePriceMethod.exponentialDecay
) {
return paymentAmountFromNumber<T>({ amount: 0, currency: wallet.currency })
}

Expand Down
16 changes: 13 additions & 3 deletions core/api/src/domain/payments/index.types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ type WithConversionArgs = {
mid: ConversionFns
}

type WithMinerFeeArgs = {
minerFee: BtcPaymentAmount
speed: PayoutSpeed
feeRate: number
}

type LightningPaymentFlowBuilder<S extends WalletCurrency> = {
withInvoice(invoice: LnInvoice): LPFBWithInvoice<S> | LPFBWithError
withNoAmountInvoice({
Expand Down Expand Up @@ -326,9 +332,13 @@ type OPFBWithAmount<S extends WalletCurrency, R extends WalletCurrency> = {
}

type OPFBWithConversion<S extends WalletCurrency, R extends WalletCurrency> = {
withMinerFee(
minerFee: BtcPaymentAmount,
): Promise<OnChainPaymentFlow<S, R> | ValidationError | DealerPriceServiceError>
withMinerFee({
minerFee,
feeRate,
speed,
}: WithMinerFeeArgs): Promise<
OnChainPaymentFlow<S, R> | ValidationError | DealerPriceServiceError
>
withoutMinerFee(): Promise<
OnChainPaymentFlow<S, R> | ValidationError | DealerPriceServiceError
>
Expand Down
Loading
Loading