mirror of
https://github.com/apotdevin/thunderhub.git
synced 2024-11-19 01:40:03 +01:00
chore: amboss login
This commit is contained in:
parent
3c051fc811
commit
bd6aa992b8
169
server/schema/amboss/resolvers.ts
Normal file
169
server/schema/amboss/resolvers.ts
Normal file
@ -0,0 +1,169 @@
|
||||
import { requestLimiter } from 'server/helpers/rateLimiter';
|
||||
import { ContextType } from 'server/types/apiTypes';
|
||||
import { appUrls } from 'server/utils/appUrls';
|
||||
import { graphqlFetchWithProxy } from 'server/utils/fetch';
|
||||
import { signMessage } from 'ln-service';
|
||||
import { toWithError } from 'server/helpers/async';
|
||||
import cookieLib from 'cookie';
|
||||
import { appConstants } from 'server/utils/appConstants';
|
||||
import { logger } from 'server/helpers/logger';
|
||||
|
||||
const ONE_MONTH_SECONDS = 60 * 60 * 24 * 30;
|
||||
|
||||
const getUserQuery = `
|
||||
query GetUser {
|
||||
getUser {
|
||||
subscription {
|
||||
end_date
|
||||
subscribed
|
||||
upgradable
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const getLoginTokenQuery = `
|
||||
query GetLoginToken(
|
||||
$seconds: Float
|
||||
) {
|
||||
getLoginToken(seconds: $seconds)
|
||||
}
|
||||
`;
|
||||
|
||||
const getSignInfoQuery = `
|
||||
query GetSignInfo {
|
||||
getSignInfo {
|
||||
expiry
|
||||
identifier
|
||||
message
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const loginMutation = `
|
||||
mutation Login(
|
||||
$identifier: String!
|
||||
$signature: String!
|
||||
$seconds: Float
|
||||
$details: String
|
||||
$token: Boolean
|
||||
) {
|
||||
login(
|
||||
identifier: $identifier
|
||||
signature: $signature
|
||||
seconds: $seconds
|
||||
details: $details
|
||||
token: $token
|
||||
)
|
||||
}
|
||||
`;
|
||||
|
||||
export const ambossResolvers = {
|
||||
Query: {
|
||||
getAmbossUser: async (
|
||||
_: undefined,
|
||||
__: undefined,
|
||||
{ ip, ambossAuth }: ContextType
|
||||
) => {
|
||||
await requestLimiter(ip, 'getAmbossUser');
|
||||
|
||||
const { data, error } = await graphqlFetchWithProxy(
|
||||
appUrls.amboss,
|
||||
getUserQuery,
|
||||
undefined,
|
||||
{
|
||||
authorization: ambossAuth ? `Bearer ${ambossAuth}` : '',
|
||||
}
|
||||
);
|
||||
|
||||
if (!data?.getUser || error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return data.getUser;
|
||||
},
|
||||
getAmbossLoginToken: async (
|
||||
_: undefined,
|
||||
__: undefined,
|
||||
{ ip, ambossAuth }: ContextType
|
||||
) => {
|
||||
await requestLimiter(ip, 'getAmbossLoginToken');
|
||||
|
||||
const { data, error } = await graphqlFetchWithProxy(
|
||||
appUrls.amboss,
|
||||
getLoginTokenQuery,
|
||||
{ seconds: ONE_MONTH_SECONDS },
|
||||
{
|
||||
authorization: ambossAuth ? `Bearer ${ambossAuth}` : '',
|
||||
}
|
||||
);
|
||||
|
||||
if (!data?.getLoginToken || error) {
|
||||
throw new Error('Error getting login token from Amboss');
|
||||
}
|
||||
|
||||
return data.getLoginToken;
|
||||
},
|
||||
},
|
||||
Mutation: {
|
||||
loginAmboss: async (
|
||||
_: undefined,
|
||||
__: undefined,
|
||||
{ ip, lnd, res }: ContextType
|
||||
) => {
|
||||
await requestLimiter(ip, 'loginAmboss');
|
||||
|
||||
const { data, error } = await graphqlFetchWithProxy(
|
||||
appUrls.amboss,
|
||||
getSignInfoQuery
|
||||
);
|
||||
|
||||
if (!data?.getSignInfo || error) {
|
||||
throw new Error('Error getting login information from Amboss');
|
||||
}
|
||||
|
||||
const [message, signError] = await toWithError<{ signature: string }>(
|
||||
signMessage({
|
||||
lnd,
|
||||
message: data.getSignInfo.message,
|
||||
})
|
||||
);
|
||||
|
||||
if (!message?.signature || signError) {
|
||||
throw new Error('Error signing message to login');
|
||||
}
|
||||
|
||||
logger.debug('Signed Amboss login message');
|
||||
|
||||
const { identifier } = data.getSignInfo;
|
||||
const params = {
|
||||
details: 'ThunderHub',
|
||||
identifier,
|
||||
signature: message.signature,
|
||||
token: true,
|
||||
seconds: ONE_MONTH_SECONDS,
|
||||
};
|
||||
|
||||
const { data: loginData, error: loginError } =
|
||||
await graphqlFetchWithProxy(appUrls.amboss, loginMutation, params);
|
||||
|
||||
if (!loginData.login || loginError) {
|
||||
throw new Error('Error logging into Amboss');
|
||||
}
|
||||
|
||||
logger.debug('Got Amboss login token');
|
||||
|
||||
res.setHeader(
|
||||
'Set-Cookie',
|
||||
cookieLib.serialize(appConstants.ambossCookieName, loginData.login, {
|
||||
maxAge: ONE_MONTH_SECONDS,
|
||||
httpOnly: true,
|
||||
sameSite: true,
|
||||
path: '/',
|
||||
})
|
||||
);
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
};
|
13
server/schema/amboss/types.ts
Normal file
13
server/schema/amboss/types.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { gql } from 'apollo-server-micro';
|
||||
|
||||
export const ambossTypes = gql`
|
||||
type AmbossSubscriptionType {
|
||||
end_date: String!
|
||||
subscribed: Boolean!
|
||||
upgradable: Boolean!
|
||||
}
|
||||
|
||||
type AmbossUserType {
|
||||
subscription: AmbossSubscriptionType
|
||||
}
|
||||
`;
|
@ -44,6 +44,7 @@ export const getContext = (context: ResolverContext) => {
|
||||
const auth = cookies[appConstants.cookieName];
|
||||
const lnMarketsAuth = cookies[appConstants.lnMarketsAuth];
|
||||
const tokenAuth = cookies[appConstants.tokenCookieName];
|
||||
const ambossAuth = cookies[appConstants.ambossCookieName];
|
||||
|
||||
let lnd: LndObject | null = null;
|
||||
let id: string | null = null;
|
||||
@ -70,6 +71,7 @@ export const getContext = (context: ResolverContext) => {
|
||||
res,
|
||||
lnMarketsAuth,
|
||||
tokenAuth,
|
||||
ambossAuth,
|
||||
};
|
||||
|
||||
return resolverContext;
|
||||
|
@ -46,6 +46,8 @@ import { boltzResolvers } from './boltz/resolvers';
|
||||
import { boltzTypes } from './boltz/types';
|
||||
import { forwardsResolver } from './forwards/resolvers';
|
||||
import { macaroonTypes } from './macaroon/types';
|
||||
import { ambossTypes } from './amboss/types';
|
||||
import { ambossResolvers } from './amboss/resolvers';
|
||||
|
||||
const typeDefs = [
|
||||
generalTypes,
|
||||
@ -71,6 +73,7 @@ const typeDefs = [
|
||||
lnMarketsTypes,
|
||||
boltzTypes,
|
||||
macaroonTypes,
|
||||
ambossTypes,
|
||||
];
|
||||
|
||||
const resolvers = merge(
|
||||
@ -98,7 +101,8 @@ const resolvers = merge(
|
||||
lnUrlResolvers,
|
||||
lnMarketsResolvers,
|
||||
boltzResolvers,
|
||||
forwardsResolver
|
||||
forwardsResolver,
|
||||
ambossResolvers
|
||||
);
|
||||
|
||||
export const schema = makeExecutableSchema({ typeDefs, resolvers });
|
||||
|
@ -28,6 +28,8 @@ export const generalTypes = gql`
|
||||
|
||||
export const queryTypes = gql`
|
||||
type Query {
|
||||
getAmbossLoginToken: String!
|
||||
getAmbossUser: AmbossUserType
|
||||
getNodeBalances: BalancesType!
|
||||
getBosNodeScores(publicKey: String!): [BosScore]!
|
||||
getBosScores: BosScoreResponse!
|
||||
@ -94,6 +96,7 @@ export const queryTypes = gql`
|
||||
|
||||
export const mutationTypes = gql`
|
||||
type Mutation {
|
||||
loginAmboss: Boolean
|
||||
getAuthToken(cookie: String): Boolean!
|
||||
getSessionToken(id: String, password: String): String!
|
||||
claimBoltzTransaction(
|
||||
|
@ -25,6 +25,7 @@ export const ContextMock: ContextType = {
|
||||
res: {} as ServerResponse,
|
||||
lnMarketsAuth: 'lnMarketAuth',
|
||||
tokenAuth: 'tokenAuth',
|
||||
ambossAuth: 'ambossAuth',
|
||||
};
|
||||
|
||||
export const ContextMockNoAccounts: ContextType = {
|
||||
@ -41,6 +42,7 @@ export const ContextMockNoAccounts: ContextType = {
|
||||
res: {} as ServerResponse,
|
||||
lnMarketsAuth: 'lnMarketAuth',
|
||||
tokenAuth: 'tokenAuth',
|
||||
ambossAuth: 'ambossAuth',
|
||||
};
|
||||
|
||||
export const ContextMockNoSSO: ContextType = {
|
||||
@ -63,4 +65,5 @@ export const ContextMockNoSSO: ContextType = {
|
||||
res: {} as ServerResponse,
|
||||
lnMarketsAuth: 'lnMarketAuth',
|
||||
tokenAuth: 'tokenAuth',
|
||||
ambossAuth: 'ambossAuth',
|
||||
};
|
||||
|
@ -18,4 +18,5 @@ export type ContextType = {
|
||||
res: ServerResponse;
|
||||
lnMarketsAuth: string | null;
|
||||
tokenAuth: string | null;
|
||||
ambossAuth: string | null;
|
||||
};
|
||||
|
@ -2,4 +2,5 @@ export const appConstants = {
|
||||
cookieName: 'Thub-Auth',
|
||||
lnMarketsAuth: 'LnMarkets-Auth',
|
||||
tokenCookieName: 'Tbase-Auth',
|
||||
ambossCookieName: 'Amboss-Auth',
|
||||
};
|
||||
|
@ -15,4 +15,5 @@ export const appUrls = {
|
||||
lnMarkets: 'https://api.lnmarkets.com/v1',
|
||||
lnMarketsExchange: 'https://lnmarkets.com',
|
||||
boltz: 'https://boltz.exchange/api',
|
||||
amboss: 'https://api.amboss.space/graphql',
|
||||
};
|
||||
|
@ -22,18 +22,30 @@ export const fetchWithProxy = (url: string, options?: {}) => {
|
||||
export const graphqlFetchWithProxy = async (
|
||||
url: string,
|
||||
query: string,
|
||||
variables?: { [key: string]: string | number | string[] }
|
||||
variables?: { [key: string]: string | number | string[] | boolean },
|
||||
headers?: { [key: string]: string | number | string[] | boolean }
|
||||
): Promise<{
|
||||
data: any;
|
||||
error: undefined | GraphQLError;
|
||||
}> => {
|
||||
return fetchWithProxy(url, {
|
||||
method: 'post',
|
||||
headers: { Accept: 'application/json' },
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...(headers || {}),
|
||||
},
|
||||
body: JSON.stringify({ query, variables }),
|
||||
})
|
||||
.then(res => res.json() as any)
|
||||
.then(data => data)
|
||||
.then(result => {
|
||||
logger.silly(result);
|
||||
const { data, errors } = result;
|
||||
return {
|
||||
data,
|
||||
error: errors?.[0]?.message,
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Error doing graphql fetch: %o', error);
|
||||
return { data: undefined, error };
|
||||
|
42
src/graphql/mutations/__generated__/loginAmboss.generated.tsx
generated
Normal file
42
src/graphql/mutations/__generated__/loginAmboss.generated.tsx
generated
Normal file
@ -0,0 +1,42 @@
|
||||
/* eslint-disable */
|
||||
import * as Types from '../../types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {}
|
||||
export type LoginAmbossMutationVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type LoginAmbossMutation = { __typename?: 'Mutation', loginAmboss?: Types.Maybe<boolean> };
|
||||
|
||||
|
||||
export const LoginAmbossDocument = gql`
|
||||
mutation LoginAmboss {
|
||||
loginAmboss
|
||||
}
|
||||
`;
|
||||
export type LoginAmbossMutationFn = Apollo.MutationFunction<LoginAmbossMutation, LoginAmbossMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useLoginAmbossMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useLoginAmbossMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useLoginAmbossMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [loginAmbossMutation, { data, loading, error }] = useLoginAmbossMutation({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useLoginAmbossMutation(baseOptions?: Apollo.MutationHookOptions<LoginAmbossMutation, LoginAmbossMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<LoginAmbossMutation, LoginAmbossMutationVariables>(LoginAmbossDocument, options);
|
||||
}
|
||||
export type LoginAmbossMutationHookResult = ReturnType<typeof useLoginAmbossMutation>;
|
||||
export type LoginAmbossMutationResult = Apollo.MutationResult<LoginAmbossMutation>;
|
||||
export type LoginAmbossMutationOptions = Apollo.BaseMutationOptions<LoginAmbossMutation, LoginAmbossMutationVariables>;
|
7
src/graphql/mutations/loginAmboss.ts
Normal file
7
src/graphql/mutations/loginAmboss.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const LOGIN_AMBOSS = gql`
|
||||
mutation LoginAmboss {
|
||||
loginAmboss
|
||||
}
|
||||
`;
|
44
src/graphql/queries/__generated__/getAmbossLoginToken.generated.tsx
generated
Normal file
44
src/graphql/queries/__generated__/getAmbossLoginToken.generated.tsx
generated
Normal file
@ -0,0 +1,44 @@
|
||||
/* eslint-disable */
|
||||
import * as Types from '../../types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {}
|
||||
export type GetAmbossLoginTokenQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetAmbossLoginTokenQuery = { __typename?: 'Query', getAmbossLoginToken: string };
|
||||
|
||||
|
||||
export const GetAmbossLoginTokenDocument = gql`
|
||||
query GetAmbossLoginToken {
|
||||
getAmbossLoginToken
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetAmbossLoginTokenQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetAmbossLoginTokenQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetAmbossLoginTokenQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useGetAmbossLoginTokenQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetAmbossLoginTokenQuery(baseOptions?: Apollo.QueryHookOptions<GetAmbossLoginTokenQuery, GetAmbossLoginTokenQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<GetAmbossLoginTokenQuery, GetAmbossLoginTokenQueryVariables>(GetAmbossLoginTokenDocument, options);
|
||||
}
|
||||
export function useGetAmbossLoginTokenLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetAmbossLoginTokenQuery, GetAmbossLoginTokenQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<GetAmbossLoginTokenQuery, GetAmbossLoginTokenQueryVariables>(GetAmbossLoginTokenDocument, options);
|
||||
}
|
||||
export type GetAmbossLoginTokenQueryHookResult = ReturnType<typeof useGetAmbossLoginTokenQuery>;
|
||||
export type GetAmbossLoginTokenLazyQueryHookResult = ReturnType<typeof useGetAmbossLoginTokenLazyQuery>;
|
||||
export type GetAmbossLoginTokenQueryResult = Apollo.QueryResult<GetAmbossLoginTokenQuery, GetAmbossLoginTokenQueryVariables>;
|
50
src/graphql/queries/__generated__/getAmbossUser.generated.tsx
generated
Normal file
50
src/graphql/queries/__generated__/getAmbossUser.generated.tsx
generated
Normal file
@ -0,0 +1,50 @@
|
||||
/* eslint-disable */
|
||||
import * as Types from '../../types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {}
|
||||
export type GetAmbossUserQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetAmbossUserQuery = { __typename?: 'Query', getAmbossUser?: Types.Maybe<{ __typename?: 'AmbossUserType', subscription?: Types.Maybe<{ __typename?: 'AmbossSubscriptionType', end_date: string, subscribed: boolean, upgradable: boolean }> }> };
|
||||
|
||||
|
||||
export const GetAmbossUserDocument = gql`
|
||||
query GetAmbossUser {
|
||||
getAmbossUser {
|
||||
subscription {
|
||||
end_date
|
||||
subscribed
|
||||
upgradable
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetAmbossUserQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetAmbossUserQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetAmbossUserQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useGetAmbossUserQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetAmbossUserQuery(baseOptions?: Apollo.QueryHookOptions<GetAmbossUserQuery, GetAmbossUserQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<GetAmbossUserQuery, GetAmbossUserQueryVariables>(GetAmbossUserDocument, options);
|
||||
}
|
||||
export function useGetAmbossUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetAmbossUserQuery, GetAmbossUserQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<GetAmbossUserQuery, GetAmbossUserQueryVariables>(GetAmbossUserDocument, options);
|
||||
}
|
||||
export type GetAmbossUserQueryHookResult = ReturnType<typeof useGetAmbossUserQuery>;
|
||||
export type GetAmbossUserLazyQueryHookResult = ReturnType<typeof useGetAmbossUserLazyQuery>;
|
||||
export type GetAmbossUserQueryResult = Apollo.QueryResult<GetAmbossUserQuery, GetAmbossUserQueryVariables>;
|
7
src/graphql/queries/getAmbossLoginToken.ts
Normal file
7
src/graphql/queries/getAmbossLoginToken.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_AMBOSS_LOGIN_TOKEN = gql`
|
||||
query GetAmbossLoginToken {
|
||||
getAmbossLoginToken
|
||||
}
|
||||
`;
|
13
src/graphql/queries/getAmbossUser.ts
Normal file
13
src/graphql/queries/getAmbossUser.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_AMBOSS_USER = gql`
|
||||
query GetAmbossUser {
|
||||
getAmbossUser {
|
||||
subscription {
|
||||
end_date
|
||||
subscribed
|
||||
upgradable
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
@ -18,6 +18,18 @@ export type Scalars = {
|
||||
Time: any;
|
||||
};
|
||||
|
||||
export type AmbossSubscriptionType = {
|
||||
__typename?: 'AmbossSubscriptionType';
|
||||
end_date: Scalars['String'];
|
||||
subscribed: Scalars['Boolean'];
|
||||
upgradable: Scalars['Boolean'];
|
||||
};
|
||||
|
||||
export type AmbossUserType = {
|
||||
__typename?: 'AmbossUserType';
|
||||
subscription?: Maybe<AmbossSubscriptionType>;
|
||||
};
|
||||
|
||||
export type AuthResponse = {
|
||||
__typename?: 'AuthResponse';
|
||||
message: Scalars['String'];
|
||||
@ -229,6 +241,7 @@ export type Mutation = {
|
||||
lnUrlChannel: Scalars['String'];
|
||||
lnUrlPay: PaySuccess;
|
||||
lnUrlWithdraw: Scalars['String'];
|
||||
loginAmboss?: Maybe<Scalars['Boolean']>;
|
||||
logout: Scalars['Boolean'];
|
||||
openChannel?: Maybe<OpenChannelType>;
|
||||
pay?: Maybe<Scalars['Boolean']>;
|
||||
@ -521,6 +534,8 @@ export type Query = {
|
||||
decodeRequest?: Maybe<DecodeType>;
|
||||
getAccount?: Maybe<ServerAccountType>;
|
||||
getAccountingReport: Scalars['String'];
|
||||
getAmbossLoginToken: Scalars['String'];
|
||||
getAmbossUser?: Maybe<AmbossUserType>;
|
||||
getBackups?: Maybe<Scalars['String']>;
|
||||
getBaseCanConnect: Scalars['Boolean'];
|
||||
getBaseInfo: BaseInfo;
|
||||
|
11
src/hooks/UseAmbossUser.tsx
Normal file
11
src/hooks/UseAmbossUser.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { useGetAmbossUserQuery } from 'src/graphql/queries/__generated__/getAmbossUser.generated';
|
||||
|
||||
export const useAmbossUser = () => {
|
||||
const { data, loading } = useGetAmbossUserQuery();
|
||||
|
||||
if (loading || !data?.getAmbossUser) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return data.getAmbossUser.subscription;
|
||||
};
|
@ -20,6 +20,7 @@ import { SupportBar } from './donate/DonateContent';
|
||||
import { OpenChannel } from './openChannel';
|
||||
import { LnUrlCard } from './lnurl';
|
||||
import { LnMarketsCard } from './lnmarkets';
|
||||
import { AmbossCard } from './amboss/AmbossCard';
|
||||
|
||||
export const QuickCard = styled.div`
|
||||
background: ${cardColor};
|
||||
@ -50,7 +51,7 @@ export const QuickCard = styled.div`
|
||||
`;
|
||||
|
||||
export const QuickTitle = styled.div`
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
color: ${unSelectedNavButton};
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
@ -99,6 +100,7 @@ export const QuickActions = () => {
|
||||
return (
|
||||
<QuickRow>
|
||||
<SupportCard callback={() => setOpenCard('support')} />
|
||||
<AmbossCard />
|
||||
<QuickCard onClick={() => setOpenCard('open_channel')}>
|
||||
<GitBranch size={24} />
|
||||
<QuickTitle>Open</QuickTitle>
|
||||
|
109
src/views/home/quickActions/amboss/AmbossCard.tsx
Normal file
109
src/views/home/quickActions/amboss/AmbossCard.tsx
Normal file
@ -0,0 +1,109 @@
|
||||
import { useEffect } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useLoginAmbossMutation } from 'src/graphql/mutations/__generated__/loginAmboss.generated';
|
||||
import { useGetAmbossLoginTokenLazyQuery } from 'src/graphql/queries/__generated__/getAmbossLoginToken.generated';
|
||||
import { useAmbossUser } from 'src/hooks/UseAmbossUser';
|
||||
import {
|
||||
cardBorderColor,
|
||||
cardColor,
|
||||
mediaWidths,
|
||||
unSelectedNavButton,
|
||||
} from 'src/styles/Themes';
|
||||
import styled from 'styled-components';
|
||||
import Image from 'next/image';
|
||||
import ambossLogo from './AmbossLogo.png';
|
||||
|
||||
const QuickTitle = styled.div`
|
||||
font-size: 12px;
|
||||
color: ${unSelectedNavButton};
|
||||
margin-top: 10px;
|
||||
`;
|
||||
|
||||
const QuickCard = styled.button`
|
||||
background: ${cardColor};
|
||||
box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
border: 1px solid ${cardBorderColor};
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 25px;
|
||||
padding: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
color: #69c0ff;
|
||||
|
||||
@media (${mediaWidths.mobile}) {
|
||||
padding: 4px;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #ff0080;
|
||||
color: white;
|
||||
|
||||
img {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
& ${QuickTitle} {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const AmbossCard = () => {
|
||||
const subscription = useAmbossUser();
|
||||
|
||||
const [login, { loading }] = useLoginAmbossMutation({
|
||||
onCompleted: () => toast.success('Logged in'),
|
||||
onError: () => toast.error('Error logging in'),
|
||||
refetchQueries: ['GetAmbossUser'],
|
||||
});
|
||||
|
||||
const [getToken, { data, loading: tokenLoading }] =
|
||||
useGetAmbossLoginTokenLazyQuery({
|
||||
onError: () => toast.error('Error getting auth token'),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!data?.getAmbossLoginToken || tokenLoading) {
|
||||
return;
|
||||
}
|
||||
if (!window?.open) return;
|
||||
const url = `https://amboss.space/token?key=${data.getAmbossLoginToken}`;
|
||||
(window as any).open(url, '_blank').focus();
|
||||
}, [data, tokenLoading]);
|
||||
|
||||
if (!subscription) {
|
||||
return (
|
||||
<QuickCard
|
||||
onClick={() => {
|
||||
if (loading) return;
|
||||
login();
|
||||
}}
|
||||
disabled={loading}
|
||||
>
|
||||
<Image src={ambossLogo} width={32} height={32} alt={'Amboss Logo'} />
|
||||
<QuickTitle>{loading ? 'Loading...' : 'Login'}</QuickTitle>
|
||||
</QuickCard>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<QuickCard
|
||||
onClick={() => {
|
||||
if (tokenLoading) return;
|
||||
getToken();
|
||||
}}
|
||||
disabled={tokenLoading}
|
||||
>
|
||||
<Image src={ambossLogo} width={32} height={32} alt={'Amboss Logo'} />
|
||||
<QuickTitle>{tokenLoading ? 'Loading...' : 'Go To'}</QuickTitle>
|
||||
</QuickCard>
|
||||
);
|
||||
};
|
BIN
src/views/home/quickActions/amboss/AmbossLogo.png
Normal file
BIN
src/views/home/quickActions/amboss/AmbossLogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
@ -10,7 +10,7 @@ import {
|
||||
} from 'src/styles/Themes';
|
||||
|
||||
const QuickTitle = styled.div`
|
||||
font-size: 14px;
|
||||
font-size: 12px;
|
||||
color: ${unSelectedNavButton};
|
||||
margin-top: 10px;
|
||||
`;
|
||||
|
Loading…
Reference in New Issue
Block a user