Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b72cc6e
add transfer feature mvp (topup with card)
islandbitcoin Jul 15, 2025
0f00afa
Your Private Profile
Nodirbek75 Jul 17, 2025
38fcc5d
redesign and refactor transfer-screen, topup-screen and card-payment-…
Nodirbek75 Jul 19, 2025
4223024
BankTransfer screen is implemented and added in the root navigation
Nodirbek75 Jul 22, 2025
f501504
restructure buy-sell-bitcoin flow screens
Nodirbek75 Jul 22, 2025
b23328a
add BankTransfer texts on the i18n file
Nodirbek75 Jul 22, 2025
26c64ad
refactor and clean up CardPayment webview screen
Nodirbek75 Jul 22, 2025
71f1e49
use texts from i18n on the BankTransfer screen and update BuyBitcoinD…
Nodirbek75 Jul 22, 2025
35458a6
update BuySellBitcoin screen icons and added navigation to cashout
Nodirbek75 Jul 23, 2025
025c12b
ArrowUpDown icon btn is added
Nodirbek75 Jul 23, 2025
9c7a02f
add back cashout mutations
Nodirbek75 Jul 23, 2025
04b6a9a
show Transfer button instead of Cashout button on the home screen
Nodirbek75 Jul 23, 2025
b41ea81
update CashoutDetails screen
Nodirbek75 Jul 23, 2025
cccfcee
update cashout description text
Nodirbek75 Jul 25, 2025
ba76a0c
update CashoutConfirmation screen to show amount in display currency
Nodirbek75 Jul 25, 2025
a01438e
add back exchangeRate to the requestCashout offer response and update…
Nodirbek75 Jul 31, 2025
7ea92b6
Merge remote-tracking branch 'origin' into feat/fygaro
Nodirbek75 Jul 31, 2025
63148d2
add back exchangeRate on the generated.gql and generated.ts files
Nodirbek75 Jul 31, 2025
c7e154e
Merge remote-tracking branch 'origin' into feat/fygaro
Nodirbek75 Aug 14, 2025
11a1ddb
BuyBitcoinSuccess screen is implemented and added in root navigation
Nodirbek75 Aug 15, 2025
0159919
Merge remote-tracking branch 'origin' into feat/fygaro
Nodirbek75 Sep 17, 2025
d47d607
enabled card payments via Fygaro - webhook wip
islandbitcoin Sep 24, 2025
47046d0
add developer comments
islandbitcoin Sep 24, 2025
5d69dda
Merge remote-tracking branch 'origin' into feat/fygaro
Nodirbek75 Apr 22, 2026
d7a0bb6
add cashout api integration changes in this branch
Nodirbek75 Apr 22, 2026
29bf684
Merge remote-tracking branch 'origin' into feat/fygaro
Nodirbek75 Apr 28, 2026
73277be
Withdraw to section is implemented and added on the cashout confirma…
Nodirbek75 Apr 29, 2026
5f28f1d
use TransferOptionModal to show topup option on the TopupCashout scre…
Nodirbek75 Apr 29, 2026
66275f9
refactor and clean up topup/cashout flow updting structure
Nodirbek75 Apr 30, 2026
d5b80dc
Merge remote-tracking branch 'origin' into feat/fygaro
Nodirbek75 Apr 30, 2026
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
3 changes: 3 additions & 0 deletions app/assets/icons/arrow-down-to-bracket.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/icons/arrow-up-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/icons/arrow-up-from-bracket.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app/components/buttons/IconBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import QR from "@app/assets/icons/qr-code-new.svg"
import Setting from "@app/assets/icons/setting.svg"
import CardRemove from "@app/assets/icons/card-remove.svg"
import Dollar from "@app/assets/icons/dollar-new.svg"
import ArrowUpDown from "@app/assets/icons/arrow-up-down.svg"

const icons = {
up: ArrowUp,
Expand All @@ -19,6 +20,7 @@ const icons = {
setting: Setting,
cardRemove: CardRemove,
dollar: Dollar,
upDown: ArrowUpDown,
}

type IconNamesType = keyof typeof icons
Expand Down
5 changes: 0 additions & 5 deletions app/components/cashout-flow/index.ts

This file was deleted.

14 changes: 7 additions & 7 deletions app/components/home-screen/Buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ const Buttons: React.FC<Props> = ({ setModalVisible, setDefaultAccountModalVisib
})
}

// if (currentLevel === AccountLevel.Two) {
// buttons.push({
// title: LL.Cashout.title(),
// target: "CashoutDetails",
// icon: "dollar",
// })
// }
if (currentLevel === AccountLevel.Two || currentLevel === AccountLevel.Three) {
buttons.push({
title: LL.HomeScreen.transfer(),
target: "TopupCashout",
icon: "upDown",
})
}

return (
<Wrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { makeStyles, Text } from "@rneui/themed"

type Props = {
title: string
detail: string | number
detail?: string | number
}

const CashoutCard: React.FC<Props> = ({ title, detail }) => {
Expand Down
99 changes: 99 additions & 0 deletions app/components/topup-cashout-flow/CashoutWithdrawTo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, { useState } from "react"
import { TouchableOpacity, View } from "react-native"
import { Icon, makeStyles, Text, useTheme } from "@rneui/themed"

import { useI18nContext } from "@app/i18n/i18n-react"
import { useLatestAccountUpgradeRequestQuery } from "@app/graphql/generated"

const CashoutWithdrawTo: React.FC = () => {
const styles = useStyles()
const { colors } = useTheme().theme
const { LL } = useI18nContext()
const [expanded, setExpanded] = useState(false)

const { data } = useLatestAccountUpgradeRequestQuery({
fetchPolicy: "cache-first",
})

const bankAccount = data?.latestAccountUpgradeRequest.upgradeRequest?.bankAccount
console.log(">>>>>>>>>>>?????????", data)

if (!bankAccount) return null

const maskedAccount = `**********${String(bankAccount.accountNumber).slice(-4)}`

return (
<View>
<Text type="bl" bold>
{LL.Cashout.withdrawTo()}
</Text>
<TouchableOpacity
style={styles.card}
onPress={() => setExpanded(!expanded)}
activeOpacity={0.7}
>
<View style={styles.header}>
<Text type="bl">{maskedAccount}</Text>
<Icon
name={expanded ? "chevron-down" : "chevron-forward"}
type="ionicon"
size={20}
color={colors.grey3}
/>
</View>
{expanded && (
<View style={styles.details}>
<DetailRow label={LL.Cashout.bankName()} value={bankAccount.bankName} />
<DetailRow label={LL.Cashout.bankBranch()} value={bankAccount.bankBranch} />
<DetailRow
label={LL.Cashout.accountNumber()}
value={String(bankAccount.accountNumber)}
/>
<DetailRow label={LL.Cashout.accountType()} value={bankAccount.accountType} />
<DetailRow label={LL.Cashout.currency()} value={bankAccount.currency} />
</View>
)}
</TouchableOpacity>
</View>
)
}

const DetailRow: React.FC<{ label: string; value: string }> = ({ label, value }) => {
const styles = useStyles()
return (
<View style={styles.detailRow}>
<Text type="bm" style={styles.detailLabel}>
{label}
</Text>
<Text type="bm">{value}</Text>
</View>
)
}

export default CashoutWithdrawTo

const useStyles = makeStyles(({ colors }) => ({
card: {
borderRadius: 10,
marginTop: 5,
marginBottom: 15,
padding: 15,
backgroundColor: colors.grey5,
},
header: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
},
details: {
marginTop: 12,
},
detailRow: {
flexDirection: "row",
justifyContent: "space-between",
paddingVertical: 4,
},
detailLabel: {
color: colors.grey3,
},
}))
109 changes: 109 additions & 0 deletions app/components/topup-cashout-flow/TransferOptionModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React from "react"
import { Modal, TouchableOpacity, View } from "react-native"
import { Icon, Text, makeStyles, useTheme } from "@rneui/themed"
import { useSafeAreaInsets } from "react-native-safe-area-context"

export type TransferOption = {
icon: string
title: string
description: string
onPress: () => void
}

type Props = {
visible: boolean
title: string
options: TransferOption[]
onClose: () => void
}

const TransferOptionModal: React.FC<Props> = ({ visible, title, options, onClose }) => {
const styles = useStyles()
const { colors, mode } = useTheme().theme
const bottom = useSafeAreaInsets().bottom

return (
<Modal
animationType="slide"
transparent={true}
visible={visible}
onRequestClose={onClose}
>
<TouchableOpacity
style={[
styles.backdrop,
{
backgroundColor: mode === "dark" ? "rgba(57,57,57,.7)" : "rgba(0,0,0,.5)",
},
]}
activeOpacity={1}
onPress={onClose}
>
<View
style={[
styles.modalContainer,
{ backgroundColor: colors.white, paddingBottom: bottom || 10 },
]}
>
<View style={styles.modalHeader}>
<Text type="h01">{title}</Text>
<TouchableOpacity style={styles.closeBtn} onPress={onClose}>
<Icon name={"close"} size={30} color={colors.black} type="ionicon" />
</TouchableOpacity>
</View>
{options.map((option, index) => (
<TouchableOpacity key={index} style={styles.optionBtn} onPress={option.onPress}>
<Icon type="ionicon" name={option.icon} size={30} color={colors.black} />
<View style={styles.optionTextWrapper}>
<Text type="p1">{option.title}</Text>
<Text type="p3" color={colors.grey2}>
{option.description}
</Text>
</View>
<Icon type="ionicon" name={"chevron-forward"} size={20} />
</TouchableOpacity>
))}
</View>
</TouchableOpacity>
</Modal>
)
}

export default TransferOptionModal

const useStyles = makeStyles(({ colors }) => ({
backdrop: {
flex: 1,
justifyContent: "flex-end",
},
modalContainer: {
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingTop: 20,
paddingHorizontal: 20,
},
modalHeader: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
marginBottom: 15,
},
closeBtn: {
padding: 5,
},
optionBtn: {
flexDirection: "row",
alignItems: "center",
borderRadius: 15,
borderWidth: 1,
borderColor: colors.border01 || "#dedede",
marginBottom: 10,
paddingHorizontal: 15,
paddingVertical: 15,
},
optionTextWrapper: {
flex: 1,
rowGap: 3,
marginHorizontal: 15,
},
}))
8 changes: 8 additions & 0 deletions app/components/topup-cashout-flow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import CashoutFromWallet from "./CashoutFromWallet"
import CashoutPercentage from "./CashoutPercentage"
import CashoutCard from "./CashoutCard"
import CashoutWithdrawTo from "./CashoutWithdrawTo"

export { CashoutFromWallet, CashoutPercentage, CashoutCard, CashoutWithdrawTo }
export { default as TransferOptionModal } from "./TransferOptionModal"
export type { TransferOption } from "./TransferOptionModal"
58 changes: 28 additions & 30 deletions app/graphql/front-end-mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,36 +117,34 @@ gql`
}
}

# mutation RequestCashout($input: RequestCashoutInput!) {
# requestCashout(input: $input) {
# errors {
# code
# message
# path
# }
# offer {
# exchangeRate
# expiresAt
# flashFee
# offerId
# receiveJmd
# receiveUsd
# send
# walletId
# }
# }
# }

# mutation InitiateCashout($input: InitiateCashoutInput!) {
# initiateCashout(input: $input) {
# errors {
# path
# message
# code
# }
# success
# }
# }
mutation RequestCashout($input: RequestCashoutInput!) {
requestCashout(input: $input) {
errors {
code
message
}
offer {
exchangeRate
expiresAt
flashFee
offerId
receiveJmd
receiveUsd
send
walletId
}
}
}

mutation InitiateCashout($input: InitiateCashoutInput!) {
initiateCashout(input: $input) {
errors {
code
message
}
journalId
}
}

mutation accountDelete {
accountDelete {
Expand Down
34 changes: 34 additions & 0 deletions app/graphql/generated.gql
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ mutation IdDocumentUploadUrlGenerate($input: IdDocumentUploadUrlGenerateInput!)
}
}

mutation InitiateCashout($input: InitiateCashoutInput!) {
initiateCashout(input: $input) {
errors {
code
message
__typename
}
journalId
__typename
}
}

mutation MerchantMapSuggest($input: MerchantMapSuggestInput!) {
merchantMapSuggest(input: $input) {
errors {
Expand All @@ -119,6 +131,28 @@ mutation MerchantMapSuggest($input: MerchantMapSuggestInput!) {
}
}

mutation RequestCashout($input: RequestCashoutInput!) {
requestCashout(input: $input) {
errors {
code
message
__typename
}
offer {
exchangeRate
expiresAt
flashFee
offerId
receiveJmd
receiveUsd
send
walletId
__typename
}
__typename
}
}

mutation accountDelete {
accountDelete {
errors {
Expand Down
Loading