feat: add wallet version query and view

This commit is contained in:
AP 2020-05-03 11:14:36 +02:00
parent 82296f3fbb
commit ac577b5438
13 changed files with 262 additions and 73 deletions

View file

@ -12,6 +12,7 @@
"release": "standard-version",
"release:push": "standard-version && git push --follow-tags origin master",
"release:test": "standard-version --dry-run",
"release:minor": "standard-version --release-as minor && git push --follow-tags origin master",
"analyze": "cross-env ANALYZE=true next build",
"storybook": "start-storybook -p 6006 -c .storybook",
"generate": "graphql-codegen --config codegen.yml",

View file

@ -1,11 +1,13 @@
import React from 'react';
import { BackupsView } from '../src/views/tools/backups/Backups';
import { MessagesView } from '../src/views/tools/messages/Messages';
import { WalletVersion } from '../src/views/tools/WalletVersion';
const ToolsView = () => (
<>
<BackupsView />
<MessagesView />
<WalletVersion />
</>
);

View file

@ -1,4 +1,5 @@
import { authenticatedLndGrpc } from 'ln-service';
import { logger } from './logger';
import getConfig from 'next/config';
const { serverRuntimeConfig } = getConfig();
@ -49,3 +50,14 @@ export const getErrorMsg = (error: any[] | string): string => {
return 'Error';
};
export const to = promise => {
return promise
.then(data => {
return data;
})
.catch(err => {
logger.error('%o', err);
throw new Error(getErrorMsg(err));
});
};

View file

@ -6,22 +6,10 @@ import {
} from 'ln-service';
import { requestLimiter } from '../../../helpers/rateLimiter';
import { GraphQLString, GraphQLNonNull, GraphQLInt } from 'graphql';
import { getErrorMsg, getAuthLnd } from '../../../helpers/helpers';
import { getAuthLnd, to } from '../../../helpers/helpers';
import { defaultParams } from '../../../helpers/defaultProps';
import { createCustomRecords } from '../../../helpers/customRecords';
import { randomBytes, createHash } from 'crypto';
import { logger } from '../../../helpers/logger';
const to = promise => {
return promise
.then(data => {
return data;
})
.catch(err => {
logger.error('%o', err);
throw new Error(getErrorMsg(err));
});
};
export const sendMessage = {
type: GraphQLInt,

View file

@ -1,20 +1,11 @@
import { GraphQLString, GraphQLBoolean } from 'graphql';
import { getInvoices, verifyMessage } from 'ln-service';
import { logger } from '../../../helpers/logger';
import { requestLimiter } from '../../../helpers/rateLimiter';
import { getAuthLnd, getErrorMsg } from '../../../helpers/helpers';
import { getAuthLnd, to } from '../../../helpers/helpers';
import { defaultParams } from '../../../helpers/defaultProps';
import { decodeMessage } from '../../../helpers/customRecords';
import { GetMessagesType } from '../../types/QueryType';
const to = promise => {
return promise
.then(data => {
return [null, data];
})
.catch(err => [err]);
};
export const getMessages = {
type: GetMessagesType,
args: {
@ -28,18 +19,13 @@ export const getMessages = {
const lnd = getAuthLnd(params.auth);
const [error, invoiceList] = await to(
const invoiceList = await to(
getInvoices({
lnd,
limit: params.initialize ? 100 : 5,
})
);
if (error) {
logger.error('Error getting invoices: %o', error);
throw new Error(getErrorMsg(error));
}
const getFiltered = () =>
Promise.all(
invoiceList.invoices.map(async invoice => {
@ -69,7 +55,7 @@ export const getMessages = {
message: customRecords.message,
});
const [error, { signed_by }] = await to(
const { signed_by } = await to(
verifyMessage({
lnd,
message: messageToVerify,
@ -77,7 +63,7 @@ export const getMessages = {
})
);
if (!error && signed_by === customRecords.sender) {
if (signed_by === customRecords.sender) {
isVerified = true;
}
}

View file

@ -3,6 +3,7 @@ import { getNodeInfo } from './nodeInfo';
import { getNode } from './getNode';
import { adminCheck } from './adminCheck';
import { decodeRequest } from './decode';
import { getWalletInfo } from './walletInfo';
export const generalQueries = {
getNetworkInfo,
@ -10,4 +11,5 @@ export const generalQueries = {
adminCheck,
getNode,
decodeRequest,
getWalletInfo,
};

View file

@ -0,0 +1,21 @@
import { getWalletVersion } from 'ln-service';
import { requestLimiter } from '../../../helpers/rateLimiter';
import { getAuthLnd, to } from '../../../helpers/helpers';
import { defaultParams } from '../../../helpers/defaultProps';
import { WalletInfoType } from '../../types/QueryType';
export const getWalletInfo = {
type: WalletInfoType,
args: defaultParams,
resolve: async (root: any, params: any, context: any) => {
await requestLimiter(context.ip, 'getWalletInfo');
const lnd = getAuthLnd(params.auth);
return await to(
getWalletVersion({
lnd,
})
);
},
};

View file

@ -243,6 +243,23 @@ export const NodeInfoType = new GraphQLObjectType({
},
});
export const WalletInfoType = new GraphQLObjectType({
name: 'walletInfoType',
fields: () => {
return {
build_tags: { type: new GraphQLList(GraphQLString) },
commit_hash: { type: GraphQLString },
is_autopilotrpc_enabled: { type: GraphQLBoolean },
is_chainrpc_enabled: { type: GraphQLBoolean },
is_invoicesrpc_enabled: { type: GraphQLBoolean },
is_signrpc_enabled: { type: GraphQLBoolean },
is_walletrpc_enabled: { type: GraphQLBoolean },
is_watchtowerrpc_enabled: { type: GraphQLBoolean },
is_wtclientrpc_enabled: { type: GraphQLBoolean },
};
},
});
export const GetChainTransactionsType = new GraphQLObjectType({
name: 'getTransactionsType',
fields: () => ({

View file

@ -52,4 +52,5 @@ export const RateConfig: RateConfigProps = {
getCurrencies: { max: 10, window: '1s' },
sendMessage: { max: 10, window: '1s' },
getMessages: { max: 10, window: '1s' },
getWalletInfo: { max: 10, window: '1s' },
};

View file

@ -26,6 +26,7 @@ export type Query = {
adminCheck?: Maybe<Scalars['Boolean']>;
getNode?: Maybe<PartnerNodeType>;
decodeRequest?: Maybe<DecodeType>;
getWalletInfo?: Maybe<WalletInfoType>;
getResume?: Maybe<GetResumeType>;
getForwards?: Maybe<GetForwardType>;
getBitcoinPrice?: Maybe<Scalars['String']>;
@ -52,73 +53,64 @@ export type Query = {
export type QueryGetChannelBalanceArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetChannelsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
active?: Maybe<Scalars['Boolean']>;
};
export type QueryGetClosedChannelsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
type?: Maybe<Scalars['String']>;
};
export type QueryGetPendingChannelsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetChannelFeesArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetChannelReportArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetNetworkInfoArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetNodeInfoArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryAdminCheckArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetNodeArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
publicKey: Scalars['String'];
withoutChannels?: Maybe<Scalars['Boolean']>;
};
export type QueryDecodeRequestArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
request: Scalars['String'];
};
export type QueryGetWalletInfoArgs = {
auth: AuthType;
};
export type QueryGetResumeArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
token?: Maybe<Scalars['String']>;
};
export type QueryGetForwardsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
time?: Maybe<Scalars['String']>;
};
@ -133,13 +125,11 @@ export type QueryGetBitcoinFeesArgs = {
export type QueryGetForwardReportArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
time?: Maybe<Scalars['String']>;
};
export type QueryGetForwardChannelsReportArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
time?: Maybe<Scalars['String']>;
order?: Maybe<Scalars['String']>;
type?: Maybe<Scalars['String']>;
@ -147,30 +137,25 @@ export type QueryGetForwardChannelsReportArgs = {
export type QueryGetInOutArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
time?: Maybe<Scalars['String']>;
};
export type QueryGetBackupsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryVerifyBackupsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
backup: Scalars['String'];
};
export type QueryRecoverFundsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
backup: Scalars['String'];
};
export type QueryGetRoutesArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
outgoing: Scalars['String'];
incoming: Scalars['String'];
tokens: Scalars['Int'];
@ -179,40 +164,33 @@ export type QueryGetRoutesArgs = {
export type QueryGetPeersArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QuerySignMessageArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
message: Scalars['String'];
};
export type QueryVerifyMessageArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
message: Scalars['String'];
signature: Scalars['String'];
};
export type QueryGetChainBalanceArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetPendingChainBalanceArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetChainTransactionsArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetUtxosArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
};
export type QueryGetOffersArgs = {
@ -221,7 +199,6 @@ export type QueryGetOffersArgs = {
export type QueryGetMessagesArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
token?: Maybe<Scalars['String']>;
initialize?: Maybe<Scalars['Boolean']>;
lastMessage?: Maybe<Scalars['String']>;
@ -387,6 +364,19 @@ export type DecodeRoutesType = {
public_key?: Maybe<Scalars['String']>;
};
export type WalletInfoType = {
__typename?: 'walletInfoType';
build_tags?: Maybe<Array<Maybe<Scalars['String']>>>;
commit_hash?: Maybe<Scalars['String']>;
is_autopilotrpc_enabled?: Maybe<Scalars['Boolean']>;
is_chainrpc_enabled?: Maybe<Scalars['Boolean']>;
is_invoicesrpc_enabled?: Maybe<Scalars['Boolean']>;
is_signrpc_enabled?: Maybe<Scalars['Boolean']>;
is_walletrpc_enabled?: Maybe<Scalars['Boolean']>;
is_watchtowerrpc_enabled?: Maybe<Scalars['Boolean']>;
is_wtclientrpc_enabled?: Maybe<Scalars['Boolean']>;
};
export type GetResumeType = {
__typename?: 'getResumeType';
token?: Maybe<Scalars['String']>;
@ -574,7 +564,6 @@ export type Mutation = {
export type MutationCloseChannelArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
id: Scalars['String'];
forceClose?: Maybe<Scalars['Boolean']>;
targetConfirmations?: Maybe<Scalars['Int']>;
@ -583,7 +572,6 @@ export type MutationCloseChannelArgs = {
export type MutationOpenChannelArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
amount: Scalars['Int'];
partnerPublicKey: Scalars['String'];
tokensPerVByte?: Maybe<Scalars['Int']>;
@ -592,7 +580,6 @@ export type MutationOpenChannelArgs = {
export type MutationUpdateFeesArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
transactionId?: Maybe<Scalars['String']>;
transactionVout?: Maybe<Scalars['Int']>;
baseFee?: Maybe<Scalars['Int']>;
@ -601,38 +588,32 @@ export type MutationUpdateFeesArgs = {
export type MutationParsePaymentArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
request: Scalars['String'];
};
export type MutationPayArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
request: Scalars['String'];
tokens?: Maybe<Scalars['Int']>;
};
export type MutationCreateInvoiceArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
amount: Scalars['Int'];
};
export type MutationPayViaRouteArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
route: Scalars['String'];
};
export type MutationCreateAddressArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
nested?: Maybe<Scalars['Boolean']>;
};
export type MutationSendToAddressArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
address: Scalars['String'];
tokens?: Maybe<Scalars['Int']>;
fee?: Maybe<Scalars['Int']>;
@ -642,7 +623,6 @@ export type MutationSendToAddressArgs = {
export type MutationAddPeerArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
publicKey: Scalars['String'];
socket: Scalars['String'];
isTemporary?: Maybe<Scalars['Boolean']>;
@ -650,13 +630,11 @@ export type MutationAddPeerArgs = {
export type MutationRemovePeerArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
publicKey: Scalars['String'];
};
export type MutationSendMessageArgs = {
auth: AuthType;
logger?: Maybe<Scalars['Boolean']>;
publicKey: Scalars['String'];
message: Scalars['String'];
messageType?: Maybe<Scalars['String']>;
@ -1570,6 +1548,27 @@ export type GetMessagesQuery = { __typename?: 'Query' } & {
>;
};
export type GetWalletInfoQueryVariables = {
auth: AuthType;
};
export type GetWalletInfoQuery = { __typename?: 'Query' } & {
getWalletInfo?: Maybe<
{ __typename?: 'walletInfoType' } & Pick<
WalletInfoType,
| 'build_tags'
| 'commit_hash'
| 'is_autopilotrpc_enabled'
| 'is_chainrpc_enabled'
| 'is_invoicesrpc_enabled'
| 'is_signrpc_enabled'
| 'is_walletrpc_enabled'
| 'is_watchtowerrpc_enabled'
| 'is_wtclientrpc_enabled'
>
>;
};
export const GetCountriesDocument = gql`
query GetCountries {
getCountries {
@ -4303,3 +4302,67 @@ export type GetMessagesQueryResult = ApolloReactCommon.QueryResult<
GetMessagesQuery,
GetMessagesQueryVariables
>;
export const GetWalletInfoDocument = gql`
query GetWalletInfo($auth: authType!) {
getWalletInfo(auth: $auth) {
build_tags
commit_hash
is_autopilotrpc_enabled
is_chainrpc_enabled
is_invoicesrpc_enabled
is_signrpc_enabled
is_walletrpc_enabled
is_watchtowerrpc_enabled
is_wtclientrpc_enabled
}
}
`;
/**
* __useGetWalletInfoQuery__
*
* To run a query within a React component, call `useGetWalletInfoQuery` and pass it any options that fit your needs.
* When your component renders, `useGetWalletInfoQuery` 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 } = useGetWalletInfoQuery({
* variables: {
* auth: // value for 'auth'
* },
* });
*/
export function useGetWalletInfoQuery(
baseOptions?: ApolloReactHooks.QueryHookOptions<
GetWalletInfoQuery,
GetWalletInfoQueryVariables
>
) {
return ApolloReactHooks.useQuery<
GetWalletInfoQuery,
GetWalletInfoQueryVariables
>(GetWalletInfoDocument, baseOptions);
}
export function useGetWalletInfoLazyQuery(
baseOptions?: ApolloReactHooks.LazyQueryHookOptions<
GetWalletInfoQuery,
GetWalletInfoQueryVariables
>
) {
return ApolloReactHooks.useLazyQuery<
GetWalletInfoQuery,
GetWalletInfoQueryVariables
>(GetWalletInfoDocument, baseOptions);
}
export type GetWalletInfoQueryHookResult = ReturnType<
typeof useGetWalletInfoQuery
>;
export type GetWalletInfoLazyQueryHookResult = ReturnType<
typeof useGetWalletInfoLazyQuery
>;
export type GetWalletInfoQueryResult = ApolloReactCommon.QueryResult<
GetWalletInfoQuery,
GetWalletInfoQueryVariables
>;

View file

@ -445,3 +445,19 @@ export const GET_MESSAGES = gql`
}
}
`;
export const GET_WALLET_INFO = gql`
query GetWalletInfo($auth: authType!) {
getWalletInfo(auth: $auth) {
build_tags
commit_hash
is_autopilotrpc_enabled
is_chainrpc_enabled
is_invoicesrpc_enabled
is_signrpc_enabled
is_walletrpc_enabled
is_watchtowerrpc_enabled
is_wtclientrpc_enabled
}
}
`;

View file

@ -66,12 +66,15 @@ const Padding = styled.span`
export const NetworkInfo = () => {
const { auth } = useAccount();
const { loading, data } = useGetNetworkInfoQuery({
const { loading, data, error } = useGetNetworkInfoQuery({
skip: !auth,
variables: { auth },
onError: error => toast.error(getErrorContent(error)),
});
if (error) {
return null;
}
if (loading || !data || !data.getNetworkInfo) {
return <LoadingCard title={'Network Info'} />;
}

View file

@ -0,0 +1,77 @@
import * as React from 'react';
import {
CardWithTitle,
SubTitle,
Card,
Sub4Title,
Separation,
} from '../../components/generic/Styled';
import { useGetWalletInfoQuery } from '../../generated/graphql';
import { useAccount } from '../../context/AccountContext';
import { useStatusState } from '../../context/StatusContext';
import { LoadingCard } from '../../components/loading/LoadingCard';
import { renderLine } from '../../components/generic/helpers';
export const WalletVersion = () => {
const { minorVersion } = useStatusState();
const { auth } = useAccount();
const { data, loading, error } = useGetWalletInfoQuery({
skip: minorVersion < 10,
variables: { auth },
});
const getStatus = (status: boolean) => (status ? 'Enabled' : 'Disabled');
if (error) {
return null;
}
const renderContent = () => {
if (minorVersion < 10) {
return (
<Card>
Update to LND version 0.10.0 or higher to see your wallet build info.
</Card>
);
}
if (loading || !data?.getWalletInfo) {
return <LoadingCard />;
}
const {
is_autopilotrpc_enabled,
is_chainrpc_enabled,
is_invoicesrpc_enabled,
is_signrpc_enabled,
is_walletrpc_enabled,
is_watchtowerrpc_enabled,
is_wtclientrpc_enabled,
commit_hash,
} = data.getWalletInfo;
return (
<Card>
{renderLine('Commit hash:', commit_hash)}
<Separation />
<Sub4Title>
<b>RPC</b>
</Sub4Title>
{renderLine('Autopilot:', getStatus(is_autopilotrpc_enabled))}
{renderLine('Chain:', getStatus(is_chainrpc_enabled))}
{renderLine('Invoices:', getStatus(is_invoicesrpc_enabled))}
{renderLine('Signer:', getStatus(is_signrpc_enabled))}
{renderLine('Wallet:', getStatus(is_walletrpc_enabled))}
{renderLine('Watchtower:', getStatus(is_watchtowerrpc_enabled))}
{renderLine('WTClient:', getStatus(is_wtclientrpc_enabled))}
</Card>
);
};
return (
<CardWithTitle>
<SubTitle>Wallet Version</SubTitle>
{renderContent()}
</CardWithTitle>
);
};