Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
81 changes: 72 additions & 9 deletions app/contexts/BreezContext.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
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,
checkLightningAddressAvailable,
} 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 = {
Expand Down Expand Up @@ -34,6 +44,14 @@ 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: "",
Expand Down Expand Up @@ -94,17 +112,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,6 +130,49 @@ 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 walletId = externalWalletRes.data?.updateExternalWallet.walletId
if (walletId) {
setBtcWallet((prev) => ({
...prev,
id: walletId,
}))
}
}

const ensureLightningAddress = async () => {
const username = meData?.me?.username
if (!username) return

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

if (existing) {
updateExternalWalletLnurlp(existing.lnurl.bech32)
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) {
updateExternalWalletLnurlp(res.lnurl.bech32)
}
} catch (err) {
console.warn("Failed to register Lightning address:", err)
}
}

const getBreezInfo = async () => {
if (initializingRef.current) return
initializingRef.current = true
Expand All @@ -122,6 +182,9 @@ export const BreezProvider = ({ children }: Props) => {
await updateBalance()
setLoading(false)

// Register Lightning address
await ensureLightningAddress()

// Trigger migration after Spark SDK is ready
if (!persistentState.sparkMigrationCompleted) {
await onMigrate()
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
}
}
`
2 changes: 2 additions & 0 deletions app/screens/import-wallet-screen/ImportWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useI18nContext } from "@app/i18n/i18n-react"
import { useCreateAccount } from "@app/hooks/useCreateAccount"
import { Text, useTheme, useThemeMode } from "@rneui/themed"
import { usePersistentStateContext } from "@app/store/persistent-state"
import { useAppConfig } from "@app/hooks/use-app-config"

// utils
import { disconnectToSDK, initializeBreezSDK } from "@app/utils/breez-sdk"
Expand All @@ -31,6 +32,7 @@ const ImportWallet: React.FC<Props> = ({ navigation, route }) => {
const { mode } = useThemeMode()
const { LL } = useI18nContext()
const { updateState } = usePersistentStateContext()
const { appConfig } = useAppConfig()
const { createDeviceAccountAndLogin } = useCreateAccount()

const inputRef = useRef<TextInput[]>([])
Expand Down
12 changes: 11 additions & 1 deletion app/screens/settings-screen/default-wallet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { gql } from "@apollo/client"
import { useSetDefaultWalletScreenQuery } from "@app/graphql/generated"
import {
useAccountUpdateDefaultWalletIdMutation,
useSetDefaultWalletScreenQuery,
} from "@app/graphql/generated"
import { useIsAuthed } from "@app/graphql/is-authed-context"
import { useI18nContext } from "@app/i18n/i18n-react"
import { Text, makeStyles } from "@rneui/themed"
Expand Down Expand Up @@ -54,6 +57,7 @@ export const DefaultWalletScreen: React.FC = () => {
fetchPolicy: "cache-first",
skip: !isAuthed,
})
const [updateDefaultWalletId] = useAccountUpdateDefaultWalletIdMutation()

const usdWallet = getUsdWallet(data?.me?.defaultAccount?.wallets)

Expand All @@ -73,6 +77,12 @@ export const DefaultWalletScreen: React.FC = () => {
defaultWallet = btcWallet
}

if (defaultWallet.id) {
await updateDefaultWalletId({
variables: { input: { walletId: defaultWallet.id } },
})
}

updateState((state: any) => {
if (state)
return {
Expand Down
1 change: 1 addition & 0 deletions app/types/declaration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ declare module "@env" {
export const GREENLIGHT_PARTNER_KEY: string
export const GOOGLE_PLACE_API_KEY: string
export const MIGRATION_FEE_LNURL_W: string
export const BREEZ_LNURL_DOMAIN: string
}
1 change: 0 additions & 1 deletion app/types/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ export const getTransactionStatus = (
tx: UnifiedTransaction,
): "SUCCESS" | "PENDING" | "FAILURE" => {
if (isBreezTransaction(tx)) {
// PaymentStatus: Completed = 0, Pending = 1, Failed = 2
switch (tx.payment.status) {
case 0:
case PaymentStatus.Completed:
Expand Down
36 changes: 33 additions & 3 deletions app/utils/breez-sdk/spark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ import type {
RecommendedFees,
SendPaymentMethod,
LnurlPayResponse,
LightningAddressInfo,
Payment,
Logger,
LogEntry,
} from "@breeztech/breez-sdk-spark-react-native"
import { API_KEY } from "@env"
import { API_KEY, BREEZ_LNURL_DOMAIN } from "@env"
import { appendLog, initLogBuffer } from "./log-buffer"

// Constants
Expand Down Expand Up @@ -67,7 +68,7 @@ export const initializeBreezSDK = async (): Promise<boolean> => {

breezSDKInitializing = (async () => {
try {
await retry(connectToSDK, 5000, 3)
await retry(() => connectToSDK(), 5000, 3)
breezSDKInitialized = true
return true
} catch (error: unknown) {
Expand Down Expand Up @@ -120,6 +121,7 @@ const connectToSDK = async (): Promise<void> => {

const config = defaultConfig(Network.Mainnet)
config.apiKey = API_KEY
config.lnurlDomain = BREEZ_LNURL_DOMAIN
config.maxDepositClaimFee = new MaxFee.NetworkRecommended({
leewaySatPerVbyte: BigInt(1),
})
Expand Down Expand Up @@ -174,7 +176,7 @@ export const getInfo = async () => {
const sdk = getSDKInstance()
const info = await sdk.getInfo({ ensureSynced: true })

return Number(info.balanceSats)
return info
}

// Fee Estimation
Expand Down Expand Up @@ -624,3 +626,31 @@ export const refundDeposit = async (
return { success: false, error: message }
}
}

// Lightning Address (LNURL-Pay)
export const checkLightningAddressAvailable = async (
username: string,
): Promise<boolean> => {
const sdk = getSDKInstance()
return sdk.checkLightningAddressAvailable({ username })
}

export const registerLightningAddress = async (
username: string,
description?: string,
): Promise<LightningAddressInfo> => {
const sdk = getSDKInstance()
return sdk.registerLightningAddress({ username, description })
}

export const getLightningAddress = async (): Promise<
LightningAddressInfo | undefined
> => {
const sdk = getSDKInstance()
return sdk.getLightningAddress()
}

export const deleteLightningAddress = async (): Promise<void> => {
const sdk = getSDKInstance()
await sdk.deleteLightningAddress()
}
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ PODS:
- breez_sdk_liquidFFI (0.11.13)
- BreezSDKLiquid (0.11.13):
- breez_sdk_liquidFFI (= 0.11.13)
- BreezSdkSparkReactNative (0.13.4):
- breeztech-breez-sdk-spark-react-native (0.7.14):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -3013,7 +3013,7 @@ SPEC CHECKSUMS:
breez_sdk_liquid: 5c229f9ab3bcf6b648bbf2d512f6fe1eee96d121
breez_sdk_liquidFFI: f05fadc0611126ade76d1fe6761ed8b020aabefb
BreezSDKLiquid: ee6bf5a57f1b2533dc3c14c24c9773496f17b756
BreezSdkSparkReactNative: 22459556b92935587708d1e8f875a59fad16005f
breeztech-breez-sdk-spark-react-native: 0af390a27a5f95bc838cddbecead825b671f60b2
BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
fast_float: 06eeec4fe712a76acc9376682e4808b05ce978b6
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1334,10 +1334,10 @@
dependencies:
"@noble/curves" "^1.7.0"

"@breeztech/breez-sdk-spark-react-native@^0.13.4":
version "0.13.4"
resolved "https://registry.yarnpkg.com/@breeztech/breez-sdk-spark-react-native/-/breez-sdk-spark-react-native-0.13.4.tgz#7c5429a677547fcbe3aef4fcb299c159e0ff1641"
integrity sha512-wspP9tXY4GDJWVH42xI3dhe+MS5ROYX0a2mOqHKLWGcFqQc+Yuf77NaPBhZqM3FDKxVvZkDtAhCDuqDJ4vaclQ==
"@breeztech/breez-sdk-spark-react-native@^0.7.14":
version "0.7.14"
resolved "https://registry.yarnpkg.com/@breeztech/breez-sdk-spark-react-native/-/breez-sdk-spark-react-native-0.7.14.tgz#b8914719e67620aa6b85178d7a903d7efcaedbac"
integrity sha512-xHhcwD0/aDQAGg6mJM1K1Wepp3bmf3SnuK7tIC2jSX7VA308lB92u6ag3vIQMvAtz6mZptu+8Le+br9sr2u4/w==
dependencies:
uniffi-bindgen-react-native "^0.29.3-1"

Expand Down