mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-17 13:07:34 +02:00
chore(send): min/max for direct send amount
This commit is contained in:
parent
161c404614
commit
cfcc5d498f
3 changed files with 42 additions and 9 deletions
|
|
@ -1,10 +1,12 @@
|
|||
import { getAddressInfo, validate as isValidBitcoinAddress, Network } from 'bitcoin-address-validation'
|
||||
import type { TFunction } from 'i18next'
|
||||
import * as yup from 'yup'
|
||||
import { TOTAL_COIN_SUPPLY } from '@/constants/jam'
|
||||
import type { AddressSummary, Jar } from '@/context/JamWalletInfoContext'
|
||||
import { TX_FEE_UNITS } from '@/lib/feeConfig'
|
||||
import type { JamFeeConfigValues } from '@/lib/feeConfig'
|
||||
import { pseudoRandomInteger } from '@/lib/utils'
|
||||
import type { AmountSats } from '@/types/global'
|
||||
import { toTxFeeFormDefaultValues, createTxFeeFormSchema } from './TxFeeForm.schema'
|
||||
import type { SendFormValues } from './types'
|
||||
|
||||
|
|
@ -18,6 +20,10 @@ export const initialNumberOfCollaborators = (minValue: number): number => {
|
|||
|
||||
const MAX_NUM_COLLABORATORS = 99
|
||||
|
||||
// min amount joinmarket is able to send (without errorsing, last check with v0.9.11 on 2026-04-26)
|
||||
export const MIN_SEND_AMOUNT: AmountSats = 292
|
||||
export const MAX_SEND_AMOUNT: AmountSats = TOTAL_COIN_SUPPLY
|
||||
|
||||
const FORM_INPUT_DEFAULT_VALUES: Partial<SendFormValues> = {
|
||||
source: undefined,
|
||||
destination: undefined,
|
||||
|
|
@ -96,12 +102,7 @@ export const createSendFormSchema = (
|
|||
isSweep: yup.boolean().default(false).required(),
|
||||
sweepAmount: yup.number().when('isSweep', {
|
||||
is: (val: boolean) => val === true,
|
||||
then: (schema) =>
|
||||
schema
|
||||
.integer()
|
||||
.min(1)
|
||||
.max(21_000_000 * 100_000_000)
|
||||
.required(),
|
||||
then: (schema) => schema.integer().min(1).max(MAX_SEND_AMOUNT).required(),
|
||||
otherwise: (schema) =>
|
||||
schema
|
||||
.transform(() => null)
|
||||
|
|
@ -120,8 +121,8 @@ export const createSendFormSchema = (
|
|||
.integer(t('send.feedback_invalid_amount'))
|
||||
.transform((value) => (Number.isSafeInteger(value) ? Number(value) : null))
|
||||
.nonNullable(t('send.feedback_invalid_amount'))
|
||||
.min(1, t('send.feedback_invalid_amount'))
|
||||
.max(21_000_000 * 100_000_000, t('send.feedback_invalid_amount'))
|
||||
.min(MIN_SEND_AMOUNT, t('send.feedback_invalid_amount'))
|
||||
.max(MAX_SEND_AMOUNT, t('send.feedback_invalid_amount'))
|
||||
.required(t('send.feedback_invalid_amount')),
|
||||
}),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -37,7 +37,13 @@ import { Spinner } from '../ui/spinner'
|
|||
import { Switch } from '../ui/switch'
|
||||
import JarSelectorDialog from './JarSelectorDialog'
|
||||
import { SendCoinjoinPreconditionAlert } from './SendCoinjoinPreconditionAlert'
|
||||
import { createSendFormSchema, initialNumberOfCollaborators, toSendFormDefaultValues } from './SendForm.schema'
|
||||
import {
|
||||
createSendFormSchema,
|
||||
initialNumberOfCollaborators,
|
||||
MAX_SEND_AMOUNT,
|
||||
MIN_SEND_AMOUNT,
|
||||
toSendFormDefaultValues,
|
||||
} from './SendForm.schema'
|
||||
import { TxFeeForm } from './TxFeeForm'
|
||||
import { estimateMaxCollaboratorFee } from './feeEstimate'
|
||||
import type { SendFormValues } from './types'
|
||||
|
|
@ -451,6 +457,8 @@ export function SendForm({
|
|||
required: false,
|
||||
disabled,
|
||||
})}
|
||||
min={MIN_SEND_AMOUNT}
|
||||
max={MAX_SEND_AMOUNT}
|
||||
type="number"
|
||||
className="h-auto pl-9"
|
||||
placeholder={t('send.placeholder_amount_input')}
|
||||
|
|
|
|||
|
|
@ -106,3 +106,27 @@ export const JAM_JM_WEBSOCKET_RECONNECT_INTERVAL_MAX: Milliseconds = Math.max(
|
|||
* the `/display` endpoint taking more than ~15s.
|
||||
*/
|
||||
export const GAPLIMIT_WARN_THRESHOLD = 250
|
||||
|
||||
export function totalCoinSupply(): AmountSats {
|
||||
const SATS_PER_COIN = 100_000_000
|
||||
const initialSubsidy = 50 * SATS_PER_COIN
|
||||
const blockPerHalving = 210_000
|
||||
|
||||
let subsidy = initialSubsidy
|
||||
let total = 0
|
||||
let halving = 0
|
||||
|
||||
// Continue until subsidy becomes zero
|
||||
while (subsidy > 0n) {
|
||||
total += blockPerHalving * subsidy
|
||||
// Prepare next halving: integer division by 2 (floor)
|
||||
subsidy = subsidy / 2
|
||||
halving += 1
|
||||
// Safety: break if loop would be infinite (not needed here but good practice)
|
||||
if (halving > 1000) break
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
export const TOTAL_COIN_SUPPLY: AmountSats = totalCoinSupply()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue