Skip to content

Commit

Permalink
Merge pull request #38 from lightsparkdev/feat/idempotency
Browse files Browse the repository at this point in the history
Add idempotency keys where needed in Client and queries
  • Loading branch information
jklein24 authored May 14, 2024
2 parents 6ccee4c + adaeae9 commit 01d4538
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 7 deletions.
46 changes: 39 additions & 7 deletions lightspark/lightspark_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
from lightspark.scripts.lightning_fee_estimate_for_node import (
LIGHTNING_FEE_ESTIMATE_FOR_NODE_QUERY,
)
from lightspark.scripts.outgoing_payment_for_idempotency_key import (
OUTGOING_PAYMENT_FOR_IDEMPOTENCY_KEY_QUERY,
)
from lightspark.scripts.outgoing_payments_for_invoice import (
OUTGOING_PAYMENTS_FOR_INVOICE_QUERY,
)
Expand Down Expand Up @@ -497,6 +500,7 @@ def pay_invoice(
timeout_secs: int,
maximum_fees_msats: int,
amount_msats: Optional[int] = None,
idempotency_key: Optional[str] = None,
) -> OutgoingPayment:
variables = {
"node_id": node_id,
Expand All @@ -506,6 +510,8 @@ def pay_invoice(
}
if amount_msats is not None:
variables["amount_msats"] = amount_msats
if idempotency_key is not None:
variables["idempotency_key"] = idempotency_key
json = self._requester.execute_graphql(
PAY_INVOICE_MUTATION,
variables,
Expand All @@ -522,6 +528,7 @@ def pay_uma_invoice(
timeout_secs: int,
maximum_fees_msats: int,
amount_msats: Optional[int] = None,
idempotency_key: Optional[str] = None,
) -> OutgoingPayment:
variables = {
"node_id": node_id,
Expand All @@ -531,6 +538,8 @@ def pay_uma_invoice(
}
if amount_msats is not None:
variables["amount_msats"] = amount_msats
if idempotency_key is not None:
variables["idempotency_key"] = idempotency_key
json = self._requester.execute_graphql(
PAY_UMA_INVOICE_MUTATION,
variables,
Expand Down Expand Up @@ -615,21 +624,24 @@ def request_withdrawal(
amount_sats: int,
bitcoin_address: str,
withdrawal_mode: WithdrawalMode,
idempotency_key: Optional[str] = None,
) -> WithdrawalRequest:
"""Withdraws funds from the account and sends it to the requested bitcoin address.
Depending on the chosen mode, it will first take the funds from the wallet, and if applicable, close channels appropriately to recover enough funds and reopen channels with the remaining funds.
The process is asynchronous and may take up to a few minutes. You can check the progress by polling the `WithdrawalRequest` that is created, or by subscribing to a webhook.
"""

variables = {
"node_id": node_id,
"amount_sats": amount_sats,
"bitcoin_address": bitcoin_address,
"withdrawal_mode": withdrawal_mode,
}
if idempotency_key is not None:
variables["idempotency_key"] = idempotency_key
json = self._requester.execute_graphql(
REQUEST_WITHDRAWAL_MUTATION,
{
"node_id": node_id,
"amount_sats": amount_sats,
"bitcoin_address": bitcoin_address,
"withdrawal_mode": withdrawal_mode,
},
variables,
self.get_signing_key(node_id),
)
return WithdrawalRequest_from_json(
Expand Down Expand Up @@ -723,6 +735,26 @@ def outgoing_payments_for_payment_hash(
for payment in json["outgoing_payments_for_payment_hash"]["payments"]
]

def outgoing_payment_for_idempotency_key(
self,
idempotency_key: str,
) -> Optional[OutgoingPayment]:
"""
Fetches the outgoing payment (if any) which have been made for a given idempotency key.
"""

json = self._requester.execute_graphql(
OUTGOING_PAYMENT_FOR_IDEMPOTENCY_KEY_QUERY,
{"idempotency_key": idempotency_key},
)
if "outgoing_payment_for_idempotency_key" not in json:
return None
if "payment" not in json["outgoing_payment_for_idempotency_key"]:
return None
return OutgoingPayment_from_json(
self._requester, json["outgoing_payment_for_idempotency_key"]["payment"]
)

def incoming_payments_for_invoice(
self,
invoice_id: str,
Expand Down
19 changes: 19 additions & 0 deletions lightspark/scripts/outgoing_payment_for_idempotency_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright ©, 2022-present, Lightspark Group, Inc. - All Rights Reserved

from lightspark.objects.OutgoingPayment import FRAGMENT as OutgoingPaymentFragment

OUTGOING_PAYMENT_FOR_IDEMPOTENCY_KEY_QUERY = f"""
query OutgoingPaymentForIdempotencyKey(
$idempotency_key: String!
) {{
outgoing_payment_for_idempotency_key(input: {{
idempotency_key: $idempotency_key
}}) {{
payment {{
...OutgoingPaymentFragment
}}
}}
}}
{OutgoingPaymentFragment}
"""
2 changes: 2 additions & 0 deletions lightspark/scripts/pay_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
$timeout_secs: Int!
$maximum_fees_msats: Long!
$amount_msats: Long
$idempotency_key: String
) {{
pay_invoice(input: {{
node_id: $node_id
encoded_invoice: $encoded_invoice
timeout_secs: $timeout_secs
maximum_fees_msats: $maximum_fees_msats
amount_msats: $amount_msats
idempotency_key: $idempotency_key
}}) {{
payment {{
...OutgoingPaymentFragment
Expand Down
2 changes: 2 additions & 0 deletions lightspark/scripts/pay_uma_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
$timeout_secs: Int!
$maximum_fees_msats: Long!
$amount_msats: Long
$idempotency_key: String
) {{
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
idempotency_key: $idempotency_key
}}) {{
payment {{
...OutgoingPaymentFragment
Expand Down
2 changes: 2 additions & 0 deletions lightspark/scripts/request_withdrawal.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
$amount_sats: Long!
$bitcoin_address: String!
$withdrawal_mode: WithdrawalMode!
$idempotency_key: String
) {{
request_withdrawal(input: {{
node_id: $node_id
amount_sats: $amount_sats
bitcoin_address: $bitcoin_address
withdrawal_mode: $withdrawal_mode
idempotency_key: $idempotency_key
}}) {{
request {{
...WithdrawalRequestFragment
Expand Down

0 comments on commit 01d4538

Please sign in to comment.