Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6fb1dc9
Configure flashapp.me domain in the SDK by passing the lnurlDomain pa…
Nodirbek75 Mar 23, 2026
02bcae7
update ImportWallet and BreezContext to register username as a lightn…
Nodirbek75 Mar 23, 2026
a9ac594
register lightning address username+walletId
Nodirbek75 Mar 30, 2026
bf4c972
configure BREEZ_LNURL_DOMAIN into spark sdk
Nodirbek75 Mar 30, 2026
ea62bda
update breez-sdk-spark to the latest version and implement the changes
Nodirbek75 Mar 30, 2026
7b4840e
Merge remote-tracking branch 'origin' into feat/breez-lightning-address
Nodirbek75 Mar 30, 2026
de2ed98
Merge remote-tracking branch 'origin' into feat/breez-lightning-address
Nodirbek75 May 7, 2026
232d3e5
Merge remote-tracking branch 'origin' into feat/breez-lightning-address
Nodirbek75 May 8, 2026
9d12ab4
update BreezContext logic to add breez btc wallet as external wallet …
Nodirbek75 May 12, 2026
6a5084f
use accountUpdateDefaultWalletId mutation to update the default walle…
Nodirbek75 May 12, 2026
d2ecb4e
updateExternalWallet mutation is added
Nodirbek75 May 12, 2026
ab0bfd2
add isExternal prop for wallet type and implement getInternalWallets …
Nodirbek75 May 19, 2026
d6b8fb2
use getInternalWallets method to filter internal wallets on the send-…
Nodirbek75 May 19, 2026
90f9394
update util methods after changing balance nullable
Nodirbek75 May 19, 2026
b2218d1
remove deleteUser supabase method on the account screen
Nodirbek75 May 19, 2026
42f2294
test the breez btc wallet lightning address end to end
Nodirbek75 May 22, 2026
352619d
Stabilize Breez external wallet setup
forge0x May 22, 2026
f0acdf2
Route BTC default usernames via LNURL
forge0x May 22, 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
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import { useBreez } from "@app/hooks"
import { useApolloClient } from "@apollo/client"
import { useI18nContext } from "@app/i18n/i18n-react"
import { useNavigation } from "@react-navigation/native"
import { useSetDefaultAccountModalQuery } from "@app/graphql/generated"
import {
useAccountUpdateDefaultWalletIdMutation,
useSetDefaultAccountModalQuery,
} from "@app/graphql/generated"
import { usePersistentStateContext } from "@app/store/persistent-state"

// utils
Expand All @@ -34,17 +37,23 @@ export const SetDefaultAccountModal = ({ isVisible, toggleModal }: Props) => {
const { LL } = useI18nContext()
const { btcWallet } = useBreez()
const { updateState } = usePersistentStateContext()
const [updateDefaultWalletId] = useAccountUpdateDefaultWalletIdMutation()

const { data } = useSetDefaultAccountModalQuery({
fetchPolicy: "cache-only",
})
const usdWallet = getUsdWallet(data?.me?.defaultAccount?.wallets)

const onPressHandler = (currency: string) => {
const onPressHandler = async (currency: string) => {
let defaultWallet = usdWallet
if (currency === "BTC") {
defaultWallet = btcWallet
}
if (defaultWallet?.id) {
await updateDefaultWalletId({
variables: { input: { walletId: defaultWallet.id } },
})
}
updateState((state: any) => {
if (state)
return {
Expand Down
143 changes: 133 additions & 10 deletions app/contexts/BreezContext.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
import React, { createContext, useEffect, useRef, useState } from "react"
import { WalletCurrency } from "@app/graphql/generated"
import { useUpdateExternalWalletMutation, WalletCurrency } from "@app/graphql/generated"
import { usePersistentStateContext } from "@app/store/persistent-state"
import { Alert, Platform } from "react-native"
import { v4 as uuidv4 } from "uuid"
import { initializeBreezSDK, getInfo, handleSparkMigration } from "@app/utils/breez-sdk"
import {
initializeBreezSDK,
getInfo,
handleSparkMigration,
registerLightningAddress,
getLightningAddress,
} from "@app/utils/breez-sdk"
import { useAppConfig } from "@app/hooks/use-app-config"
import { useAddressScreenQuery } from "@app/graphql/generated"
import { useIsAuthed } from "@app/graphql/is-authed-context"
import SparkMigrationModal from "@app/components/spark-migration-modal"

type BtcWallet = {
id: string
walletCurrency: WalletCurrency
balance: number
isExternal: boolean
}

interface BreezInterface {
refreshBreez: () => void
retryExternalWalletRegistration: () => Promise<void>
loading: boolean
externalWalletLoading: boolean
externalWalletError?: string
btcWallet: BtcWallet
}

export const BreezContext = createContext<BreezInterface>({
refreshBreez: () => {},
retryExternalWalletRegistration: async () => {},
loading: false,
externalWalletLoading: false,
externalWalletError: undefined,
btcWallet: {
id: "",
walletCurrency: "BTC",
balance: 0,
isExternal: true,
},
})

Expand All @@ -34,17 +51,30 @@ type Props = {

export const BreezProvider = ({ children }: Props) => {
const { persistentState, updateState } = usePersistentStateContext()
const { appConfig } = useAppConfig()
const isAuthed = useIsAuthed()
const { data: meData } = useAddressScreenQuery({
fetchPolicy: "cache-first",
skip: !isAuthed,
})
const [updateExternalWallet] = useUpdateExternalWalletMutation()

const [loading, setLoading] = useState(false)
const [btcWallet, setBtcWallet] = useState<BtcWallet>({
id: "",
walletCurrency: "BTC",
balance: persistentState.breezBalance || 0,
isExternal: true,
})
const initializingRef = useRef(false)
const updatingBalanceRef = useRef(false)
const registeringExternalWalletRef = useRef(false)
const [migrating, setMigrating] = useState(false)
const [migrationModal, setMigrationModal] = useState(false)
const [migrationErr, setMigrationErr] = useState<string | undefined>()
const [externalWalletLoading, setExternalWalletLoading] = useState(false)
const [externalWalletError, setExternalWalletError] = useState<string | undefined>()
const [breezReady, setBreezReady] = useState(false)

const onMigrate = async () => {
setMigrating(true)
Expand Down Expand Up @@ -85,7 +115,9 @@ export const BreezProvider = ({ children }: Props) => {
id: "",
walletCurrency: "BTC",
balance: 0,
isExternal: true,
})
setExternalWalletError(undefined)
}
}
}, [persistentState.isAdvanceMode])
Expand All @@ -94,17 +126,16 @@ export const BreezProvider = ({ children }: Props) => {
if (updatingBalanceRef.current) return
updatingBalanceRef.current = true
try {
const balanceSats = await getInfo()
setBtcWallet({
id: uuidv4(),
walletCurrency: WalletCurrency.Btc,
balance: balanceSats,
})
const walletInfo = await getInfo()
setBtcWallet((prev) => ({
...prev,
balance: Number(walletInfo.balanceSats),
}))
updateState((state: any) => {
if (state)
return {
...state,
breezBalance: balanceSats,
breezBalance: Number(walletInfo.balanceSats),
}
return undefined
})
Expand All @@ -113,15 +144,98 @@ export const BreezProvider = ({ children }: Props) => {
}
}

const updateExternalWalletLnurlp = async (lnurlp: string) => {
const externalWalletRes = await updateExternalWallet({
variables: { input: { lnurlp } },
})
console.log("Update External Wallet Response: ", externalWalletRes)
const errors = externalWalletRes.data?.updateExternalWallet.errors
if (errors?.length) {
throw new Error(errors.map((error) => error.message).join(", "))
}

const walletId = externalWalletRes.data?.updateExternalWallet.walletId
if (walletId) {
setBtcWallet((prev) => ({
...prev,
id: walletId,
}))
}

return walletId
}

const ensureLightningAddress = async () => {
const username = meData?.me?.username
if (registeringExternalWalletRef.current || btcWallet.id) return
if (!username) return

registeringExternalWalletRef.current = true
setExternalWalletLoading(true)
setExternalWalletError(undefined)

try {
const existing = await getLightningAddress()
console.log("BREEZ LIGHTNING ADDRESS: ", existing)

if (existing) {
const walletId = await updateExternalWalletLnurlp(existing.lnurl.bech32)
if (!walletId) {
throw new Error("External wallet registration returned no wallet id")
}
return
}

// Register with username as the Lightning address
const lightningAddress = username + uuidv4()
const res = await registerLightningAddress(
lightningAddress,
`Pay to ${username}@${appConfig.galoyInstance.lnAddressHostname}`,
)
console.log("BREEZ LIGHTNING ADDRESS RES: ", res)

if (res) {
const walletId = await updateExternalWalletLnurlp(res.lnurl.bech32)
if (!walletId) {
throw new Error("External wallet registration returned no wallet id")
}
return
}

throw new Error("Breez lightning address registration returned no address")
} catch (err) {
const message = err instanceof Error ? err.message : String(err)
setExternalWalletError(message)
console.warn("Failed to register Lightning address:", message)
} finally {
setExternalWalletLoading(false)
registeringExternalWalletRef.current = false
}
}

useEffect(() => {
if (Platform.OS === "ios" && Number(Platform.Version) < 13) return
if (!persistentState.isAdvanceMode) return
if (!breezReady) return
if (!meData?.me?.username) return
if (btcWallet.id) return

ensureLightningAddress()
}, [persistentState.isAdvanceMode, breezReady, meData?.me?.username, btcWallet.id])

const getBreezInfo = async () => {
if (initializingRef.current) return
initializingRef.current = true
try {
setLoading(true)
await initializeBreezSDK()
setBreezReady(true)
await updateBalance()
setLoading(false)

// Register Lightning address
await ensureLightningAddress()

// Trigger migration after Spark SDK is ready
if (!persistentState.sparkMigrationCompleted) {
await onMigrate()
Expand All @@ -141,7 +255,16 @@ export const BreezProvider = ({ children }: Props) => {
}

return (
<BreezContext.Provider value={{ btcWallet, loading, refreshBreez }}>
<BreezContext.Provider
value={{
btcWallet,
loading,
externalWalletLoading,
externalWalletError,
refreshBreez,
retryExternalWalletRegistration: ensureLightningAddress,
}}
>
{children}
<SparkMigrationModal
isVisible={migrationModal}
Expand Down
1 change: 1 addition & 0 deletions app/graphql/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}

Expand Down
10 changes: 10 additions & 0 deletions app/graphql/front-end-mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,14 @@ gql`
uploadUrl
}
}

mutation UpdateExternalWallet($input: UpdateExternalWalletInput!) {
updateExternalWallet(input: $input) {
errors {
code
message
}
walletId
}
}
`
10 changes: 10 additions & 0 deletions app/graphql/front-end-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}
}
Expand Down Expand Up @@ -83,6 +84,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}
}
Expand All @@ -97,6 +99,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}
}
Expand All @@ -111,6 +114,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}
}
Expand All @@ -135,6 +139,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}
}
Expand All @@ -150,6 +155,7 @@ gql`
id
wallets {
id
isExternal
}
}
contacts {
Expand All @@ -162,6 +168,7 @@ gql`
query accountDefaultWallet($username: Username!) {
accountDefaultWallet(username: $username) {
id
walletCurrency
}
}

Expand All @@ -178,6 +185,7 @@ gql`
id
walletCurrency
balance
isExternal
}
}
}
Expand Down Expand Up @@ -224,6 +232,7 @@ gql`
id
balance
walletCurrency
isExternal
}
}
}
Expand All @@ -245,6 +254,7 @@ gql`
id
wallets {
id
isExternal
}
}
contacts {
Expand Down
Loading