Skip to content

Commit

Permalink
Fix duplicate processing of NWC commands in fallback websocket mode
Browse files Browse the repository at this point in the history
  • Loading branch information
minibits-cash committed Aug 28, 2024
1 parent 53e30d4 commit d29ee42
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "minibits_wallet",
"version": "0.1.8-beta.58",
"version": "0.1.8-beta.59",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
Expand Down
10 changes: 8 additions & 2 deletions src/models/NwcStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,11 @@ export const NwcStoreModel = types
walletPubkey: self.walletPubkey
})

if(self.nwcConnections.length === 0) {
log.trace('[receiveNwcEvents] No NWC connections, skipping subscription...')
return
}

// reset daily limits if day changed
for (const c of self.nwcConnections) {
if(!isSameDay(c.currentDay, new Date())) {
Expand All @@ -729,7 +734,7 @@ export const NwcStoreModel = types

try {
const since = Math.floor(Date.now() / 1000)
const connectionsPubkeys = self.nwcConnections.map(c => c.connectionPubkey)
const connectionsPubkeys = self.nwcConnections.map(c => c.connectionPubkey)

const filters = [{
kinds: [NwcKind.request],
Expand Down Expand Up @@ -782,7 +787,8 @@ export const NwcStoreModel = types
)

if(!targetConnection) {
throw new AppError(Err.VALIDATION_ERROR, 'Missing connection matching event pubkey', {pubkey: event.pubkey})
log.error('[handleNwcRequestFromNotification] Missing connection matching event pubkey.', {pubkey: event.pubkey})
return
}

yield targetConnection.handleRequest(event)
Expand Down
31 changes: 22 additions & 9 deletions src/screens/NwcScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { moderateVerticalScale, verticalScale } from '@gocodingnow/rn-size-matte
import { NwcConnection } from '../models/NwcStore'
import { QRCodeBlock } from './Wallet/QRCode'
import { CollapsibleText } from '../components/CollapsibleText'
import { NotificationService } from '../services/notificationService'
import { isSameDay } from 'date-fns/isSameDay'

interface SettingsScreenProps extends SettingsStackScreenProps<'Nwc'> {}

Expand All @@ -35,28 +35,41 @@ export const NwcScreen: FC<SettingsScreenProps> = observer(
const [info, setInfo] = useState('')
const [error, setError] = useState<AppError | undefined>()
const [isLoading, setIsLoading] = useState(false)
const [areNotificationsEnabled, setAreNotificationsEnabled] = useState<boolean>(false)
const [isRemoteDataPushEnabled, setIsRemoteDataPushEnabled] = useState<boolean>(false)

useHeader({
leftIcon: 'faArrowLeft',
onLeftPress: () => navigation.goBack(),
rightIcon: areNotificationsEnabled ? 'faRotate' : undefined,
onRightPress: () => areNotificationsEnabled ? onConnect() : false
rightIcon: isRemoteDataPushEnabled ? 'faRotate' : undefined,
onRightPress: () => isRemoteDataPushEnabled ? onConnect() : false
})

useEffect(() => {
const getNotificationPermission = async () => {
try {
const permissionGranted = await NotificationService.areNotificationsEnabled()
try {
const remoteEnabled = walletProfileStore.device ? true : false
setAreNotificationsEnabled(permissionGranted && remoteEnabled)
setIsRemoteDataPushEnabled(remoteEnabled)
} catch (e: any) {
log.warn(e.name, e.message)
return false // silent
}
}
getNotificationPermission()
}, [])


useEffect(() => {
const resetDailyLimits = async () => {
// reset daily limits if day changed
for (const c of nwcStore.nwcConnections) {
if(!isSameDay(c.currentDay, new Date())) {
c.setRemainingDailyLimit(c.dailyLimit)
c.setCurrentDay()
}
}
}
resetDailyLimits()
}, [])

const toggleAddConnectionModal = () => {
setIsAddConnectionModalVisible(previousState => !previousState)
Expand Down Expand Up @@ -100,11 +113,11 @@ export const NwcScreen: FC<SettingsScreenProps> = observer(
const onConnect = async function () {
log.trace('onConnect')

if(!areNotificationsEnabled) {
if(!isRemoteDataPushEnabled) {
setSelectedConnection(undefined)
nwcStore.receiveNwcEvents()
setInfo(`
Your device has no push notifications enabled. This is essential to recieve NWC commands.
Your device can not receive background push messages. This is essential to recieve NWC commands.
As a fallback, Minibits subscribed to Nostr relays to receive the commands.
However, this will stop working when app is in the background or off.
`)
Expand Down
16 changes: 8 additions & 8 deletions src/screens/RelaysScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,27 @@ export const RelaysScreen: FC<SettingsScreenProps> = observer(
})

const newRelayInputRef = useRef<TextInput>(null)
const {relaysStore, nwcStore} = useStores()
const {relaysStore, nwcStore, walletProfileStore} = useStores()

const [selectedRelay, setSelectedRelay] = useState<Relay | undefined>()
const [isAddRelayModalVisible, setIsAddRelayModalVisible] = useState(false)
const [newPublicRelay, setNewPublicRelay] = useState<string>('')
const [info, setInfo] = useState('')
const [error, setError] = useState<AppError | undefined>()
const [areNotificationsEnabled, setAreNotificationsEnabled] = useState<boolean>(false)
const [isRemoteDataPushEnabled, setIsRemoteDataPushEnabled] = useState<boolean>(false)

useEffect(() => {
const getNotificationPermission = async () => {
try {
const enabled = await NotificationService.areNotificationsEnabled()
setAreNotificationsEnabled(enabled)
try {
const remoteEnabled = walletProfileStore.device ? true : false
setIsRemoteDataPushEnabled(remoteEnabled)
} catch (e: any) {
log.warn(e.name, e.message)
return false // silent
}
}
getNotificationPermission()
}, [])
}, [])

const toggleAddRelayModal = () => {
setIsAddRelayModalVisible(previousState => !previousState)
Expand Down Expand Up @@ -77,8 +77,8 @@ export const RelaysScreen: FC<SettingsScreenProps> = observer(
// Full force re-subscription, not just reconnect
WalletTask.receiveEventsFromRelays().catch(e => false)

// Subscribe to NWC events as well as a push notifications fallback
if(!areNotificationsEnabled) {
// Subscribe to NWC events if we have some connections
if(!isRemoteDataPushEnabled) {
nwcStore.receiveNwcEvents()
}
setSelectedRelay(undefined)
Expand Down
8 changes: 4 additions & 4 deletions src/screens/WalletScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ export const WalletScreen: FC<WalletScreenProps> = observer(
pagerRef.current && pagerRef.current.setPage(pageIndex)

// Create websocket subscriptions to receive NWC requests from remote wallets (if any)
// go through websockets only if notifications are disabled or not working
const permissionGranted = await NotificationService.areNotificationsEnabled()
const remoteEnabled = walletProfileStore.device ? true : false
if((permissionGranted && remoteEnabled) === false) {nwcStore.receiveNwcEvents()}
// go through websockets only if remote notifications not working as push data messages are
// delivered even if notifications are disabled on device
const isRemoteDataPushEnabled = walletProfileStore.device ? true : false
if(!isRemoteDataPushEnabled) {nwcStore.receiveNwcEvents()}
}

Linking.addEventListener('url', handleDeeplink)
Expand Down

0 comments on commit d29ee42

Please sign in to comment.