2020-06-01 08:36:33 +02:00
|
|
|
import { randomBytes, createHash } from 'crypto';
|
|
|
|
import {
|
|
|
|
payViaRoutes,
|
|
|
|
createInvoice,
|
|
|
|
decodePaymentRequest,
|
|
|
|
payViaPaymentDetails,
|
|
|
|
createInvoice as createInvoiceRequest,
|
|
|
|
} from 'ln-service';
|
|
|
|
import { ContextType } from 'server/types/apiTypes';
|
|
|
|
import { logger } from 'server/helpers/logger';
|
|
|
|
import { requestLimiter } from 'server/helpers/rateLimiter';
|
|
|
|
import {
|
|
|
|
getAuthLnd,
|
|
|
|
getErrorMsg,
|
|
|
|
getCorrectAuth,
|
2020-06-06 18:04:19 +02:00
|
|
|
getLnd,
|
2020-06-01 08:36:33 +02:00
|
|
|
} from 'server/helpers/helpers';
|
2020-06-06 18:04:19 +02:00
|
|
|
import { to } from 'server/helpers/async';
|
2020-07-21 23:31:12 +02:00
|
|
|
import { DecodedType } from 'server/types/ln-service.types';
|
2020-06-01 08:36:33 +02:00
|
|
|
|
|
|
|
const KEYSEND_TYPE = '5482373484';
|
|
|
|
|
|
|
|
export const invoiceResolvers = {
|
2020-06-06 18:04:19 +02:00
|
|
|
Query: {
|
|
|
|
decodeRequest: async (_: undefined, params: any, context: ContextType) => {
|
|
|
|
await requestLimiter(context.ip, 'decode');
|
2020-06-01 08:36:33 +02:00
|
|
|
|
2020-06-06 18:04:19 +02:00
|
|
|
const lnd = getLnd(params.auth, context);
|
2020-06-01 08:36:33 +02:00
|
|
|
|
2020-07-21 23:31:12 +02:00
|
|
|
const decoded = await to<DecodedType>(
|
2020-06-06 18:04:19 +02:00
|
|
|
decodePaymentRequest({
|
2020-06-01 08:36:33 +02:00
|
|
|
lnd,
|
2020-06-06 18:04:19 +02:00
|
|
|
request: params.request,
|
|
|
|
})
|
|
|
|
);
|
2020-06-01 08:36:33 +02:00
|
|
|
|
2020-06-06 18:04:19 +02:00
|
|
|
return {
|
|
|
|
...decoded,
|
|
|
|
destination_node: { lnd, publicKey: decoded.destination },
|
|
|
|
probe_route: {
|
2020-06-01 08:36:33 +02:00
|
|
|
lnd,
|
2020-06-06 18:04:19 +02:00
|
|
|
destination: decoded.destination,
|
|
|
|
tokens: decoded.tokens,
|
|
|
|
},
|
|
|
|
};
|
2020-06-01 08:36:33 +02:00
|
|
|
},
|
2020-06-06 18:04:19 +02:00
|
|
|
},
|
|
|
|
Mutation: {
|
|
|
|
createInvoice: async (_: undefined, params: any, context: ContextType) => {
|
|
|
|
await requestLimiter(context.ip, 'createInvoice');
|
2020-06-01 08:36:33 +02:00
|
|
|
|
|
|
|
const auth = getCorrectAuth(params.auth, context);
|
|
|
|
const lnd = getAuthLnd(auth);
|
|
|
|
|
2020-06-06 18:04:19 +02:00
|
|
|
return await to(
|
|
|
|
createInvoiceRequest({
|
2020-06-01 08:36:33 +02:00
|
|
|
lnd,
|
2020-06-06 18:04:19 +02:00
|
|
|
tokens: params.amount,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
},
|
|
|
|
keysend: async (_: undefined, params: any, context: ContextType) => {
|
|
|
|
await requestLimiter(context.ip, 'keysend');
|
2020-06-01 08:36:33 +02:00
|
|
|
|
2020-06-06 18:04:19 +02:00
|
|
|
const { auth, destination, tokens } = params;
|
|
|
|
const lnd = getLnd(auth, context);
|
2020-06-01 08:36:33 +02:00
|
|
|
|
|
|
|
const preimage = randomBytes(32);
|
|
|
|
const secret = preimage.toString('hex');
|
|
|
|
const id = createHash('sha256').update(preimage).digest().toString('hex');
|
|
|
|
|
2020-06-06 18:04:19 +02:00
|
|
|
return await to(
|
|
|
|
payViaPaymentDetails({
|
2020-06-01 08:36:33 +02:00
|
|
|
id,
|
|
|
|
lnd,
|
2020-06-06 18:04:19 +02:00
|
|
|
tokens,
|
|
|
|
destination,
|
2020-06-01 08:36:33 +02:00
|
|
|
messages: [
|
|
|
|
{
|
|
|
|
type: KEYSEND_TYPE,
|
|
|
|
value: secret,
|
|
|
|
},
|
|
|
|
],
|
2020-06-06 18:04:19 +02:00
|
|
|
})
|
|
|
|
);
|
2020-06-01 08:36:33 +02:00
|
|
|
},
|
2020-06-06 18:04:19 +02:00
|
|
|
circularRebalance: async (
|
|
|
|
_: undefined,
|
|
|
|
params: any,
|
|
|
|
context: ContextType
|
|
|
|
) => {
|
|
|
|
await requestLimiter(context.ip, 'circularRebalance');
|
2020-06-01 08:36:33 +02:00
|
|
|
|
|
|
|
const auth = getCorrectAuth(params.auth, context);
|
|
|
|
const lnd = getAuthLnd(auth);
|
|
|
|
|
|
|
|
let route;
|
|
|
|
try {
|
|
|
|
route = JSON.parse(params.route);
|
|
|
|
} catch (error) {
|
|
|
|
logger.error('Corrupt route json: %o', error);
|
|
|
|
throw new Error('Corrupt Route JSON');
|
|
|
|
}
|
|
|
|
|
|
|
|
const { id } = await createInvoice({
|
|
|
|
lnd,
|
|
|
|
tokens: params.tokens,
|
2020-06-20 12:52:59 +02:00
|
|
|
description: 'Rebalance',
|
2020-06-01 08:36:33 +02:00
|
|
|
}).catch((error: any) => {
|
|
|
|
logger.error('Error getting invoice: %o', error);
|
|
|
|
throw new Error(getErrorMsg(error));
|
|
|
|
});
|
|
|
|
|
|
|
|
await payViaRoutes({ lnd, routes: [route], id }).catch((error: any) => {
|
|
|
|
logger.error('Error making payment: %o', error);
|
|
|
|
throw new Error(getErrorMsg(error));
|
|
|
|
});
|
|
|
|
|
2020-06-06 18:04:19 +02:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
payViaRoute: async (_: undefined, params: any, context: ContextType) => {
|
|
|
|
await requestLimiter(context.ip, 'payViaRoute');
|
|
|
|
|
|
|
|
const { auth, route: routeJSON, id } = params;
|
|
|
|
const lnd = getLnd(auth, context);
|
|
|
|
|
|
|
|
let route;
|
|
|
|
try {
|
|
|
|
route = JSON.parse(routeJSON);
|
|
|
|
} catch (error) {
|
|
|
|
logger.error('Corrupt route json: %o', error);
|
|
|
|
throw new Error('Corrupt Route JSON');
|
|
|
|
}
|
|
|
|
|
|
|
|
await to(payViaRoutes({ lnd, routes: [route], id }));
|
|
|
|
|
2020-06-01 08:36:33 +02:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|