Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 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
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
2 changes: 1 addition & 1 deletion app/components/cashout-flow/CashoutCard.tsx
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
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: "BuySellBitcoin",
icon: "upDown",
})
}

return (
<Wrapper>
Expand Down
60 changes: 30 additions & 30 deletions app/graphql/front-end-mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,36 +117,36 @@ 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
path
}
offer {
exchangeRate
expiresAt
flashFee
offerId
receiveJmd
receiveUsd
send
walletId
}
}
}

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

mutation accountDelete {
accountDelete {
Expand Down
36 changes: 36 additions & 0 deletions app/graphql/generated.gql
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ fragment TransactionList on TransactionConnection {
__typename
}

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

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

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

mutation accountDelete {
accountDelete {
errors {
Expand Down
99 changes: 99 additions & 0 deletions app/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,20 @@ export type MerchantMapSuggestMutationVariables = Exact<{

export type MerchantMapSuggestMutation = { readonly __typename: 'Mutation', readonly merchantMapSuggest: { readonly __typename: 'MerchantPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly code?: string | null, readonly message: string, readonly path?: ReadonlyArray<string | null> | null }>, readonly merchant?: { readonly __typename: 'Merchant', readonly createdAt: number, readonly id: string, readonly title: string, readonly username: string, readonly validated: boolean, readonly coordinates: { readonly __typename: 'Coordinates', readonly latitude: number, readonly longitude: number } } | null } };

export type RequestCashoutMutationVariables = Exact<{
input: RequestCashoutInput;
}>;


export type RequestCashoutMutation = { readonly __typename: 'Mutation', readonly requestCashout: { readonly __typename: 'RequestCashoutResponse', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly code?: string | null, readonly message: string, readonly path?: ReadonlyArray<string | null> | null }>, readonly offer?: { readonly __typename: 'CashoutOffer', readonly exchangeRate: number, readonly expiresAt: number, readonly flashFee: number, readonly offerId: string, readonly receiveJmd: number, readonly receiveUsd: number, readonly send: number, readonly walletId: string } | null } };

export type InitiateCashoutMutationVariables = Exact<{
input: InitiateCashoutInput;
}>;


export type InitiateCashoutMutation = { readonly __typename: 'Mutation', readonly initiateCashout: { readonly __typename: 'SuccessPayload', readonly success?: boolean | null, readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly path?: ReadonlyArray<string | null> | null, readonly message: string, readonly code?: string | null }> } };

export type AccountDeleteMutationVariables = Exact<{ [key: string]: never; }>;


Expand Down Expand Up @@ -3506,6 +3520,91 @@ export function useMerchantMapSuggestMutation(baseOptions?: Apollo.MutationHookO
export type MerchantMapSuggestMutationHookResult = ReturnType<typeof useMerchantMapSuggestMutation>;
export type MerchantMapSuggestMutationResult = Apollo.MutationResult<MerchantMapSuggestMutation>;
export type MerchantMapSuggestMutationOptions = Apollo.BaseMutationOptions<MerchantMapSuggestMutation, MerchantMapSuggestMutationVariables>;
export const RequestCashoutDocument = gql`
mutation RequestCashout($input: RequestCashoutInput!) {
requestCashout(input: $input) {
errors {
code
message
path
}
offer {
exchangeRate
expiresAt
flashFee
offerId
receiveJmd
receiveUsd
send
walletId
}
}
}
`;
export type RequestCashoutMutationFn = Apollo.MutationFunction<RequestCashoutMutation, RequestCashoutMutationVariables>;

/**
* __useRequestCashoutMutation__
*
* To run a mutation, you first call `useRequestCashoutMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useRequestCashoutMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [requestCashoutMutation, { data, loading, error }] = useRequestCashoutMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useRequestCashoutMutation(baseOptions?: Apollo.MutationHookOptions<RequestCashoutMutation, RequestCashoutMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<RequestCashoutMutation, RequestCashoutMutationVariables>(RequestCashoutDocument, options);
}
export type RequestCashoutMutationHookResult = ReturnType<typeof useRequestCashoutMutation>;
export type RequestCashoutMutationResult = Apollo.MutationResult<RequestCashoutMutation>;
export type RequestCashoutMutationOptions = Apollo.BaseMutationOptions<RequestCashoutMutation, RequestCashoutMutationVariables>;
export const InitiateCashoutDocument = gql`
mutation InitiateCashout($input: InitiateCashoutInput!) {
initiateCashout(input: $input) {
errors {
path
message
code
}
success
}
}
`;
export type InitiateCashoutMutationFn = Apollo.MutationFunction<InitiateCashoutMutation, InitiateCashoutMutationVariables>;

/**
* __useInitiateCashoutMutation__
*
* To run a mutation, you first call `useInitiateCashoutMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useInitiateCashoutMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [initiateCashoutMutation, { data, loading, error }] = useInitiateCashoutMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useInitiateCashoutMutation(baseOptions?: Apollo.MutationHookOptions<InitiateCashoutMutation, InitiateCashoutMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<InitiateCashoutMutation, InitiateCashoutMutationVariables>(InitiateCashoutDocument, options);
}
export type InitiateCashoutMutationHookResult = ReturnType<typeof useInitiateCashoutMutation>;
export type InitiateCashoutMutationResult = Apollo.MutationResult<InitiateCashoutMutation>;
export type InitiateCashoutMutationOptions = Apollo.BaseMutationOptions<InitiateCashoutMutation, InitiateCashoutMutationVariables>;
export const AccountDeleteDocument = gql`
mutation accountDelete {
accountDelete {
Expand Down
63 changes: 62 additions & 1 deletion app/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ const en: BaseTranslation = {
balance: "Refresh Balance",
showQrCode: "Topup via QR",
send: "Send",
transfer: "Transfer",
sweep: "Sweep to Wallet",
pay: "Pay",
title: "Home",
Expand Down Expand Up @@ -565,6 +566,62 @@ const en: BaseTranslation = {
backupTitle: "Backup your BTC wallet",
backupDesc: "Backup and secure your Bitcoin wallet using recovery phrase."
},
TopUpScreen: {
title: "Top Up",
bankTransfer: "Bank Transfer",
bankTransferDesc: "Transfer funds from your bank",
debitCreditCard: "Debit/Credit Card",
debitCreditCardDesc: "Pay with your debit or credit card"
},
BuyBitcoinDetails: {
title: "Card Payment",
bankTransfer: "Bank Transfer",
email: "Email",
emailPlaceholder: "Enter your email address",
wallet: "Wallet",
walletPlaceholder: "Select wallet",
amount: "Amount (USD)",
amountPlaceholder: "Enter amount",
continue: "Continue",
usdWallet: "USD Wallet",
btcWallet: "BTC Wallet",
invalidEmail: "Please enter a valid email address",
invalidAmount: "Please enter a valid amount",
minimumAmount: "Minimum amount is $1.00"
},
FygaroWebViewScreen: {
title: "Fygaro Payment",
loading: "Loading payment page...",
error: "Failed to load payment page",
retry: "Retry"
},
BankTransfer: {
title: "Bank Transfer",
desc1: "Your order has been created. To complete the order, please transfer ${amount: number} USD to the bank details provided below.",
desc2: "Use {code: string} as the reference description. This unique code will help us associate the payment with your Flash account and process the Bitcoin transfer.",
desc3: "After we have received your payment, you will be credited with ${amount: number} USD in your Cash wallet, with a ${fee: number} USD fee deducted. You can then choose when you convert those USD to Bitcoin on your own using the Convert functionality in the mobile app.",
accountType: "Account Type",
destinationBank: "Destination Bank",
accountNumber: "Account Number",
typeOfClient: "Type of Client",
receiverName: "Receiver's Name",
email: "Email",
amount: "Amount",
uniqueCode: "Unique Code",
fees: "Fees",
desc4: "After payment completion on your end you can send us an email to {email: string} with a screenshot of your payment confirmation.",
desc5: "Your payment will be processed even if we don't receive this email, but having this confirmation can help accelerate the order.",
backHome: "Back to Home"
},
PaymentSuccessScreen: {
title: "Payment Successful",
successMessage: "Your payment has been processed successfully",
amountSent: "Amount Sent",
depositedTo: "Deposited to",
transactionId: "Transaction ID",
done: "Done",
viewTransaction: "View Transaction"
},
PinScreen: {
attemptsRemaining: "Incorrect PIN. {attemptsRemaining: number} attempts remaining.",
oneAttemptRemaining: "Incorrect PIN. 1 attempt remaining.",
Expand Down Expand Up @@ -1086,6 +1143,10 @@ const en: BaseTranslation = {
TransferScreen: {
title: "Transfer",
percentageToConvert: "% to convert",
topUp: "Top Up",
topUpDesc: "Add funds to your wallet",
settle: "Settle",
settleDesc: "Cashout funds from your wallet"
},
UpgradeAccountModal: {
title: "Upgrade your account",
Expand Down Expand Up @@ -1337,7 +1398,7 @@ const en: BaseTranslation = {
email: "Email",
enjoyingApp: "Enjoying the app?",
statusPage: "Status Page",
//telegram: "Telegram",
// telegram: "Telegram",
discord: "Discord",
mattermost: "Mattermost",
thankYouText: "Thank you for the feedback, would you like to suggest an improvement?",
Expand Down
Loading