Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
Automatic wallet opt in if server knows us
Browse files Browse the repository at this point in the history
  • Loading branch information
ericvicenti committed Nov 28, 2023
1 parent e51320e commit fcc50fb
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 34 deletions.
2 changes: 1 addition & 1 deletion frontend/apps/site/server/routers/_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const walletsRouter = router({
getAccountsAvailable: procedure
.input(z.array(z.string().or(z.undefined()).or(z.null())))
.query(async ({input}) => {
let url = 'https://ln.mintter.com/v2/check'
let url = `${process.env.NEXT_PUBLIC_LN_HOST || ''}/v2/check`
input.forEach((editor, index) => {
url += `${index === 0 ? '?' : '&'}user=${editor}`
})
Expand Down
4 changes: 3 additions & 1 deletion frontend/apps/site/src/web-tipping.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,9 @@ async function checkInvoice(invoice: InternalInvoice) {
const userId = invoice.split[0]?.id
if (!userId) throw new Error('Invalid invoice, no user id')
const res = await fetch(
`https://ln.mintter.com/v2/invoicemeta/${invoice.hash}?user=${userId}`,
`${process.env.NEXT_PUBLIC_LN_HOST || ''}/v2/invoicemeta/${
invoice.hash
}?user=${userId}`,
)
// @juligasa this response returns a 404 before the invoice is paid. after the invoice is paid the output looks like this:
// {
Expand Down
2 changes: 2 additions & 0 deletions frontend/packages/app/models/query-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export const queryKeys = {
CHANGE: 'CHANGE', //, changeId: string
ALL_ENTITY_CHANGES: 'ALL_ENTITY_CHANGES', //, entityId: string
DOCUMENT_TEXT_CONTENT: 'DOCUMENT_TEXT_CONTENT',

LIGHTNING_ACCOUNT_CHECK: 'LIGHTNING_ACCOUNT_CHECK', //, accountId: string
} as const

export function labelOfQueryKey(key: QueryKey) {
Expand Down
51 changes: 46 additions & 5 deletions frontend/packages/app/models/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import {BACKEND_GRAPHQL_ENDPOINT, Mutation} from '@mintter/shared'
import {UseMutationOptions, useMutation} from '@tanstack/react-query'
import {
BACKEND_GRAPHQL_ENDPOINT,
LIGHTNING_SERVER_URL,
Mutation,
} from '@mintter/shared'
import {UseMutationOptions, useMutation, useQuery} from '@tanstack/react-query'
import request, {gql} from 'graphql-request'
import {useEffect} from 'react'
import {useQueryInvalidator} from '../app-context'
import {useMyAccount} from './accounts'
import {useWallets} from './payments'
import {queryKeys} from './query-keys'

let exportBuiltInWalletMutation = gql`
mutation exportBuiltInWallet {
Expand All @@ -24,21 +32,48 @@ let insertDefaultWalletMutation = gql`
}
`

export async function checkWalletAccounts(accountIds: string[]) {
let url = `${LIGHTNING_SERVER_URL}/v2/check`
accountIds.forEach((accountId, index) => {
url += `${index === 0 ? '?' : '&'}user=${accountId}`
})
const res = await fetch(url)
const output = await res.json()
return output.existing_users || []
}

export function useAccountCheck(accountId?: string) {
return useQuery({
queryKey: [queryKeys.LIGHTNING_ACCOUNT_CHECK, accountId],
queryFn: async () => {
if (!accountId) return false
const res = await checkWalletAccounts([accountId])
return res.includes(accountId)
},
})
}

export function useMyAccountCheck() {
const account = useMyAccount()
const check = useAccountCheck(account?.data?.id)
return check
}

export function useWalletOptIn(opts?: UseMutationOptions) {
const wallets = useWallets()
const invalidate = useQueryInvalidator()
return useMutation({
const walletCheck = useMyAccountCheck()
const optIn = useMutation({
mutationFn: async (input) => {
const exported: Mutation = await request(
BACKEND_GRAPHQL_ENDPOINT,
exportBuiltInWalletMutation,
)
console.log('exported', exported)
const imported: Mutation = await request(
BACKEND_GRAPHQL_ENDPOINT,
insertDefaultWalletMutation,
{credentials: exported.exportWallet.credentials},
)
console.log('imported', imported)
return
},
...opts,
Expand All @@ -47,4 +82,10 @@ export function useWalletOptIn(opts?: UseMutationOptions) {
opts?.onSuccess?.(result, input, context)
},
})

useEffect(() => {
if (walletCheck.data === true && wallets.data?.length === 0) optIn.mutate()
}, [walletCheck.data, wallets.data])

return {optIn, wallets, walletCheck}
}
36 changes: 20 additions & 16 deletions frontend/packages/app/pages/onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ function Analytics(props: OnboardingStepProps) {
}

function Wallet(props: OnboardingStepProps) {
const optIn = useWalletOptIn({
const {optIn, wallets} = useWalletOptIn({
onError: (e) => {
toast.error(e.message)
},
Expand All @@ -597,24 +597,28 @@ function Wallet(props: OnboardingStepProps) {
<H1>Wallet</H1>
</StepTitleSection>
<YStack flex={2}>
<YStack gap="$5" maxWidth={500}>
<StepParagraph>
Opt in to receiving lightning payments
</StepParagraph>
<XStack>
<Button
onPress={() => {
optIn.mutate()
}}
>
Accept Lightning Payments
</Button>
</XStack>
</YStack>
{wallets.data?.length && wallets.data?.length > 0 ? (
<StepParagraph>Your wallet is ready to use!</StepParagraph>
) : wallets.data?.length === 0 ? (
<YStack gap="$5" maxWidth={500}>
<StepParagraph>
Opt in to receiving lightning payments
</StepParagraph>
<XStack>
<Button
onPress={() => {
optIn.mutate()
}}
>
Accept Lightning Payments
</Button>
</XStack>
</YStack>
) : null}
</YStack>
</XStack>
<XStack alignItems="center" justifyContent="flex-end" gap="$4">
{optIn.isLoading ? <Spinner /> : null}
{optIn.isLoading || optIn.isLoading ? <Spinner /> : null}
<PrevButton onPress={() => props.send('PREV')}>PREV</PrevButton>
<NextButton onPress={() => props.send('NEXT')}>NEXT</NextButton>
</XStack>
Expand Down
28 changes: 17 additions & 11 deletions frontend/packages/app/pages/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export default function Settings() {
</Tabs.Tab>
<Tabs.Tab value="wallets" data-testid="tab-wallets" borderRadius={0}>
<SizableText flex={1} textAlign="left">
Wallets
Sponsorship
</SizableText>
</Tabs.Tab>
<Tabs.Tab value="experimental" data-testid="tab-experimental">
Expand Down Expand Up @@ -772,19 +772,25 @@ function ExistingWallets({wallets}: {wallets: LightningWallet[]}) {
}

function NoWallets() {
const optIn = useWalletOptIn()
const {optIn, walletCheck} = useWalletOptIn()
const isLoading = optIn.isLoading || walletCheck.isLoading
return (
<YStack gap="$4">
<Heading>Sponsorship Wallets</Heading>
<SizableText>No Lightning Wallet</SizableText>
<Button
onPress={() => {
optIn.mutate()
}}
>
Enable Lightning Sponsorship
</Button>
{optIn.isLoading ? <Spinner /> : null}
{isLoading ? (
<Spinner />
) : (
<>
<SizableText>No Lightning Wallet</SizableText>
<Button
onPress={() => {
optIn.mutate()
}}
>
Enable Lightning Sponsorship
</Button>
</>
)}
</YStack>
)
}
Expand Down
4 changes: 4 additions & 0 deletions frontend/packages/shared/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ export const BACKEND_GRAPHQL_ENDPOINT = `${BACKEND_HOSTNAME}:${BACKEND_HTTP_PORT
// this is injected by Vite, so it indicates if we are in the production build of the DESKTOP app
export const IS_PROD_DESKTOP = !!import.meta.env?.PROD

export const LIGHTNING_SERVER_URL = IS_PROD_DESKTOP
? 'https://ln.mintter.com'
: 'https://ln.testnet.mintter.com'

export const MINTTER_SENTRY_DESKTOP_DSN = import.meta.env
?.VITE_MINTTER_SENTRY_DESKTOP

0 comments on commit fcc50fb

Please sign in to comment.