diff --git a/frontend/Components/MenuItems/index.tsx b/frontend/Components/MenuItems/index.tsx index 4525af6..b943237 100644 --- a/frontend/Components/MenuItems/index.tsx +++ b/frontend/Components/MenuItems/index.tsx @@ -25,7 +25,7 @@ export const MenuItems: React.FC = () => { const [drawerItemIndex, setDrawerItemIndex] = React.useState(-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 ( {`${balance} `} diff --git a/frontend/Contexts/WalletContext.tsx b/frontend/Contexts/WalletContext.tsx index 88a9237..e0b52b9 100644 --- a/frontend/Contexts/WalletContext.tsx +++ b/frontend/Contexts/WalletContext.tsx @@ -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 + refreshWallet: (params?: object, type?: string) => void payInvoice: (invoice: string) => Promise 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(initialWalletContext.active) - const [lndHub, setLndHub] = useState() + const [type, setType] = React.useState() + const [config, setConfig] = useState() const [balance, setBalance] = useState() const [updatedAt, setUpdatedAt] = useState() const [transactions, setTransactions] = useState( @@ -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 = 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 = 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 ( { 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([]) const [users, setUsers] = React.useState([]) @@ -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) diff --git a/frontend/Pages/WalletPage/index.tsx b/frontend/Pages/WalletPage/index.tsx index 0698b18..4d4f775 100644 --- a/frontend/Pages/WalletPage/index.tsx +++ b/frontend/Pages/WalletPage/index.tsx @@ -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() + const [lnBitsAddress, setLnBitsAddress] = React.useState() + const [lnBitsInvoiceKey, setLnBitsInvoiceKey] = React.useState() + const [lnBitsAdminKey, setLnBitsAdminKey] = React.useState() const [showNotification, setShowNotification] = React.useState() const [actions, setActions] = React.useState([]) const [zaps, setZaps] = React.useState>({}) const bottomLndHubRef = React.useRef(null) + const bottomLndBitsRef = React.useRef(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 = () => { + ), [], @@ -109,7 +143,7 @@ export const WalletPage: React.FC = () => { const zap = zaps[item.id] return ( - <> + {(index === 0 || !isSameDay(date, prevDate)) && ( {format(date, formatPattern)} )} @@ -172,29 +206,33 @@ export const WalletPage: React.FC = () => { - + ) } return ( - {active ? ( - - - - {`${balance} `} - - {getSatoshiSymbol()} - + {type ? ( + balance !== undefined ? ( + + + + {`${balance} `} + + {getSatoshiSymbol()} + + + - item.id} - /> - + ) : ( + + + + + {t('walletPage.connectingWallet')} + + ) ) : ( login )} @@ -206,7 +244,7 @@ export const WalletPage: React.FC = () => { onIconPress={() => setShowNotification(undefined)} onDismiss={() => setShowNotification(undefined)} > - {t(`profileCard.notifications.${showNotification}`)} + {t(`walletPage.notifications.${showNotification}`)} )} @@ -224,7 +262,7 @@ export const WalletPage: React.FC = () => { right={ paste(setLndHubAddress)} forceTextInputFocus={false} /> } @@ -234,6 +272,69 @@ export const WalletPage: React.FC = () => { + + + + {t('walletPage.addLnBits')} + + paste(setLnBitsAddress)} + forceTextInputFocus={false} + /> + } + /> + paste(setLnBitsAdminKey)} + forceTextInputFocus={false} + /> + } + /> + paste(setLnBitsInvoiceKey)} + forceTextInputFocus={false} + /> + } + /> + + + ) } @@ -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, }, diff --git a/frontend/lib/Lightning/LnBits/index.ts b/frontend/lib/Lightning/LnBits/index.ts new file mode 100644 index 0000000..2e329b2 --- /dev/null +++ b/frontend/lib/Lightning/LnBits/index.ts @@ -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 = 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 diff --git a/frontend/lib/Lightning/LndHub/index.ts b/frontend/lib/Lightning/LndHub/index.ts new file mode 100644 index 0000000..7e14bc5 --- /dev/null +++ b/frontend/lib/Lightning/LndHub/index.ts @@ -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 = 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 = 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 = 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 diff --git a/frontend/lib/Lightning/index.ts b/frontend/lib/Lightning/index.ts new file mode 100644 index 0000000..5fcb770 --- /dev/null +++ b/frontend/lib/Lightning/index.ts @@ -0,0 +1,9 @@ +export interface WalletAction { + id: string + monto: number + type: 'invoice' | 'transaction' + description: string + timestamp: number +} + +export default WalletAction diff --git a/package.json b/package.json index def4039..597adcd 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/yarn.lock b/yarn.lock index e2f430a..07e7599 100644 --- a/yarn.lock +++ b/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"