mirror of
https://github.com/KoalaSat/nostros.git
synced 2024-09-28 22:30:41 +00:00
LnBits integration
This commit is contained in:
parent
f95a62be52
commit
ee62d25340
@ -25,7 +25,7 @@ export const MenuItems: React.FC = () => {
|
||||
const [drawerItemIndex, setDrawerItemIndex] = React.useState<number>(-1)
|
||||
const { getSatoshiSymbol } = React.useContext(AppContext)
|
||||
const { relays } = React.useContext(RelayPoolContext)
|
||||
const { balance, active } = React.useContext(WalletContext)
|
||||
const { balance, type } = React.useContext(WalletContext)
|
||||
const {
|
||||
nPub,
|
||||
publicKey,
|
||||
@ -154,7 +154,7 @@ export const MenuItems: React.FC = () => {
|
||||
onPress={() => onPressItem('wallet', 1)}
|
||||
onTouchEnd={() => setDrawerItemIndex(-1)}
|
||||
right={() => {
|
||||
if (!active) return <></>
|
||||
if (!type || !balance) return <></>
|
||||
return (
|
||||
<Text>
|
||||
{`${balance} `}
|
||||
|
@ -1,31 +1,20 @@
|
||||
import axios from 'axios'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import SInfo from 'react-native-sensitive-info'
|
||||
|
||||
export interface LndHub {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface WalletAction {
|
||||
id: string
|
||||
monto: number
|
||||
type: 'invoice' | 'transaction'
|
||||
description: string
|
||||
timestamp: number
|
||||
}
|
||||
import type WalletAction from '../lib/Lightning'
|
||||
import LnBits, { type LnBitsConfig } from '../lib/Lightning/LnBits'
|
||||
import LndHub, { type LndHubConfig } from '../lib/Lightning/LndHub'
|
||||
|
||||
export interface WalletContextProps {
|
||||
active: boolean
|
||||
updatedAt?: number
|
||||
lndHub?: LndHub
|
||||
setLndHub: (lndHub: LndHub) => void
|
||||
type?: string
|
||||
setType: (type: string) => void
|
||||
updatedAt?: string
|
||||
lndHub?: LndHubConfig | LnBitsConfig
|
||||
balance?: number
|
||||
transactions: WalletAction[]
|
||||
invoices: WalletAction[]
|
||||
refreshLndHub: (login?: string, password?: string, uri?: string) => void
|
||||
updateWallet: () => Promise<void>
|
||||
refreshWallet: (params?: object, type?: string) => void
|
||||
payInvoice: (invoice: string) => Promise<boolean>
|
||||
logoutWallet: () => void
|
||||
}
|
||||
@ -35,18 +24,18 @@ export interface WalletContextProviderProps {
|
||||
}
|
||||
|
||||
export const initialWalletContext: WalletContextProps = {
|
||||
active: false,
|
||||
setLndHub: () => {},
|
||||
transactions: [],
|
||||
invoices: [],
|
||||
refreshLndHub: () => {},
|
||||
setType: () => {},
|
||||
updateWallet: async () => {},
|
||||
refreshWallet: () => {},
|
||||
payInvoice: async () => false,
|
||||
logoutWallet: () => {},
|
||||
}
|
||||
|
||||
export const WalletContextProvider = ({ children }: WalletContextProviderProps): JSX.Element => {
|
||||
const [active, setActive] = React.useState<boolean>(initialWalletContext.active)
|
||||
const [lndHub, setLndHub] = useState<LndHub>()
|
||||
const [type, setType] = React.useState<string>()
|
||||
const [config, setConfig] = useState<LndHubConfig | LnBitsConfig>()
|
||||
const [balance, setBalance] = useState<number>()
|
||||
const [updatedAt, setUpdatedAt] = useState<string>()
|
||||
const [transactions, setTransactions] = useState<WalletAction[]>(
|
||||
@ -57,119 +46,82 @@ export const WalletContextProvider = ({ children }: WalletContextProviderProps):
|
||||
useEffect(() => {
|
||||
SInfo.getItem('lndHub', {}).then((value) => {
|
||||
if (value) {
|
||||
setLndHub(JSON.parse(value))
|
||||
setConfig(JSON.parse(value))
|
||||
setType('lndHub')
|
||||
}
|
||||
})
|
||||
SInfo.getItem('lnBits', {}).then((value) => {
|
||||
if (value) {
|
||||
setConfig(JSON.parse(value))
|
||||
setType('lnBits')
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
const refreshLndHub: (login?: string, password?: string, uri?: string) => void = (
|
||||
login,
|
||||
password,
|
||||
uri,
|
||||
const getClient: (params?: any, clientType?: string) => LndHub | LnBits | undefined = (
|
||||
params,
|
||||
clientType,
|
||||
) => {
|
||||
setLndHub(undefined)
|
||||
let params:
|
||||
| { type: string; refresh_token?: string; login?: string; password?: string }
|
||||
| undefined
|
||||
if (lndHub?.refreshToken) {
|
||||
params = {
|
||||
type: 'refresh_token',
|
||||
refresh_token: lndHub?.refreshToken,
|
||||
}
|
||||
uri = lndHub?.url
|
||||
} else if (login !== '' && password !== '' && uri !== '') {
|
||||
params = {
|
||||
type: 'auth',
|
||||
login,
|
||||
password,
|
||||
const kind = clientType ?? type
|
||||
let client
|
||||
if (kind === 'lndHub') {
|
||||
client = new LndHub(params ?? config)
|
||||
} else if (kind === 'lnBits') {
|
||||
client = new LnBits(params ?? config)
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
const refreshWallet: (params?: any, clientType?: string) => void = (params, clientType) => {
|
||||
setConfig(undefined)
|
||||
if (clientType) {
|
||||
setType(clientType)
|
||||
const client = getClient(params, clientType)
|
||||
if (client) {
|
||||
client.refresh(params).then((response) => {
|
||||
if (response?.status === 200) setConfig(response.config)
|
||||
})
|
||||
}
|
||||
}
|
||||
if (params && uri) {
|
||||
axios.post(`${uri}/auth`, {}, { params }).then((response) => {
|
||||
if (response?.data?.refresh_token && response.data?.access_token && uri) {
|
||||
setLndHub({
|
||||
accessToken: response.data.access_token,
|
||||
refreshToken: response.data.refresh_token,
|
||||
url: uri,
|
||||
})
|
||||
}
|
||||
|
||||
const updateWallet: () => Promise<void> = async () => {
|
||||
console.log('config', config)
|
||||
console.log('type', type)
|
||||
if (!config || !type) return
|
||||
|
||||
const client = getClient()
|
||||
console.log('client', client)
|
||||
if (client) {
|
||||
client.getBalance().then((response) => {
|
||||
if (response?.status === 200) {
|
||||
setUpdatedAt(`${getUnixTime(new Date())}-balance`)
|
||||
setBalance(response.balance)
|
||||
SInfo.setItem(type, JSON.stringify(client.config), {})
|
||||
} else if (response?.status === 401) {
|
||||
refreshWallet()
|
||||
}
|
||||
})
|
||||
|
||||
client.getMovements(setTransactions, setInvoices, setUpdatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
const updateLndHub: () => void = () => {
|
||||
if (!lndHub) return
|
||||
|
||||
const headers = {
|
||||
Authorization: `Bearer ${lndHub.accessToken}`,
|
||||
}
|
||||
|
||||
axios.get(`${lndHub.url}/balance`, { headers }).then((response) => {
|
||||
if (response) {
|
||||
if (response.status === 200) {
|
||||
setUpdatedAt(`${getUnixTime(new Date())}-balance`)
|
||||
setBalance(response.data?.BTC?.AvailableBalance ?? 0)
|
||||
SInfo.setItem('lndHub', JSON.stringify(lndHub), {})
|
||||
setActive(true)
|
||||
} else if (response.status === 401) {
|
||||
refreshLndHub()
|
||||
}
|
||||
}
|
||||
})
|
||||
axios.get(`${lndHub.url}/gettxs`, { headers }).then((response) => {
|
||||
if (response) {
|
||||
setTransactions(
|
||||
response.data.map((item: any) => {
|
||||
return {
|
||||
id: item.payment_preimage,
|
||||
monto: item.value,
|
||||
type: 'transaction',
|
||||
description: item.memo,
|
||||
timestamp: item.timestamp,
|
||||
}
|
||||
}),
|
||||
)
|
||||
setUpdatedAt(`${getUnixTime(new Date())}-gettxs`)
|
||||
}
|
||||
})
|
||||
axios.get(`${lndHub.url}/getuserinvoices`, { headers }).then((response) => {
|
||||
if (response) {
|
||||
setInvoices(
|
||||
response.data
|
||||
.filter((item: any) => item.ispaid)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
id: item.payment_hash,
|
||||
monto: item.amt,
|
||||
type: 'invoice',
|
||||
description: item.description,
|
||||
timestamp: item.timestamp,
|
||||
}
|
||||
}),
|
||||
)
|
||||
setUpdatedAt(`${getUnixTime(new Date())}-getuserinvoices`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(updateLndHub, [lndHub])
|
||||
useEffect(() => {
|
||||
if (config) updateWallet()
|
||||
}, [config])
|
||||
|
||||
const payInvoice: (invoice: string) => Promise<boolean> = async (invoice) => {
|
||||
if (active && invoice && invoice !== '') {
|
||||
const headers = {
|
||||
Authorization: `Bearer ${lndHub?.accessToken}`,
|
||||
}
|
||||
const params = {
|
||||
invoice,
|
||||
}
|
||||
const response = await axios.post(`${lndHub?.url}/payinvoice`, params, { headers })
|
||||
if (response) {
|
||||
if (response.status === 200) {
|
||||
updateLndHub()
|
||||
return response?.data?.payment_error === ''
|
||||
} else if (response.status === 401) {
|
||||
refreshLndHub()
|
||||
}
|
||||
if (type && config) {
|
||||
const client = new LndHub(config as LndHubConfig)
|
||||
const response = await client.payInvoice(invoice)
|
||||
if (response?.status === 200) {
|
||||
updateWallet()
|
||||
return true
|
||||
} else if (response?.status === 401) {
|
||||
refreshWallet()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,8 +130,8 @@ export const WalletContextProvider = ({ children }: WalletContextProviderProps):
|
||||
|
||||
const logoutWallet: () => void = () => {
|
||||
SInfo.deleteItem('lndHub', {})
|
||||
setActive(false)
|
||||
setLndHub(undefined)
|
||||
setType(undefined)
|
||||
setConfig(undefined)
|
||||
setBalance(undefined)
|
||||
setUpdatedAt(undefined)
|
||||
setTransactions([])
|
||||
@ -189,13 +141,14 @@ export const WalletContextProvider = ({ children }: WalletContextProviderProps):
|
||||
return (
|
||||
<WalletContext.Provider
|
||||
value={{
|
||||
active,
|
||||
type,
|
||||
setType,
|
||||
updatedAt,
|
||||
setLndHub,
|
||||
balance,
|
||||
transactions,
|
||||
invoices,
|
||||
refreshLndHub,
|
||||
refreshWallet,
|
||||
updateWallet,
|
||||
payInvoice,
|
||||
logoutWallet,
|
||||
}}
|
||||
|
@ -26,6 +26,17 @@
|
||||
"loginStep3Description": "You can add the relays used by your contacts to your list and connect to them to strengthen the network.",
|
||||
"loginskip": "You can skip this process but you may miss out on the opportunity to connect to a diverse range of relays and expand your network's reach"
|
||||
},
|
||||
"walletPage": {
|
||||
"addLnBits": "Add LnBits",
|
||||
"adminKey": "Admin Key",
|
||||
"invoiceReadKey": "Invoice Read Key",
|
||||
"address": "Address",
|
||||
"walletId": "Wallet id",
|
||||
"connectingWallet": "Connecting to wallet",
|
||||
"lnHub": "LNDHub address",
|
||||
"addLnhub": "Add LNDHub",
|
||||
"connect": "Connect"
|
||||
},
|
||||
"homeNavigator": {
|
||||
"ProfileCreate": "Profil anlegen",
|
||||
"Search": "",
|
||||
|
@ -27,8 +27,14 @@
|
||||
"loginskip": "You can skip this process but you may miss out on the opportunity to connect to a diverse range of relays and expand your network's reach"
|
||||
},
|
||||
"walletPage": {
|
||||
"addLnhub": "Add LNHub",
|
||||
"lnHub": "LNHub address",
|
||||
"addLnBits": "Add LnBits",
|
||||
"adminKey": "Admin Key",
|
||||
"invoiceReadKey": "Invoice Read Key",
|
||||
"address": "Address",
|
||||
"walletId": "Wallet id",
|
||||
"connectingWallet": "Connecting to wallet",
|
||||
"lnHub": "LNDHub address",
|
||||
"addLnhub": "Add LNDHub",
|
||||
"connect": "Connect"
|
||||
},
|
||||
"homeNavigator": {
|
||||
|
@ -26,6 +26,17 @@
|
||||
"loginStep3Description": "You can add the relays used by your contacts to your list and connect to them to strengthen the network.",
|
||||
"loginskip": "You can skip this process but you may miss out on the opportunity to connect to a diverse range of relays and expand your network's reach"
|
||||
},
|
||||
"walletPage": {
|
||||
"addLnBits": "Añadir LnBits",
|
||||
"adminKey": "Admin Key",
|
||||
"invoiceReadKey": "Invoice Read Key",
|
||||
"address": "Dirección",
|
||||
"walletId": "Wallet id",
|
||||
"connectingWallet": "Conectando a la wallet",
|
||||
"lnHub": "Dirección LNDHub",
|
||||
"addLnhub": "Añadir LNDHub",
|
||||
"connect": "Connectar"
|
||||
},
|
||||
"searchPage": {
|
||||
"placeholder": "Busca for claves públicas, notas, ...",
|
||||
"emptyTitle": "Consejo",
|
||||
|
@ -26,6 +26,17 @@
|
||||
"loginStep3Description": "You can add the relays used by your contacts to your list and connect to them to strengthen the network.",
|
||||
"loginskip": "You can skip this process but you may miss out on the opportunity to connect to a diverse range of relays and expand your network's reach"
|
||||
},
|
||||
"walletPage": {
|
||||
"addLnBits": "Add LnBits",
|
||||
"adminKey": "Admin Key",
|
||||
"invoiceReadKey": "Invoice Read Key",
|
||||
"address": "Address",
|
||||
"walletId": "Wallet id",
|
||||
"connectingWallet": "Connecting to wallet",
|
||||
"lnHub": "LNDHub address",
|
||||
"addLnhub": "Add LNDHub",
|
||||
"connect": "Connect"
|
||||
},
|
||||
"searchPage": {
|
||||
"placeholder": "Look for public keys, notes, hashtags...",
|
||||
"emptyTitle": "Tip",
|
||||
|
@ -26,6 +26,17 @@
|
||||
"loginStep3Description": "You can add the relays used by your contacts to your list and connect to them to strengthen the network.",
|
||||
"loginskip": "You can skip this process but you may miss out on the opportunity to connect to a diverse range of relays and expand your network's reach"
|
||||
},
|
||||
"walletPage": {
|
||||
"addLnBits": "Add LnBits",
|
||||
"adminKey": "Admin Key",
|
||||
"invoiceReadKey": "Invoice Read Key",
|
||||
"address": "Address",
|
||||
"walletId": "Wallet id",
|
||||
"connectingWallet": "Connecting to wallet",
|
||||
"lnHub": "LNDHub address",
|
||||
"addLnhub": "Add LNDHub",
|
||||
"connect": "Connect"
|
||||
},
|
||||
"searchPage": {
|
||||
"placeholder": "Look for public keys, notes, hashtags...",
|
||||
"emptyTitle": "Tip",
|
||||
|
@ -26,6 +26,17 @@
|
||||
"loginStep3Description": "您可以将您的联系人使用的中继添加到您的列表中并连接到它们以加强网络",
|
||||
"loginskip": "您可以跳过此过程,但您可能会错过连接到各种中继和扩大网络覆盖范围的机会"
|
||||
},
|
||||
"walletPage": {
|
||||
"addLnBits": "Add LnBits",
|
||||
"adminKey": "Admin Key",
|
||||
"invoiceReadKey": "Invoice Read Key",
|
||||
"address": "Address",
|
||||
"walletId": "Wallet id",
|
||||
"connectingWallet": "Connecting to wallet",
|
||||
"lnHub": "LNDHub address",
|
||||
"addLnhub": "Add LNDHub",
|
||||
"connect": "Connect"
|
||||
},
|
||||
"searchPage": {
|
||||
"placeholder": "查找公钥,Notes,标签...",
|
||||
"emptyTitle": "提示",
|
||||
|
@ -32,7 +32,7 @@ export const NotificationsFeed: React.FC = () => {
|
||||
const theme = useTheme()
|
||||
const { t } = useTranslation('common')
|
||||
const { database, setNotificationSeenAt, pushedTab, getSatoshiSymbol } = useContext(AppContext)
|
||||
const { publicKey, reloadLists, mutedEvents } = useContext(UserContext)
|
||||
const { publicKey, reloadLists, mutedEvents, mutedUsers } = useContext(UserContext)
|
||||
const { lastEventId, relayPool } = useContext(RelayPoolContext)
|
||||
const [pubKeys, setPubKeys] = React.useState<string[]>([])
|
||||
const [users, setUsers] = React.useState<User[]>([])
|
||||
@ -145,7 +145,9 @@ export const NotificationsFeed: React.FC = () => {
|
||||
const unmutedThreads = notes.filter((note) => {
|
||||
if (!note?.id) return false
|
||||
const eTags = getETags(note)
|
||||
return !eTags.some((tag) => mutedEvents.includes(tag[1]))
|
||||
return (
|
||||
!eTags.some((tag) => mutedEvents.includes(tag[1])) && !mutedUsers.includes(note.pubkey)
|
||||
)
|
||||
})
|
||||
setMentionNotes(unmutedThreads)
|
||||
setRefreshing(false)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import Clipboard from '@react-native-clipboard/clipboard'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
import { differenceInDays, format, fromUnixTime, isSameDay } from 'date-fns'
|
||||
import { t } from 'i18next'
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
@ -15,24 +16,36 @@ import {
|
||||
} from 'react-native-paper'
|
||||
import RBSheet from 'react-native-raw-bottom-sheet'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
|
||||
import Logo from '../../Components/Logo'
|
||||
import NostrosAvatar from '../../Components/NostrosAvatar'
|
||||
import { AppContext } from '../../Contexts/AppContext'
|
||||
import { type WalletAction, WalletContext } from '../../Contexts/WalletContext'
|
||||
import { WalletContext } from '../../Contexts/WalletContext'
|
||||
import { getZaps, type Zap } from '../../Functions/DatabaseFunctions/Zaps'
|
||||
import type WalletAction from '../../lib/Lightning'
|
||||
import { navigate } from '../../lib/Navigation'
|
||||
|
||||
export const WalletPage: React.FC = () => {
|
||||
const theme = useTheme()
|
||||
const { getSatoshiSymbol, database, setDisplayUserDrawer } = React.useContext(AppContext)
|
||||
const { refreshLndHub, active, balance, transactions, invoices, updatedAt } =
|
||||
const { refreshWallet, updateWallet, type, balance, transactions, invoices, updatedAt } =
|
||||
React.useContext(WalletContext)
|
||||
const [lnHubAddress, setLndHubAddress] = React.useState<string>()
|
||||
const [lnBitsAddress, setLnBitsAddress] = React.useState<string>()
|
||||
const [lnBitsInvoiceKey, setLnBitsInvoiceKey] = React.useState<string>()
|
||||
const [lnBitsAdminKey, setLnBitsAdminKey] = React.useState<string>()
|
||||
const [showNotification, setShowNotification] = React.useState<undefined | string>()
|
||||
const [actions, setActions] = React.useState<WalletAction[]>([])
|
||||
const [zaps, setZaps] = React.useState<Record<string, Zap>>({})
|
||||
const bottomLndHubRef = React.useRef<RBSheet>(null)
|
||||
const bottomLndBitsRef = React.useRef<RBSheet>(null)
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
updateWallet()
|
||||
return () => {}
|
||||
}, []),
|
||||
)
|
||||
|
||||
useEffect(refreshLndHub, [])
|
||||
useEffect(() => {
|
||||
const array = [...transactions, ...invoices].sort(
|
||||
(item1, item2) => item2.timestamp - item1.timestamp,
|
||||
@ -51,9 +64,9 @@ export const WalletPage: React.FC = () => {
|
||||
}
|
||||
}, [updatedAt])
|
||||
|
||||
const pasteLndHub: () => void = () => {
|
||||
const paste: (setFunction: (value: string) => void) => void = (setFunction) => {
|
||||
Clipboard.getString().then((value) => {
|
||||
setLndHubAddress(value ?? '')
|
||||
setFunction(value ?? '')
|
||||
})
|
||||
}
|
||||
|
||||
@ -67,13 +80,27 @@ export const WalletPage: React.FC = () => {
|
||||
if (uri[uri.length - 1] === '/') {
|
||||
uri = uri.substring(0, uri.length - 1)
|
||||
}
|
||||
refreshLndHub(login, password, uri)
|
||||
refreshWallet({ login, password, uri }, 'lndHub')
|
||||
setLndHubAddress(undefined)
|
||||
bottomLndHubRef.current?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const connectLnBits: () => void = () => {
|
||||
if (lnBitsAddress && lnBitsAdminKey && lnBitsInvoiceKey) {
|
||||
let uri = lnBitsAddress
|
||||
if (uri[uri.length - 1] === '/') {
|
||||
uri = uri.substring(0, uri.length - 1)
|
||||
}
|
||||
refreshWallet({ lnBitsAddress, lnBitsAdminKey, lnBitsInvoiceKey }, 'lnBits')
|
||||
setLnBitsAddress(undefined)
|
||||
setLnBitsAdminKey(undefined)
|
||||
setLnBitsInvoiceKey(undefined)
|
||||
bottomLndBitsRef.current?.close()
|
||||
}
|
||||
}
|
||||
|
||||
const bottomSheetStyles = React.useMemo(() => {
|
||||
return {
|
||||
container: {
|
||||
@ -95,6 +122,13 @@ export const WalletPage: React.FC = () => {
|
||||
<Button mode='contained' onPress={() => bottomLndHubRef.current?.open()}>
|
||||
{t('walletPage.addLnhub')}
|
||||
</Button>
|
||||
<Button
|
||||
mode='contained'
|
||||
style={styles.button}
|
||||
onPress={() => bottomLndBitsRef.current?.open()}
|
||||
>
|
||||
{t('walletPage.addLnBits')}
|
||||
</Button>
|
||||
</View>
|
||||
),
|
||||
[],
|
||||
@ -109,7 +143,7 @@ export const WalletPage: React.FC = () => {
|
||||
const zap = zaps[item.id]
|
||||
|
||||
return (
|
||||
<>
|
||||
<View key={item.id ?? index}>
|
||||
{(index === 0 || !isSameDay(date, prevDate)) && (
|
||||
<Text variant='titleMedium'>{format(date, formatPattern)}</Text>
|
||||
)}
|
||||
@ -172,29 +206,33 @@ export const WalletPage: React.FC = () => {
|
||||
</View>
|
||||
</View>
|
||||
</TouchableRipple>
|
||||
</>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{active ? (
|
||||
<View>
|
||||
<View style={[styles.balance, { backgroundColor: theme.colors.onSecondary }]}>
|
||||
<View style={styles.balanceNumber}>
|
||||
<Text variant='displayMedium'>{`${balance} `}</Text>
|
||||
<Text style={styles.balanceSymbol} variant='headlineSmall'>
|
||||
{getSatoshiSymbol()}
|
||||
</Text>
|
||||
{type ? (
|
||||
balance !== undefined ? (
|
||||
<View>
|
||||
<View style={[styles.balance, { backgroundColor: theme.colors.onSecondary }]}>
|
||||
<View style={styles.balanceNumber}>
|
||||
<Text variant='displayMedium'>{`${balance} `}</Text>
|
||||
<Text style={styles.balanceSymbol} variant='headlineSmall'>
|
||||
{getSatoshiSymbol()}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<FlatList data={actions} renderItem={renderAction} style={styles.list} />
|
||||
</View>
|
||||
<FlatList
|
||||
data={actions}
|
||||
renderItem={renderAction}
|
||||
style={styles.list}
|
||||
keyExtractor={(item) => item.id}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.center}>
|
||||
<View style={styles.centerItem}>
|
||||
<Logo onlyIcon size='large' />
|
||||
</View>
|
||||
<Text style={styles.centerItem}>{t('walletPage.connectingWallet')}</Text>
|
||||
</View>
|
||||
)
|
||||
) : (
|
||||
login
|
||||
)}
|
||||
@ -206,7 +244,7 @@ export const WalletPage: React.FC = () => {
|
||||
onIconPress={() => setShowNotification(undefined)}
|
||||
onDismiss={() => setShowNotification(undefined)}
|
||||
>
|
||||
{t(`profileCard.notifications.${showNotification}`)}
|
||||
{t(`walletPage.notifications.${showNotification}`)}
|
||||
</Snackbar>
|
||||
)}
|
||||
<RBSheet ref={bottomLndHubRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
@ -224,7 +262,7 @@ export const WalletPage: React.FC = () => {
|
||||
right={
|
||||
<TextInput.Icon
|
||||
icon='content-paste'
|
||||
onPress={pasteLndHub}
|
||||
onPress={() => paste(setLndHubAddress)}
|
||||
forceTextInputFocus={false}
|
||||
/>
|
||||
}
|
||||
@ -234,6 +272,69 @@ export const WalletPage: React.FC = () => {
|
||||
</Button>
|
||||
</View>
|
||||
</RBSheet>
|
||||
<RBSheet ref={bottomLndBitsRef} closeOnDragDown={true} customStyles={bottomSheetStyles}>
|
||||
<View>
|
||||
<Text variant='headlineSmall' style={styles.drawerParagraph}>
|
||||
{t('walletPage.addLnBits')}
|
||||
</Text>
|
||||
<TextInput
|
||||
style={styles.drawerParagraph}
|
||||
mode='outlined'
|
||||
multiline
|
||||
label={t('walletPage.address') ?? ''}
|
||||
onChangeText={setLnBitsAddress}
|
||||
value={lnBitsAddress}
|
||||
right={
|
||||
<TextInput.Icon
|
||||
icon='content-paste'
|
||||
onPress={() => paste(setLnBitsAddress)}
|
||||
forceTextInputFocus={false}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.drawerParagraph}
|
||||
mode='outlined'
|
||||
multiline
|
||||
label={t('walletPage.adminKey') ?? ''}
|
||||
onChangeText={setLnBitsAdminKey}
|
||||
value={lnBitsAdminKey}
|
||||
right={
|
||||
<TextInput.Icon
|
||||
icon='content-paste'
|
||||
onPress={() => paste(setLnBitsAdminKey)}
|
||||
forceTextInputFocus={false}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<TextInput
|
||||
style={styles.drawerParagraph}
|
||||
mode='outlined'
|
||||
multiline
|
||||
label={t('walletPage.invoiceReadKey') ?? ''}
|
||||
onChangeText={setLnBitsInvoiceKey}
|
||||
value={lnBitsInvoiceKey}
|
||||
right={
|
||||
<TextInput.Icon
|
||||
icon='content-paste'
|
||||
onPress={() => paste(setLnBitsInvoiceKey)}
|
||||
forceTextInputFocus={false}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
mode='contained'
|
||||
onPress={connectLnBits}
|
||||
disabled={
|
||||
lnBitsAddress === undefined ||
|
||||
lnBitsAdminKey === undefined ||
|
||||
lnBitsInvoiceKey === undefined
|
||||
}
|
||||
>
|
||||
{t('walletPage.connect')}
|
||||
</Button>
|
||||
</View>
|
||||
</RBSheet>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@ -245,10 +346,18 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
center: {
|
||||
justifyContent: 'center',
|
||||
alignContent: 'center',
|
||||
height: '100%',
|
||||
padding: 16,
|
||||
},
|
||||
centerItem: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
width: '100%',
|
||||
textAlign: 'center',
|
||||
},
|
||||
button: {
|
||||
marginTop: 16,
|
||||
},
|
||||
drawerParagraph: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
|
108
frontend/lib/Lightning/LnBits/index.ts
Normal file
108
frontend/lib/Lightning/LnBits/index.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import axios from 'axios'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import type WalletAction from '..'
|
||||
|
||||
export interface LnBitsConfig {
|
||||
lnBitsAddress: string
|
||||
lnBitsAdminKey: string
|
||||
lnBitsInvoiceKey: string
|
||||
}
|
||||
|
||||
class LndHub {
|
||||
constructor(config?: LnBitsConfig) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
public config: LnBitsConfig | undefined
|
||||
|
||||
private readonly getHeaders: () => object | undefined = () => {
|
||||
if (!this.config) return
|
||||
return {
|
||||
'X-Api-Key': this.config.lnBitsInvoiceKey,
|
||||
}
|
||||
}
|
||||
|
||||
public payInvoice: (invoice: string) => Promise<{ status: number } | undefined> = async (
|
||||
invoice,
|
||||
) => {
|
||||
if (!this.config) return
|
||||
if (invoice && invoice !== '') {
|
||||
const params = {
|
||||
invoice,
|
||||
}
|
||||
const response = await axios.post(`${this.config?.lnBitsAddress}/payinvoice`, params, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
if (response) {
|
||||
return { status: response.status }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getBalance: () => Promise<{ balance?: number; status: number } | undefined> = async () => {
|
||||
if (!this.config) return
|
||||
const headers = {
|
||||
'X-Api-Key': this.config.lnBitsInvoiceKey,
|
||||
}
|
||||
const response = await axios.get(`${this.config.lnBitsAddress}/api/v1/wallet`, { headers })
|
||||
if (response) {
|
||||
return {
|
||||
balance: (response.data?.balance ?? 0) / 1000,
|
||||
status: response.status,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getMovements: (
|
||||
setTransactions: (transactions: WalletAction[]) => void,
|
||||
setInvoices: (invoices: WalletAction[]) => void,
|
||||
setUpdatedAt: (updatedAt: string) => void,
|
||||
) => Promise<void> = async (setTransactions, setInvoices, setUpdatedAt) => {
|
||||
if (!this.config) return
|
||||
const headers = {
|
||||
'X-Api-Key': this.config.lnBitsInvoiceKey,
|
||||
}
|
||||
const response = await axios.get(`${this.config.lnBitsAddress}/api/v1/payments`, { headers })
|
||||
if (response) {
|
||||
setTransactions(
|
||||
response.data
|
||||
.filter((item: any) => item.amount < 0)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
id: item.payment_preimage,
|
||||
monto: Math.abs(item.amount / 1000),
|
||||
type: 'transaction',
|
||||
description: item.memo,
|
||||
timestamp: item.time,
|
||||
}
|
||||
}),
|
||||
)
|
||||
setInvoices(
|
||||
response.data
|
||||
.filter((item: any) => item.amount > 0)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
id: item.payment_preimage,
|
||||
monto: item.amount / 1000,
|
||||
type: 'invoice',
|
||||
description: item.memo,
|
||||
timestamp: item.time,
|
||||
}
|
||||
}),
|
||||
)
|
||||
setUpdatedAt(`${getUnixTime(new Date())}-movements`)
|
||||
}
|
||||
}
|
||||
|
||||
public refresh: (params: any) => Promise<{ config: LnBitsConfig; status: number } | undefined> =
|
||||
async (params) => {
|
||||
if (params?.lnBitsAddress) {
|
||||
return {
|
||||
config: params,
|
||||
status: 200,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default LndHub
|
134
frontend/lib/Lightning/LndHub/index.ts
Normal file
134
frontend/lib/Lightning/LndHub/index.ts
Normal file
@ -0,0 +1,134 @@
|
||||
import axios from 'axios'
|
||||
import { getUnixTime } from 'date-fns'
|
||||
import type WalletAction from '..'
|
||||
|
||||
export interface LndHubConfig {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
url: string
|
||||
}
|
||||
|
||||
class LndHub {
|
||||
constructor(config?: LndHubConfig) {
|
||||
this.config = config
|
||||
}
|
||||
|
||||
public config: LndHubConfig | undefined
|
||||
|
||||
private readonly getHeaders: () => object | undefined = () => {
|
||||
if (!this.config) return
|
||||
return {
|
||||
Authorization: `Bearer ${this.config.accessToken}`,
|
||||
}
|
||||
}
|
||||
|
||||
public payInvoice: (invoice: string) => Promise<{ status: number } | undefined> = async (
|
||||
invoice,
|
||||
) => {
|
||||
if (!this.config) return
|
||||
if (invoice && invoice !== '') {
|
||||
const params = {
|
||||
invoice,
|
||||
}
|
||||
const response = await axios.post(`${this.config?.url}/payinvoice`, params, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
if (response) {
|
||||
return { status: response.status }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getBalance: () => Promise<{ balance?: number; status: number } | undefined> = async () => {
|
||||
if (!this.config) return
|
||||
const response = await axios.get(`${this.config.url}/balance`, { headers: this.getHeaders() })
|
||||
if (response) {
|
||||
return {
|
||||
balance: response.data?.BTC?.AvailableBalance ?? 0,
|
||||
status: response.status,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly getTransactions: () => Promise<WalletAction[] | undefined> = async () => {
|
||||
if (!this.config) return
|
||||
const response = await axios.get(`${this.config.url}/gettxs`, { headers: this.getHeaders() })
|
||||
if (response) {
|
||||
return response.data.map((item: any) => {
|
||||
return {
|
||||
id: item.payment_preimage,
|
||||
monto: item.value,
|
||||
type: 'transaction',
|
||||
description: item.memo,
|
||||
timestamp: item.timestamp,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private readonly getInvoices: () => Promise<WalletAction[] | undefined> = async () => {
|
||||
if (!this.config) return
|
||||
const response = await axios.get(`${this.config.url}/getuserinvoices`, {
|
||||
headers: this.getHeaders(),
|
||||
})
|
||||
if (response) {
|
||||
return response.data
|
||||
.filter((item: any) => item.ispaid)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
id: item.payment_hash,
|
||||
monto: item.amt,
|
||||
type: 'invoice',
|
||||
description: item.description,
|
||||
timestamp: item.timestamp,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public getMovements: (
|
||||
setTransactions: (transactions: WalletAction[]) => void,
|
||||
setInvoices: (transactions: WalletAction[]) => void,
|
||||
setUpdatedAt: (updatedAt: string) => void,
|
||||
) => Promise<void> = async (setTransactions, setInvoices, setUpdatedAt) => {
|
||||
if (!this.config) return
|
||||
setTransactions((await this.getTransactions()) ?? [])
|
||||
setInvoices((await this.getInvoices()) ?? [])
|
||||
setUpdatedAt(`${getUnixTime(new Date())}-movements`)
|
||||
}
|
||||
|
||||
public refresh: (params: any) => Promise<{ config: LndHubConfig; status: number } | undefined> =
|
||||
async (params) => {
|
||||
let requestParams:
|
||||
| { type: string; refresh_token?: string; login?: string; password?: string }
|
||||
| undefined
|
||||
if (this.config?.refreshToken) {
|
||||
requestParams = {
|
||||
type: 'refresh_token',
|
||||
refresh_token: this.config?.refreshToken,
|
||||
}
|
||||
params.uri = this.config?.url
|
||||
} else if (params.login !== '' && params.password !== '' && params.uri !== '') {
|
||||
requestParams = {
|
||||
type: 'auth',
|
||||
login: params.login,
|
||||
password: params.password,
|
||||
}
|
||||
}
|
||||
if (params?.uri) {
|
||||
const response = await axios.post(`${params.uri}/auth`, {}, { params: requestParams })
|
||||
if (response) {
|
||||
return {
|
||||
config: {
|
||||
accessToken: response.data.access_token,
|
||||
refreshToken: response.data.refresh_token,
|
||||
url: params.uri,
|
||||
},
|
||||
status: response.status,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default LndHub
|
9
frontend/lib/Lightning/index.ts
Normal file
9
frontend/lib/Lightning/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export interface WalletAction {
|
||||
id: string
|
||||
monto: number
|
||||
type: 'invoice' | 'transaction'
|
||||
description: string
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
export default WalletAction
|
@ -80,7 +80,7 @@
|
||||
"@types/react-native-vector-icons": "^6.4.13",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
||||
"babel-jest": "^29.4.3",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
@ -94,10 +94,10 @@
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"jest": "^29.4.3",
|
||||
"metro-react-native-babel-preset": "^0.75.0",
|
||||
"metro-react-native-babel-preset": "^0.76.0",
|
||||
"prettier": "^2.8.4",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "^4.9.4"
|
||||
"typescript": "^5.0.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "^17"
|
||||
|
108
yarn.lock
108
yarn.lock
@ -1798,7 +1798,7 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.30.5", "@typescript-eslint/eslint-plugin@^5.43.0":
|
||||
"@typescript-eslint/eslint-plugin@^5.30.5":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz#bc2400c3a23305e8c9a9c04aa40933868aaaeb47"
|
||||
integrity sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==
|
||||
@ -1814,6 +1814,22 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz#e4fbb4d6dd8dab3e733485c1a44a02189ae75364"
|
||||
integrity sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "5.56.0"
|
||||
"@typescript-eslint/type-utils" "5.56.0"
|
||||
"@typescript-eslint/utils" "5.56.0"
|
||||
debug "^4.3.4"
|
||||
grapheme-splitter "^1.0.4"
|
||||
ignore "^5.2.0"
|
||||
natural-compare-lite "^1.4.0"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@^5.30.5", "@typescript-eslint/parser@^5.43.0":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.55.0.tgz#8c96a0b6529708ace1dcfa60f5e6aec0f5ed2262"
|
||||
@ -1832,6 +1848,14 @@
|
||||
"@typescript-eslint/types" "5.55.0"
|
||||
"@typescript-eslint/visitor-keys" "5.55.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz#62b4055088903b5254fa20403010e1c16d6ab725"
|
||||
integrity sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.56.0"
|
||||
"@typescript-eslint/visitor-keys" "5.56.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.55.0":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz#74bf0233523f874738677bb73cb58094210e01e9"
|
||||
@ -1842,11 +1866,26 @@
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz#e6f004a072f09c42e263dc50e98c70b41a509685"
|
||||
integrity sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.56.0"
|
||||
"@typescript-eslint/utils" "5.56.0"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/types@5.55.0":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.55.0.tgz#9830f8d3bcbecf59d12f821e5bc6960baaed41fd"
|
||||
integrity sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==
|
||||
|
||||
"@typescript-eslint/types@5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.56.0.tgz#b03f0bfd6fa2afff4e67c5795930aff398cbd834"
|
||||
integrity sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.55.0":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz#8db7c8e47ecc03d49b05362b8db6f1345ee7b575"
|
||||
@ -1860,6 +1899,19 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz#48342aa2344649a03321e74cab9ccecb9af086c3"
|
||||
integrity sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.56.0"
|
||||
"@typescript-eslint/visitor-keys" "5.56.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/utils@5.55.0", "@typescript-eslint/utils@^5.10.0":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.55.0.tgz#34e97322e7ae5b901e7a870aabb01dad90023341"
|
||||
@ -1874,6 +1926,20 @@
|
||||
eslint-scope "^5.1.1"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/utils@5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.56.0.tgz#db64705409b9a15546053fb4deb2888b37df1f41"
|
||||
integrity sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.56.0"
|
||||
"@typescript-eslint/types" "5.56.0"
|
||||
"@typescript-eslint/typescript-estree" "5.56.0"
|
||||
eslint-scope "^5.1.1"
|
||||
semver "^7.3.7"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.55.0":
|
||||
version "5.55.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz#01ad414fca8367706d76cdb94adf788dc5b664a2"
|
||||
@ -1882,6 +1948,14 @@
|
||||
"@typescript-eslint/types" "5.55.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.56.0":
|
||||
version "5.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz#f19eb297d972417eb13cb69b35b3213e13cc214f"
|
||||
integrity sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.56.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||
@ -2144,6 +2218,13 @@ available-typed-arrays@^1.0.5:
|
||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||
|
||||
axios@^0.21.1:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
axios@^1.2.6, axios@^1.3.3:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024"
|
||||
@ -3999,7 +4080,7 @@ flow-parser@^0.121.0:
|
||||
resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f"
|
||||
integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg==
|
||||
|
||||
follow-redirects@^1.15.0:
|
||||
follow-redirects@^1.14.0, follow-redirects@^1.15.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
@ -5452,6 +5533,14 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
lnbits@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lnbits/-/lnbits-1.1.5.tgz#ffe4bec2c1abddba3ad5c1277fcad0956b2fe712"
|
||||
integrity sha512-RPCBNsKKxlyQTHPKdU66iiXFBz6SuISVVkxJoSZY3Z+CBEzOu6xpgzZtQcZTbc1BCLqQc6HeK4qtfByKWjBTmg==
|
||||
dependencies:
|
||||
axios "^0.21.1"
|
||||
typescript "^4.1.3"
|
||||
|
||||
lnurl-pay@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lnurl-pay/-/lnurl-pay-2.2.0.tgz#aaf1d3f997d113ea54ca65f5d9de8020005c6e91"
|
||||
@ -5751,10 +5840,10 @@ metro-react-native-babel-preset@0.72.3:
|
||||
"@babel/template" "^7.0.0"
|
||||
react-refresh "^0.4.0"
|
||||
|
||||
metro-react-native-babel-preset@^0.75.0:
|
||||
version "0.75.1"
|
||||
resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.75.1.tgz#370bb3bba3ca83b3be1d8b0ab628271c864491cd"
|
||||
integrity sha512-a4Se/koIVsH+wmfWsSOiRpFLBSICJcbd6o1wv37QRoFSnH7mYXDOfYxNBZYX46PwN1QwmgR49Iwsef79JOaJMg==
|
||||
metro-react-native-babel-preset@^0.76.0:
|
||||
version "0.76.0"
|
||||
resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.76.0.tgz#440a0e8965b2eb01afa391ef95575faeed67636b"
|
||||
integrity sha512-2sM6dy9uAbuQlg7l/VOdiudUUMFRkABJ1YLkZU6Fpqi/rJCXn4fbF0pO+TwCFbBYNIQBY50clv9RPvD2n64hXg==
|
||||
dependencies:
|
||||
"@babel/core" "^7.20.0"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.0.0"
|
||||
@ -7981,11 +8070,16 @@ typeforce@^1.11.3:
|
||||
resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc"
|
||||
integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==
|
||||
|
||||
typescript@^4.9.4:
|
||||
typescript@^4.1.3:
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
|
||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
||||
|
||||
typescript@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.2.tgz#891e1a90c5189d8506af64b9ef929fca99ba1ee5"
|
||||
integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==
|
||||
|
||||
uglify-es@^3.1.9:
|
||||
version "3.3.9"
|
||||
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
|
||||
|
Loading…
Reference in New Issue
Block a user