Skip to content

Commit

Permalink
Add the uma mutations to JS and update code samples. (#6187)
Browse files Browse the repository at this point in the history
fyi @coreymartin

GitOrigin-RevId: e1997b4c2e3185dc05d304aff9a8eceed5f4b6a1
  • Loading branch information
jklein24 authored and Lightspark Eng committed Sep 16, 2023
1 parent 94ba7f7 commit 25f44d2
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 6 deletions.
108 changes: 104 additions & 4 deletions packages/lightspark-sdk/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ import { TransactionUpdateFromJson } from "./objects/TransactionUpdate.js";
import type WithdrawalMode from "./objects/WithdrawalMode.js";
import type WithdrawalRequest from "./objects/WithdrawalRequest.js";
import { WithdrawalRequestFromJson } from "./objects/WithdrawalRequest.js";
import { CreateUmaInvoice } from "./graphql/CreateUmaInvoice.js";
import { PayUmaInvoice } from "./graphql/PayUmaInvoice.js";

const sdkVersion = packageJson.version;

Expand Down Expand Up @@ -393,20 +395,26 @@ class LightsparkClient {
* @param type The type of invoice to create. Defaults to a normal payment invoice, but you can pass InvoiceType.AMP
* to create an [AMP invoice](https://docs.lightning.engineering/lightning-network-tools/lnd/amp), which can be
* paid multiple times.
* @param expirySecs The number of seconds until the invoice expires. Defaults to 86400 (1 day).
* @returns An encoded payment request for the invoice, or undefined if the invoice could not be created.
*/
public async createInvoice(
nodeId: string,
amountMsats: number,
memo: string,
type: InvoiceType | undefined = undefined,
expirySecs: number | undefined = undefined,
): Promise<string | undefined> {
const response = await this.requester.makeRawRequest(CreateInvoice, {
const variables = {
node_id: nodeId,
amount_msats: amountMsats,
memo,
type,
});
};
if (expirySecs !== undefined) {
variables["expiry_secs"] = expirySecs;
}
const response = await this.requester.makeRawRequest(CreateInvoice, variables);
return response.create_invoice?.invoice.data?.encoded_payment_request;
}

Expand All @@ -422,25 +430,65 @@ class LightsparkClient {
* @param metadata The LNURL metadata payload field in the initial payreq response. This wil be hashed and present in the
* h-tag (SHA256 purpose of payment) of the resulting Bolt 11 invoice. See
* [this spec](https://github.com/lnurl/luds/blob/luds/06.md#pay-to-static-qrnfclink) for details.
* @param expirySecs The number of seconds until the invoice expires. Defaults to 86400 (1 day).
* @returns An Invoice object representing the generated invoice.
*/
public async createLnurlInvoice(
nodeId: string,
amountMsats: number,
metadata: string,
expirySecs: number | undefined = undefined,
): Promise<Invoice | undefined> {
const response = await this.requester.makeRawRequest(CreateLnurlInvoice, {
const variables = {
node_id: nodeId,
amount_msats: amountMsats,
metadata_hash: createHash("sha256").update(metadata).digest("hex"),
});
};
if (expirySecs !== undefined) {
variables["expiry_secs"] = expirySecs;
}
const response = await this.requester.makeRawRequest(CreateLnurlInvoice, variables);
const invoiceJson = response.create_lnurl_invoice?.invoice;
if (!invoiceJson) {
return undefined;
}
return InvoiceFromJson(invoiceJson);
}

/**
* Creates a new invoice for the UMA protocol. The metadata is hashed and included in the invoice.
* This API generates a Lightning Invoice (follows the Bolt 11 specification) to request a payment
* from another Lightning Node. This should only be used for generating invoices for UMA, with `createInvoice`
* preferred in the general case.
*
* @param nodeId The node ID for which to create an invoice.
* @param amountMsats The amount of the invoice in msats. You can create a zero-amount invoice to accept any payment amount.
* @param metadata The LNURL metadata payload field in the initial payreq response. This wil be hashed and present in the
* h-tag (SHA256 purpose of payment) of the resulting Bolt 11 invoice. See
* [this spec](https://github.com/lnurl/luds/blob/luds/06.md#pay-to-static-qrnfclink) for details.
* @param expirySecs The number of seconds until the invoice expires. Defaults to 3600 (1 hour).
* @returns An Invoice object representing the generated invoice.
*/
public async createUmaInvoice(
nodeId: string,
amountMsats: number,
metadata: string,
expirySecs: number | undefined = undefined,
): Promise<Invoice | undefined> {
const variables = {
node_id: nodeId,
amount_msats: amountMsats,
metadata_hash: createHash("sha256").update(metadata).digest("hex"),
expiry_secs: (expirySecs !== undefined) ? expirySecs : 3600,
};
const response = await this.requester.makeRawRequest(CreateUmaInvoice, variables);
const invoiceJson = response.create_uma_invoice?.invoice;
if (!invoiceJson) {
return undefined;
}
return InvoiceFromJson(invoiceJson);
}

/**
* Decodes an encoded lightning invoice string.
*
Expand Down Expand Up @@ -650,6 +698,58 @@ class LightsparkClient {
);
}

/**
* sends an UMA payment to a node on the Lightning Network, based on the invoice
* (as defined by the BOLT11 specification) that you provide.
* This should only be used for paying UMA invoices, with `payInvoice` preferred in the general case.
*
* @param payerNodeId The ID of the node that will pay the invoice.
* @param encodedInvoice The encoded invoice to pay.
* @param maximumFeesMsats Maximum fees (in msats) to pay for the payment. This parameter is required.
* As guidance, a maximum fee of 16 basis points should make almost all transactions succeed. For example,
* for a transaction between 10k sats and 100k sats, this would mean a fee limit of 16 to 160 sats.
* @param timeoutSecs A timeout for the payment in seconds. Defaults to 60 seconds.
* @param amountMsats The amount to pay in msats for a zero-amount invoice. Defaults to the full amount of the
* invoice. NOTE: This parameter can only be passed for a zero-amount invoice. Otherwise, the call will fail.
* @returns An `OutgoingPayment` object if the payment was successful, or undefined if the payment failed.
*/
public async payUmaInvoice(
payerNodeId: string,
encodedInvoice: string,
maximumFeesMsats: number,
timeoutSecs: number = 60,
amountMsats: number | undefined = undefined,
): Promise<OutgoingPayment | undefined> {
if (!this.nodeKeyCache.hasKey(payerNodeId)) {
throw new LightsparkSigningException("Paying node is not unlocked");
}
const variables: Record<string, string | number> = {
node_id: payerNodeId,
encoded_invoice: encodedInvoice,
timeout_secs: timeoutSecs,
maximum_fees_msats: maximumFeesMsats,
};
if (amountMsats !== undefined) {
variables.amount_msats = amountMsats;
}
const response = await this.requester.makeRawRequest(
PayUmaInvoice,
variables,
payerNodeId,
);
if (response.pay_invoice?.payment.outgoing_payment_failure_message) {
throw new LightsparkException(
"PaymentError",
response.pay_invoice?.payment.outgoing_payment_failure_message
.rich_text_text,
);
}
return (
response.pay_uma_invoice &&
OutgoingPaymentFromJson(response.pay_invoice.payment)
);
}

/**
* Sends a payment directly to a node on the Lightning Network through the public key of the node without an invoice.
*
Expand Down
5 changes: 3 additions & 2 deletions packages/lightspark-sdk/src/graphql/CreateInvoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ export const CreateInvoice = `
$amount_msats: Long!
$memo: String
$type: InvoiceType = null
) {
create_invoice(input: { node_id: $node_id, amount_msats: $amount_msats, memo: $memo, invoice_type: $type }) {
$expiry_secs: Int = null
) {
create_invoice(input: { node_id: $node_id, amount_msats: $amount_msats, memo: $memo, invoice_type: $type, expiry_secs: $expiry_secs }) {
invoice {
data {
encoded_payment_request
Expand Down
2 changes: 2 additions & 0 deletions packages/lightspark-sdk/src/graphql/CreateLnurlInvoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ mutation CreateLnurlInvoice(
$node_id: ID!
$amount_msats: Long!
$metadata_hash: String!
$expiry_secs: Int = null
) {
create_lnurl_invoice(input: {
node_id: $node_id
amount_msats: $amount_msats
metadata_hash: $metadata_hash
expiry_secs: $expiry_secs
}) {
invoice {
...InvoiceFragment
Expand Down
23 changes: 23 additions & 0 deletions packages/lightspark-sdk/src/graphql/CreateUmaInvoice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved
import { FRAGMENT as InvoiceFragment } from "../objects/Invoice.js";

export const CreateUmaInvoice = `
mutation CreateUmaInvoice(
$node_id: ID!
$amount_msats: Long!
$metadata_hash: String!
$expiry_secs: Int = null
) {
create_uma_invoice(input: {
node_id: $node_id
amount_msats: $amount_msats
metadata_hash: $metadata_hash
expiry_secs: $expiry_secs
}) {
invoice {
...InvoiceFragment
}
}
}
${InvoiceFragment}
`;
29 changes: 29 additions & 0 deletions packages/lightspark-sdk/src/graphql/PayUmaInvoice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright ©, 2023-present, Lightspark Group, Inc. - All Rights Reserved

import { FRAGMENT as OutgoingPaymentFragment } from "../objects/OutgoingPayment.js";

export const PayUmaInvoice = `
mutation PayUmaInvoice(
$node_id: ID!
$encoded_invoice: String!
$timeout_secs: Int!
$maximum_fees_msats: Long!
$amount_msats: Long
) {
pay_uma_invoice(
input: {
node_id: $node_id
encoded_invoice: $encoded_invoice
timeout_secs: $timeout_secs
maximum_fees_msats: $maximum_fees_msats
amount_msats: $amount_msats
}
) {
payment {
...OutgoingPaymentFragment
}
}
}
${OutgoingPaymentFragment}
`;

0 comments on commit 25f44d2

Please sign in to comment.