Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9bee394

Browse files
Consider crypto balance for max sell quotes
1 parent 5b622f0 commit 9bee394

File tree

9 files changed

+139
-23
lines changed

9 files changed

+139
-23
lines changed

‎src/components/scenes/RampCreateScene.tsx‎

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
type SupportedPluginResult,
2222
useSupportedPlugins
2323
} from '../../hooks/useSupportedPlugins'
24+
import { useWalletBalance } from '../../hooks/useWalletBalance'
2425
import { useWatch } from '../../hooks/useWatch'
2526
import { lstrings } from '../../locales/strings'
2627
import type {
@@ -40,7 +41,11 @@ import type {
4041
import type { GuiFiatType } from '../../types/types'
4142
import { getCurrencyCode } from '../../util/CurrencyInfoHelpers'
4243
import { getHistoricalFiatRate } from '../../util/exchangeRates'
43-
import { DECIMAL_PRECISION, mulToPrecision } from '../../util/utils'
44+
import {
45+
convertNativeToDenomination,
46+
DECIMAL_PRECISION,
47+
mulToPrecision
48+
} from '../../util/utils'
4449
import { DropdownInputButton } from '../buttons/DropdownInputButton'
4550
import { EdgeButton } from '../buttons/EdgeButton'
4651
import { PillButton } from '../buttons/PillButton'
@@ -332,6 +337,18 @@ export const RampCreateScene: React.FC<Props> = (props: Props) => {
332337
)
333338
})
334339

340+
const walletBalanceNative = useWalletBalance(
341+
selectedWallet,
342+
selectedCrypto?.tokenId
343+
)
344+
345+
const walletBalanceDisplayAmount = React.useMemo(() => {
346+
if (selectedWallet == null || denomination == null) return '0'
347+
return convertNativeToDenomination(denomination.multiplier)(
348+
walletBalanceNative
349+
)
350+
}, [selectedWallet, denomination, walletBalanceNative])
351+
335352
// Get the best quote using .find because we want to preserve undefined in its type
336353
const bestQuote = allQuotes.find((_, index) => index === 0)
337354

@@ -541,8 +558,10 @@ export const RampCreateScene: React.FC<Props> = (props: Props) => {
541558

542559
// Trigger a transient max flow: request quotes with {max:true} and auto-navigate when ready
543560
setPendingMaxNav(true)
544-
setLastUsedInput('fiat')
545-
setExchangeAmount({ max: true })
561+
setLastUsedInput(direction === 'buy' ? 'fiat' : 'crypto')
562+
setExchangeAmount({
563+
max: direction === 'sell' ? walletBalanceDisplayAmount : true
564+
})
546565
})
547566

548567
// Auto-navigate once a best quote arrives for the transient max flow

‎src/hooks/useWalletBalance.ts‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ import * as React from 'react'
55
* Subscribes to a specific balance within a wallet.
66
*/
77
export function useWalletBalance(
8-
wallet: EdgeCurrencyWallet,
9-
tokenId: EdgeTokenId
8+
wallet: EdgeCurrencyWallet|undefined,
9+
tokenId: EdgeTokenId|undefined
1010
): string {
1111
// The core still reports balances by currency code:
12-
const [out, setOut] = React.useState<string>(
13-
wallet.balanceMap.get(tokenId) ?? '0'
14-
)
12+
const [out, setOut] = React.useState<string>('0')
1513

1614
React.useEffect(() => {
15+
if (wallet == null || tokenId === undefined) {
16+
setOut('0')
17+
return
18+
}
19+
1720
setOut(wallet.balanceMap.get(tokenId) ?? '0')
1821
return wallet.watch('balanceMap', balances => {
1922
setOut(wallet.balanceMap.get(tokenId) ?? '0')

‎src/plugins/ramps/banxa/banxaRampPlugin.ts‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,10 +890,14 @@ export const banxaRampPlugin: RampPluginFactory = (
890890
} = request
891891
const currencyPluginId = request.wallet.currencyInfo.pluginId
892892

893-
const isMaxAmount =
894-
'max' in request.exchangeAmount && request.exchangeAmount.max
893+
const isMaxAmount = 'max' in request.exchangeAmount
895894
const exchangeAmount =
896895
'amount' in request.exchangeAmount ? request.exchangeAmount.amount : ''
896+
const maxAmountLimit =
897+
'max' in request.exchangeAmount &&
898+
typeof request.exchangeAmount.max === 'string'
899+
? request.exchangeAmount.max
900+
: undefined
897901

898902
// Fetch provider configuration (cached or fresh)
899903
const config = await fetchProviderConfig()
@@ -1058,6 +1062,13 @@ export const banxaRampPlugin: RampPluginFactory = (
10581062
continue
10591063
}
10601064
maxAmountString = maxPriceRow.coin_amount
1065+
1066+
if (
1067+
maxAmountLimit != null &&
1068+
gt(maxAmountString, maxAmountLimit)
1069+
) {
1070+
maxAmountString = maxAmountLimit
1071+
}
10611072
}
10621073
}
10631074

‎src/plugins/ramps/bity/bityRampPlugin.ts‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,10 +685,14 @@ export const bityRampPlugin = (pluginConfig: RampPluginConfig): RampPlugin => {
685685
const currencyPluginId = request.wallet.currencyInfo.pluginId
686686
const isBuy = direction === 'buy'
687687

688-
const isMaxAmount =
689-
'max' in request.exchangeAmount && request.exchangeAmount.max
688+
const isMaxAmount = 'max' in request.exchangeAmount
690689
const exchangeAmount =
691690
'amount' in request.exchangeAmount ? request.exchangeAmount.amount : ''
691+
const maxAmountLimit =
692+
'max' in request.exchangeAmount &&
693+
typeof request.exchangeAmount.max === 'string'
694+
? request.exchangeAmount.max
695+
: undefined
692696

693697
// Validate region using helper function
694698
if (!isRegionSupported(regionCode)) {
@@ -782,6 +786,10 @@ export const bityRampPlugin = (pluginConfig: RampPluginConfig): RampPlugin => {
782786
return []
783787
}
784788
}
789+
790+
if (maxAmountLimit != null && gt(amount, maxAmountLimit)) {
791+
amount = maxAmountLimit
792+
}
785793
} else {
786794
amount = toFixed(exchangeAmount, amountPrecision)
787795
}

‎src/plugins/ramps/moonpay/moonpayRampPlugin.ts‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,10 +517,14 @@ export const moonpayRampPlugin: RampPluginFactory = (
517517
const { direction, regionCode, displayCurrencyCode, tokenId } = request
518518
const fiatCurrencyCode = ensureIsoPrefix(request.fiatCurrencyCode)
519519

520-
const isMaxAmount =
521-
'max' in request.exchangeAmount && request.exchangeAmount.max
520+
const isMaxAmount = 'max' in request.exchangeAmount
522521
const exchangeAmountString =
523522
'amount' in request.exchangeAmount ? request.exchangeAmount.amount : ''
523+
const maxAmountLimitString =
524+
'max' in request.exchangeAmount &&
525+
typeof request.exchangeAmount.max === 'string'
526+
? request.exchangeAmount.max
527+
: undefined
524528

525529
// Fetch provider configuration (with caching)
526530
const config = await fetchProviderConfig()
@@ -647,9 +651,17 @@ export const moonpayRampPlugin: RampPluginFactory = (
647651
Infinity
648652
}
649653

654+
const maxAmountLimit =
655+
maxAmountLimitString != null
656+
? parseFloat(maxAmountLimitString)
657+
: undefined
658+
650659
let exchangeAmount: number
651660
if (isMaxAmount) {
652661
exchangeAmount = request.amountType === 'fiat' ? maxFiat : maxCrypto
662+
if (maxAmountLimit != null && isFinite(maxAmountLimit)) {
663+
exchangeAmount = Math.min(exchangeAmount, maxAmountLimit)
664+
}
653665
} else {
654666
exchangeAmount = parseFloat(exchangeAmountString)
655667
}

‎src/plugins/ramps/paybis/paybisRampPlugin.ts‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,10 +747,14 @@ export const paybisRampPlugin: RampPluginFactory = (
747747
} = request
748748
const currencyPluginId = request.wallet.currencyInfo.pluginId
749749

750-
const isMaxAmount =
751-
'max' in request.exchangeAmount && request.exchangeAmount.max
750+
const isMaxAmount = 'max' in request.exchangeAmount
752751
const exchangeAmount =
753752
'amount' in request.exchangeAmount ? request.exchangeAmount.amount : ''
753+
const maxAmountLimit =
754+
'max' in request.exchangeAmount &&
755+
typeof request.exchangeAmount.max === 'string'
756+
? request.exchangeAmount.max
757+
: undefined
754758

755759
// Validate region restrictions
756760
if (regionCode != null) {
@@ -837,6 +841,16 @@ export const paybisRampPlugin: RampPluginFactory = (
837841
if (isMaxAmount) {
838842
// Use default max amounts
839843
amount = amountType === 'fiat' ? '10000' : '10'
844+
845+
if (maxAmountLimit != null) {
846+
const maxCapNumber = parseFloat(maxAmountLimit)
847+
const amountNumber = parseFloat(amount)
848+
if (!Number.isNaN(maxCapNumber) && !Number.isNaN(amountNumber)) {
849+
if (amountNumber > maxCapNumber) {
850+
amount = maxAmountLimit
851+
}
852+
}
853+
}
840854
} else {
841855
amount = exchangeAmount
842856
}

‎src/plugins/ramps/rampPluginTypes.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export interface RampSupportResult {
3939

4040
export type RampExchangeAmount =
4141
| {
42-
max: true
42+
max: string|true
4343
}
4444
| { amount: string }
4545

‎src/plugins/ramps/revolut/revolutRampPlugin.ts‎

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,14 @@ export const revolutRampPlugin: RampPluginFactory = (
191191
} = request
192192
const currencyPluginId = request.wallet.currencyInfo.pluginId
193193

194-
const isMaxAmount =
195-
'max' in request.exchangeAmount && request.exchangeAmount.max
194+
const isMaxAmount = 'max' in request.exchangeAmount
196195
const exchangeAmount =
197196
'amount' in request.exchangeAmount ? request.exchangeAmount.amount : ''
197+
const maxAmountLimit =
198+
'max' in request.exchangeAmount &&
199+
typeof request.exchangeAmount.max === 'string'
200+
? request.exchangeAmount.max
201+
: undefined
198202

199203
// Constraints per request
200204
const constraintOk = validateRampQuoteRequest(
@@ -287,7 +291,7 @@ export const revolutRampPlugin: RampPluginFactory = (
287291
}
288292

289293
// Fetch quote from Revolut (API only needs country code)
290-
const quoteData = await fetchRevolutQuote(
294+
let quoteData = await fetchRevolutQuote(
291295
{
292296
fiat: revolutFiat.currency,
293297
amount,
@@ -298,8 +302,42 @@ export const revolutRampPlugin: RampPluginFactory = (
298302
{ apiKey, baseUrl: apiUrl }
299303
)
300304

305+
if (isMaxAmount && maxAmountLimit != null) {
306+
const capValue = parseFloat(maxAmountLimit)
307+
const quotedCrypto = parseFloat(quoteData.crypto.amount.toString())
308+
const currentFiat = parseFloat(amount)
309+
if (
310+
!Number.isNaN(capValue) &&
311+
!Number.isNaN(quotedCrypto) &&
312+
!Number.isNaN(currentFiat) &&
313+
quotedCrypto > 0 &&
314+
capValue < quotedCrypto
315+
) {
316+
const scaledFiat = (currentFiat * capValue) / quotedCrypto
317+
if (scaledFiat < revolutFiat.min_limit) {
318+
throw new FiatProviderError({
319+
providerId: pluginId,
320+
errorType: 'underLimit',
321+
errorAmount: revolutFiat.min_limit,
322+
displayCurrencyCode: revolutFiat.currency
323+
})
324+
}
325+
amount = scaledFiat.toString()
326+
quoteData = await fetchRevolutQuote(
327+
{
328+
fiat: revolutFiat.currency,
329+
amount,
330+
crypto: revolutCrypto.id,
331+
payment: 'revolut',
332+
region: regionCode.countryCode
333+
},
334+
{ apiKey, baseUrl: apiUrl }
335+
)
336+
}
337+
}
338+
301339
const cryptoAmount = quoteData.crypto.amount.toString()
302-
const fiatAmount = exchangeAmount
340+
const fiatAmount = amount
303341

304342
// Assume 1 minute expiration
305343
const expirationDate = new Date(Date.now() + 1000 * 60)

‎src/plugins/ramps/simplex/simplexRampPlugin.ts‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,10 +480,14 @@ export const simplexRampPlugin: RampPluginFactory = (
480480
} = request
481481
const currencyPluginId = request.wallet.currencyInfo.pluginId
482482

483-
const isMaxAmount =
484-
'max' in request.exchangeAmount && request.exchangeAmount.max
483+
const isMaxAmount = 'max' in request.exchangeAmount
485484
const exchangeAmount =
486485
'amount' in request.exchangeAmount ? request.exchangeAmount.amount : ''
486+
const maxAmountLimit =
487+
'max' in request.exchangeAmount &&
488+
typeof request.exchangeAmount.max === 'string'
489+
? request.exchangeAmount.max
490+
: undefined
487491

488492
// Validate direction
489493
if (!validateDirection(direction)) {
@@ -531,6 +535,13 @@ export const simplexRampPlugin: RampPluginFactory = (
531535
if (isMaxAmount) {
532536
// Use reasonable max amounts
533537
sourceAmount = amountType === 'fiat' ? 50000 : 100
538+
539+
if (amountType !== 'fiat' && maxAmountLimit != null) {
540+
const capValue = parseFloat(maxAmountLimit)
541+
if (isFinite(capValue)) {
542+
sourceAmount = Math.min(sourceAmount, capValue)
543+
}
544+
}
534545
} else {
535546
sourceAmount = parseFloat(exchangeAmount)
536547
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /