diff --git a/src/models/PaymentRequest.ts b/src/models/PaymentRequest.ts index 71917bf6..e3d02e6f 100644 --- a/src/models/PaymentRequest.ts +++ b/src/models/PaymentRequest.ts @@ -4,7 +4,7 @@ import {withSetPropAction} from './helpers/withSetPropAction' import {Contact, ContactModel} from './Contact' import {log} from '../services/logService' import addSeconds from 'date-fns/addSeconds' -import { MintUnit } from '../services' +import { MintUnit, MintUnits } from '../services/wallet/currency' /** * This represents incoming lightning invoice to pay (by transfer tx) @@ -16,6 +16,9 @@ export enum PaymentRequestStatus { EXPIRED = 'EXPIRED', } +export enum MintMethod { + BOLT11 = 'bolt11', +} export enum PaymentRequestType { INCOMING = 'INCOMING', @@ -27,10 +30,13 @@ export const PaymentRequestModel = types type: types.frozen(), status: types.frozen(), mint: types.maybe(types.string), - mintQuote: types.maybe(types.string), + mintQuote: types.maybe(types.string), + mintUnit: types.frozen(), // TODO migration to set default unit for existing PRs + mintMethod: types.optional(types.frozen(), MintMethod.BOLT11), + amountToTopup: types.number, encodedInvoice: types.string, - amount: types.number, - unit: types.frozen(), // TODO migration to set default unit for existing PRs + invoicedAmount: types.number, + invoicedUnit: types.optional(types.frozen(), 'sat'), description: types.optional(types.string, ''), paymentHash: types.string, contactFrom: types.frozen(), @@ -52,10 +58,12 @@ export type PaymentRequest = { type: PaymentRequestType status: PaymentRequestStatus mint?: string + mintUnit: MintUnit mintQuote?: string + mintMethod?: MintMethod + amountToTopup: number encodedInvoice: string - amount: number - unit: MintUnit + invoicedAmount: number description?: string paymentHash: string contactFrom: Contact diff --git a/src/models/ProofsStore.ts b/src/models/ProofsStore.ts index c0783c9d..52661096 100644 --- a/src/models/ProofsStore.ts +++ b/src/models/ProofsStore.ts @@ -262,7 +262,7 @@ export const ProofsStoreModel = types unitPendingBalances, } - log.debug('[getBalances]', balances) + // log.debug('[getBalances]', balances) // console.log(balances) return balances @@ -292,6 +292,21 @@ export const ProofsStoreModel = types return filteredMintBalances }, + getMintBalancesWithUnit: (unit: MintUnit) => { + const balances = self.getBalances().mintBalances + + const filteredMintBalances = balances + .slice() + .filter((balance: MintBalance) => { + if(Object.keys(balance.balances).includes(unit)) { + return true + } + return false + }) + .sort((a, b) => b.balances[unit]! - a.balances[unit]!) + + return filteredMintBalances + }, getMintBalanceWithMaxBalance: (unit: MintUnit) => { const balances = self.getBalances().mintBalances diff --git a/src/navigation/TabsNavigator.tsx b/src/navigation/TabsNavigator.tsx index 7357bf46..aa1f164a 100644 --- a/src/navigation/TabsNavigator.tsx +++ b/src/navigation/TabsNavigator.tsx @@ -47,6 +47,7 @@ import { MintBalance } from "../models/Mint" import { PaymentRequest } from "../models/PaymentRequest" import { LNURLPayParams, LNURLWithdrawParams } from "js-lnurl" import { IncomingDataType } from "../services/incomingParser" +import { MintUnit } from "../services/wallet/currency" export type TabsParamList = { @@ -124,12 +125,29 @@ export type WalletStackParamList = { SendOptions: undefined Send: {contact?: Contact, relays?: string[], paymentOption?: SendOption} Scan: undefined - LightningPay: undefined + LightningPay: { + mintUrl?: string, + unit?: MintUnit + } TranDetail: {id: number} TranHistory: undefined PaymentRequests: undefined - Transfer: {encodedInvoice?: string, paymentRequest?: PaymentRequest, lnurlParams?: LNURLPayParams & {address?: string}, paymentOption?: SendOption,} - Topup: {contact?: Contact, relays?: string[], paymentOption?: ReceiveOption, lnurlParams?: LNURLWithdrawParams} + Transfer: { + encodedInvoice?: string, + paymentRequest?: PaymentRequest, + lnurlParams?: LNURLPayParams & {address?: string}, + paymentOption?: SendOption, + mintUrl?: string, + unit?: MintUnit + } + Topup: { + contact?: Contact, + relays?: string[], + paymentOption?: ReceiveOption, + lnurlParams?: LNURLWithdrawParams, + mintUrl?: string, + unit?: MintUnit + } ContactsNavigator: {screen: string, params: any} SettingsNavigator: {screen: string, params: any} } diff --git a/src/screens/Mints/MintListItem.tsx b/src/screens/Mints/MintListItem.tsx index d3c16a38..edcdf025 100644 --- a/src/screens/Mints/MintListItem.tsx +++ b/src/screens/Mints/MintListItem.tsx @@ -36,7 +36,7 @@ export const MintListItem = observer(function(props: { const {mint, mintBalance, selectedUnit, onMintSelect, isSelected, isSelectable, isBlocked, isUnitVisible, separator} = props - log.trace('[MintListItem]', props) + // log.trace('[MintListItem]', props) return ( - @@ -95,7 +95,7 @@ export const PaymentRequestListItem = observer(function (props: PaymentRequestLi size={spacing.medium} color={dim} /> - + diff --git a/src/screens/TopupScreen.tsx b/src/screens/TopupScreen.tsx index 3e407ab7..02fcc134 100644 --- a/src/screens/TopupScreen.tsx +++ b/src/screens/TopupScreen.tsx @@ -48,11 +48,11 @@ import { Contact } from '../models/Contact' import { getImageSource, infoMessage } from '../utils/utils' import { ReceiveOption } from './ReceiveOptionsScreen' import { LNURLWithdrawParams } from 'js-lnurl' -import { roundDown } from '../utils/number' +import { roundDown, roundUp, toNumber } from '../utils/number' import { LnurlClient, LnurlWithdrawResult } from '../services/lnurlService' import { moderateVerticalScale, verticalScale } from '@gocodingnow/rn-size-matters' import { CurrencySign } from './Wallet/CurrencySign' -import { CurrencyCode, MintUnit, MintUnitCurrencyPairs, MintUnits } from "../services/wallet/currency" +import { Currencies, CurrencyCode, MintUnit, MintUnitCurrencyPairs, MintUnits } from "../services/wallet/currency" if ( Platform.OS === 'android' && @@ -120,6 +120,19 @@ export const TopupScreen: FC> = observer( } }, []) + useEffect(() => { + const { mintUrl, unit } = route.params + + const setSelectedMintandUnit = () => { + setUnit(unit!) + setMintBalanceToTopup(proofsStore.getMintBalance(mintUrl!)) + } + + if(mintUrl && unit) { + setSelectedMintandUnit() + } + }, []) + // Send to contact useFocusEffect( useCallback(() => { @@ -288,7 +301,11 @@ export const TopupScreen: FC> = observer( const onAmountEndEditing = function () { try { - const amount = parseInt(amountToTopup) + const precision = Currencies[MintUnitCurrencyPairs[unit]]!.precision + const mantissa = Currencies[MintUnitCurrencyPairs[unit]]!.mantissa + const amount = toNumber(amountToTopup) * precision + + log.trace('[onAmountEndEditing]', amount) if (!amount || amount === 0) { infoMessage('Amount should be positive number.') @@ -300,17 +317,18 @@ export const TopupScreen: FC> = observer( return } - const availableBalances = proofsStore.getBalances().mintBalances + const availableBalances = proofsStore.getMintBalancesWithUnit(unit) if (availableBalances.length === 0) { - infoMessage('Add the mint first.', 'There is no mint connected to your wallet that you would receive your ecash from.') + infoMessage('Add the mint first.', 'There is no mint connected to your wallet that you would receive your ecash to.') return } + setAmountToTopup(`${roundUp(toNumber(amountToTopup), mantissa)}`) // round amount based on currency format setAvailableMintBalances(availableBalances) - // Default mint with highest balance to topup - setMintBalanceToTopup(availableBalances[0]) + // Default mint is the one with the highest balance to topup + if(!mintBalanceToTopup) setMintBalanceToTopup(availableBalances[0]) setIsAmountEndEditing(true) // We do not make memo focus mandatory LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) @@ -365,7 +383,7 @@ export const TopupScreen: FC> = observer( WalletTask.topup( mintBalanceToTopup as MintBalance, - parseInt(amountToTopup), + toNumber(amountToTopup) * Currencies[MintUnitCurrencyPairs[unit]]!.precision, unit, memo, contactToSendTo diff --git a/src/screens/Wallet/CurrencyAmount.tsx b/src/screens/Wallet/CurrencyAmount.tsx index 0f415472..6c71af11 100644 --- a/src/screens/Wallet/CurrencyAmount.tsx +++ b/src/screens/Wallet/CurrencyAmount.tsx @@ -19,14 +19,14 @@ export const CurrencyAmount = observer(function (props: { }) { const {currencyCode, mintUnit, amount, symbolStyle, amountStyle, containerStyle, size} = props - let currencySymbol: string = Currencies.SATS?.symbol! + let currencySymbol: string = Currencies.SATS!.symbol if(!!currencyCode) { - currencySymbol = Currencies[currencyCode]?.symbol! + currencySymbol = Currencies[currencyCode]!.symbol } if(!!mintUnit) { - currencySymbol = Currencies[MintUnitCurrencyPairs[mintUnit]]?.symbol! + currencySymbol = Currencies[MintUnitCurrencyPairs[mintUnit]]!.symbol } const amountColor = useThemeColor('amount') @@ -34,14 +34,11 @@ export const CurrencyAmount = observer(function (props: { return ( = observer( navigation.navigate('Scan') } - const gotoMintInfo = function (mintUrl: string) { + /* const gotoMintInfo = function (mintUrl: string) { navigation.navigate('SettingsNavigator', {screen: 'MintInfo', params: {mintUrl}}) - } + } */ const gotoTranHistory = function () { navigation.navigate('TranHistory') @@ -305,7 +307,7 @@ export const WalletScreen: FC = observer( /* Mints pager */ const groupedMints = mintsStore.groupedByUnit - log.trace('[WalletScreen]', {groupedByUnit: groupedMints}) + // log.trace('[WalletScreen]', {groupedByUnit: groupedMints}) const width = spacing.screenWidth const pagerRef = useRef(null) const scrollOffsetAnimatedValue = React.useRef(new Animated.Value(0)).current @@ -404,7 +406,7 @@ export const WalletScreen: FC = observer( {/*transactionsStore.recentByHostname(mints.hostname).length > 0 && ( (false) + + const [selectedMintUrl, setSelectedMintUrl] = useState(undefined) - const toggleMenu = function () { - if (isMenuVisible) { - log.trace('[toggleMenu]', !isMenuVisible) - setIsMenuVisible(false) - } else { - log.trace('[toggleMenu]', !isMenuVisible) - setIsMenuVisible(true) + const onSelectedMint = function (mintUrl: string) { + if (selectedMintUrl && selectedMintUrl === mintUrl) { + LayoutAnimation.easeInEaseOut() + setSelectedMintUrl(undefined) + return } - }*/ + LayoutAnimation.easeInEaseOut() + setSelectedMintUrl(mintUrl) + } + + const gotoMintInfo = function (mintUrl: string) { + props.navigation.navigate('SettingsNavigator', {screen: 'MintInfo', params: {mintUrl}}) + } + + + const gotoTopup = function (mintUrl: string, unit: MintUnit) { + props.navigation.navigate('Topup', { + paymentOption: ReceiveOption.SHOW_INVOICE, + mintUrl, + unit + }) + } + + + const gotoLightningPay = async function (mintUrl: string, unit: MintUnit) { + props.navigation.navigate('LightningPay', { + mintUrl, + unit + }) + } + + const color = useThemeColor('textDim') const balanceColor = useThemeColor('amount') const {mintsByUnit} = props @@ -615,11 +641,11 @@ const MintsByUnitListItem = observer(function (props: { ContentComponent={ <> {mintsByUnit.mints.map((mint: Mint) => ( - + props.gotoMintInfo(mint.mintUrl)} + onPress={() => onSelectedMint(mint.mintUrl)} /> + {selectedMintUrl === mint.mintUrl && ( + +