Skip to content

Commit 4b29767

Browse files
committed
Add the UMA invites functions.
1 parent 92c437e commit 4b29767

7 files changed

Lines changed: 202 additions & 2 deletions

File tree

lightspark/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,24 @@
2626
from lightspark.objects.ChannelToTransactionsConnection import (
2727
ChannelToTransactionsConnection,
2828
)
29+
from lightspark.objects.ClaimUmaInvitationInput import ClaimUmaInvitationInput
30+
from lightspark.objects.ClaimUmaInvitationOutput import ClaimUmaInvitationOutput
31+
from lightspark.objects.ClaimUmaInvitationWithIncentivesInput import (
32+
ClaimUmaInvitationWithIncentivesInput,
33+
)
34+
from lightspark.objects.ClaimUmaInvitationWithIncentivesOutput import (
35+
ClaimUmaInvitationWithIncentivesOutput,
36+
)
2937
from lightspark.objects.ComplianceProvider import ComplianceProvider
3038
from lightspark.objects.Connection import Connection
3139
from lightspark.objects.CreateApiTokenInput import CreateApiTokenInput
3240
from lightspark.objects.CreateApiTokenOutput import CreateApiTokenOutput
41+
from lightspark.objects.CreateInvitationWithIncentivesInput import (
42+
CreateInvitationWithIncentivesInput,
43+
)
44+
from lightspark.objects.CreateInvitationWithIncentivesOutput import (
45+
CreateInvitationWithIncentivesOutput,
46+
)
3347
from lightspark.objects.CreateInvoiceInput import CreateInvoiceInput
3448
from lightspark.objects.CreateInvoiceOutput import CreateInvoiceOutput
3549
from lightspark.objects.CreateLnurlInvoiceInput import CreateLnurlInvoiceInput
@@ -41,6 +55,8 @@
4155
from lightspark.objects.CreateTestModeInvoiceOutput import CreateTestModeInvoiceOutput
4256
from lightspark.objects.CreateTestModePaymentInput import CreateTestModePaymentInput
4357
from lightspark.objects.CreateTestModePaymentoutput import CreateTestModePaymentoutput
58+
from lightspark.objects.CreateUmaInvitationInput import CreateUmaInvitationInput
59+
from lightspark.objects.CreateUmaInvitationOutput import CreateUmaInvitationOutput
4460
from lightspark.objects.CreateUmaInvoiceInput import CreateUmaInvoiceInput
4561
from lightspark.objects.CurrencyAmount import CurrencyAmount
4662
from lightspark.objects.CurrencyUnit import CurrencyUnit
@@ -57,6 +73,10 @@
5773
from lightspark.objects.Hop import Hop
5874
from lightspark.objects.HtlcAttemptFailureCode import HtlcAttemptFailureCode
5975
from lightspark.objects.IdAndSignature import IdAndSignature
76+
from lightspark.objects.IncentivesIneligibilityReason import (
77+
IncentivesIneligibilityReason,
78+
)
79+
from lightspark.objects.IncentivesStatus import IncentivesStatus
6080
from lightspark.objects.IncomingPayment import IncomingPayment
6181
from lightspark.objects.IncomingPaymentAttempt import IncomingPaymentAttempt
6282
from lightspark.objects.IncomingPaymentAttemptStatus import IncomingPaymentAttemptStatus
@@ -115,6 +135,7 @@
115135
from lightspark.objects.PayUmaInvoiceInput import PayUmaInvoiceInput
116136
from lightspark.objects.Permission import Permission
117137
from lightspark.objects.PostTransactionData import PostTransactionData
138+
from lightspark.objects.RegionCode import RegionCode
118139
from lightspark.objects.RegisterPaymentInput import RegisterPaymentInput
119140
from lightspark.objects.RegisterPaymentOutput import RegisterPaymentOutput
120141
from lightspark.objects.ReleaseChannelPerCommitmentSecretInput import (
@@ -152,6 +173,7 @@
152173
from lightspark.objects.TransactionFailures import TransactionFailures
153174
from lightspark.objects.TransactionStatus import TransactionStatus
154175
from lightspark.objects.TransactionType import TransactionType
176+
from lightspark.objects.UmaInvitation import UmaInvitation
155177
from lightspark.objects.UpdateChannelPerCommitmentPointInput import (
156178
UpdateChannelPerCommitmentPointInput,
157179
)

lightspark/lightspark_client.py

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright ©, 2022-present, Lightspark Group, Inc. - All Rights Reserved
22

33
import logging
4+
import re
45
from dataclasses import dataclass
56
from datetime import datetime, timedelta, timezone
67
from hashlib import sha256
@@ -45,15 +46,22 @@
4546
from lightspark.objects.PaymentDirection import PaymentDirection
4647
from lightspark.objects.PaymentRequestData import PaymentRequestData
4748
from lightspark.objects.Permission import Permission
49+
from lightspark.objects.RegionCode import RegionCode
4850
from lightspark.objects.RiskRating import RiskRating
4951
from lightspark.objects.TransactionStatus import TransactionStatus
52+
from lightspark.objects.UmaInvitation import UmaInvitation
53+
from lightspark.objects.UmaInvitation import from_json as UmaInvitation_from_json
5054
from lightspark.objects.WithdrawalMode import WithdrawalMode
5155
from lightspark.objects.WithdrawalRequest import WithdrawalRequest
5256
from lightspark.objects.WithdrawalRequest import (
5357
from_json as WithdrawalRequest_from_json,
5458
)
5559
from lightspark.requests.requester import Requester
5660
from lightspark.scripts.bitcoin_fee_estimate import BITCOIN_FEE_ESTIMATE_QUERY
61+
from lightspark.scripts.claim_uma_invitation import (
62+
CLAIM_UMA_INVITATION_MUTATION,
63+
CLAIM_UMA_INVITATION_WITH_INCENTIVES_MUTATION,
64+
)
5765
from lightspark.scripts.create_api_token import CREATE_API_TOKEN_MUTATION
5866
from lightspark.scripts.create_invoice import CREATE_INVOICE_MUTATION
5967
from lightspark.scripts.create_lnurl_invoice import CREATE_LNURL_INVOICE_MUTATION
@@ -64,10 +72,15 @@
6472
from lightspark.scripts.create_test_mode_payment import (
6573
CREATE_TEST_MODE_PAYMENT_MUTATION,
6674
)
75+
from lightspark.scripts.create_uma_invitation import (
76+
CREATE_UMA_INVITATION_MUTATION,
77+
CREATE_UMA_INVITATION_WITH_INCENTIVES_MUTATION,
78+
)
6779
from lightspark.scripts.create_uma_invoice import CREATE_UMA_INVOICE_MUTATION
6880
from lightspark.scripts.current_account import CURRENT_ACCOUNT_QUERY
6981
from lightspark.scripts.decoded_payment_request import DECODED_PAYMENT_REQUEST_QUERY
7082
from lightspark.scripts.delete_api_token import DELETE_API_TOKEN_MUTATION
83+
from lightspark.scripts.fetch_uma_invitation import FETCH_UMA_INVITATION_QUERY
7184
from lightspark.scripts.fund_node import FUND_NODE_MUTATION
7285
from lightspark.scripts.lightning_fee_estimate_for_invoice import (
7386
LIGHTNING_FEE_ESTIMATE_FOR_INVOICE_QUERY,
@@ -87,7 +100,7 @@
87100
from lightspark.scripts.send_payment import SEND_PAYMENT_MUTATION
88101
from lightspark.utils.crypto import decrypt_private_key
89102
from lightspark.utils.enums import parse_enum
90-
from lightspark.utils.signing_key import SigningKey, Secp256k1SigningKey, RSASigningKey
103+
from lightspark.utils.signing_key import RSASigningKey, Secp256k1SigningKey, SigningKey
91104

92105
logger = logging.getLogger("lightspark")
93106

@@ -653,3 +666,135 @@ def outgoing_payments_for_invoice(
653666
OutgoingPayment_from_json(self._requester, payment)
654667
for payment in json["outgoing_payments_for_invoice"]["payments"]
655668
]
669+
670+
def create_uma_invitation(
671+
self,
672+
inviter_uma: str,
673+
) -> UmaInvitation:
674+
"""
675+
Creates a new UMA invitation. If you are part of the incentive program, you should use the
676+
`create_uma_invitation_with_incentives` method instead.
677+
678+
Args:
679+
inviter_uma: The UMA of the inviter.
680+
"""
681+
json = self._requester.execute_graphql(
682+
CREATE_UMA_INVOICE_MUTATION,
683+
{
684+
"inviter_uma": inviter_uma,
685+
},
686+
)
687+
return UmaInvitation_from_json(json["create_uma_invitation"]["invitation"])
688+
689+
def create_uma_invitation_with_incentives(
690+
self,
691+
inviter_uma: str,
692+
inviter_phone_number_e164: str,
693+
inviter_region: RegionCode,
694+
) -> UmaInvitation:
695+
"""
696+
Creates a new UMA invitation with incentives. If you are not part of the incentive program, you should use the
697+
`create_uma_invitation` method instead.
698+
699+
Args:
700+
inviter_uma: The UMA of the inviter.
701+
inviter_phone_number_e164: The E.164 formatted phone number of the inviter.
702+
inviter_region: The region of the inviter.
703+
"""
704+
json = self._requester.execute_graphql(
705+
CREATE_UMA_INVITATION_WITH_INCENTIVES_MUTATION,
706+
{
707+
"inviter_uma": inviter_uma,
708+
"inviter_phone_hash": self._hash_phone_number(
709+
inviter_phone_number_e164
710+
),
711+
"inviter_region": inviter_region.name,
712+
},
713+
)
714+
return UmaInvitation_from_json(
715+
json["create_uma_invitation_with_incentives"]["invitation"]
716+
)
717+
718+
def claim_uma_invitation(
719+
self,
720+
invitation_code: str,
721+
invitee_uma: str,
722+
) -> None:
723+
"""
724+
Claims a UMA invitation. If you are part of the incentive program, you should use the
725+
`claim_uma_invitation_with_incentives` method instead.
726+
727+
Args:
728+
invitation_code: The invitation code of the invitation to claim.
729+
invitee_uma: The new UMA of the invitee.
730+
"""
731+
self._requester.execute_graphql(
732+
CLAIM_UMA_INVITATION_MUTATION,
733+
{
734+
"invitation_code": invitation_code,
735+
"invitee_uma": invitee_uma,
736+
},
737+
)
738+
739+
def claim_uma_invitation_with_incentives(
740+
self,
741+
invitation_code: str,
742+
invitee_uma: str,
743+
invitee_phone_number_e164: str,
744+
invitee_region: RegionCode,
745+
) -> None:
746+
"""
747+
Claims a UMA invitation with incentives. If you are not part of the incentive program, you should use the
748+
`claim_uma_invitation` method instead.
749+
750+
Args:
751+
invitation_code: The invitation code of the invitation to claim.
752+
invitee_uma: The new UMA of the invitee.
753+
invitee_phone_number_e164: The E.164 formatted phone number of the invitee.
754+
invitee_region: The region of the invitee.
755+
"""
756+
self._requester.execute_graphql(
757+
CLAIM_UMA_INVITATION_WITH_INCENTIVES_MUTATION,
758+
{
759+
"invitation_code": invitation_code,
760+
"invitee_uma": invitee_uma,
761+
"invitee_phone_hash": self._hash_phone_number(
762+
invitee_phone_number_e164
763+
),
764+
"invitee_region": invitee_region,
765+
},
766+
)
767+
768+
def fetch_uma_invitation(
769+
self,
770+
invitation_code: str,
771+
) -> Optional[UmaInvitation]:
772+
"""
773+
Fetches a UMA invitation by its invitation code.
774+
775+
Args:
776+
invitation_code: The invitation code of the invitation to fetch.
777+
"""
778+
json = self._requester.execute_graphql(
779+
FETCH_UMA_INVITATION_QUERY,
780+
{
781+
"invitation_code": invitation_code,
782+
},
783+
)
784+
785+
return (
786+
UmaInvitation_from_json(json["uma_invitation_by_code"])
787+
if json["uma_invitation_by_code"]
788+
else None
789+
)
790+
791+
def _hash_phone_number(self, phone_number_e164_format: str) -> str:
792+
match = E614_REGEX.search(phone_number_e164_format)
793+
if not match:
794+
raise LightsparkException(
795+
"InvalidPhoneNumber", "The phone number must follow the E.164 format."
796+
)
797+
return sha256(phone_number_e164_format.encode()).hexdigest()
798+
799+
800+
E614_REGEX = re.compile("^\+?[1-9]\d{1,14}$")

lightspark/objects/Entity.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,7 @@ class Entity:
12421242
outgoing_payment_attempt_status: status
12431243
outgoing_payment_attempt_failure_code: failure_code
12441244
outgoing_payment_attempt_failure_source_index: failure_source_index
1245+
outgoing_payment_attempt_attempted_at: attempted_at
12451246
outgoing_payment_attempt_resolved_at: resolved_at
12461247
outgoing_payment_attempt_amount: amount {
12471248
__typename
@@ -1366,6 +1367,18 @@ class Entity:
13661367
id
13671368
}
13681369
}
1370+
... on UmaInvitation {
1371+
__typename
1372+
uma_invitation_id: id
1373+
uma_invitation_created_at: created_at
1374+
uma_invitation_updated_at: updated_at
1375+
uma_invitation_code: code
1376+
uma_invitation_url: url
1377+
uma_invitation_inviter_uma: inviter_uma
1378+
uma_invitation_invitee_uma: invitee_uma
1379+
uma_invitation_incentives_status: incentives_status
1380+
uma_invitation_incentives_ineligibility_reason: incentives_ineligibility_reason
1381+
}
13691382
... on Wallet {
13701383
__typename
13711384
wallet_id: id

lightspark/objects/OutgoingPayment.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def get_attempts(
106106
outgoing_payment_attempt_status: status
107107
outgoing_payment_attempt_failure_code: failure_code
108108
outgoing_payment_attempt_failure_source_index: failure_source_index
109+
outgoing_payment_attempt_attempted_at: attempted_at
109110
outgoing_payment_attempt_resolved_at: resolved_at
110111
outgoing_payment_attempt_amount: amount {
111112
__typename

lightspark/objects/OutgoingPaymentAttempt.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class OutgoingPaymentAttempt(Entity):
3434
"""The unique identifier of this entity across all Lightspark systems. Should be treated as an opaque string."""
3535

3636
created_at: datetime
37-
"""The date and time when the attempt was initiated."""
37+
"""The date and time when the entity was first created."""
3838

3939
updated_at: datetime
4040
"""The date and time when the entity was last updated."""
@@ -48,6 +48,9 @@ class OutgoingPaymentAttempt(Entity):
4848
failure_source_index: Optional[int]
4949
"""If the payment attempt failed, then this contains the index of the hop at which the problem occurred."""
5050

51+
attempted_at: datetime
52+
"""The date and time when the attempt was initiated."""
53+
5154
resolved_at: Optional[datetime]
5255
"""The time the outgoing payment attempt failed or succeeded."""
5356

@@ -133,6 +136,7 @@ def to_json(self) -> Mapping[str, Any]:
133136
if self.failure_code
134137
else None,
135138
"outgoing_payment_attempt_failure_source_index": self.failure_source_index,
139+
"outgoing_payment_attempt_attempted_at": self.attempted_at.isoformat(),
136140
"outgoing_payment_attempt_resolved_at": self.resolved_at.isoformat()
137141
if self.resolved_at
138142
else None,
@@ -158,6 +162,7 @@ def to_json(self) -> Mapping[str, Any]:
158162
outgoing_payment_attempt_status: status
159163
outgoing_payment_attempt_failure_code: failure_code
160164
outgoing_payment_attempt_failure_source_index: failure_source_index
165+
outgoing_payment_attempt_attempted_at: attempted_at
161166
outgoing_payment_attempt_resolved_at: resolved_at
162167
outgoing_payment_attempt_amount: amount {
163168
__typename
@@ -243,6 +248,9 @@ def from_json(requester: Requester, obj: Mapping[str, Any]) -> OutgoingPaymentAt
243248
HtlcAttemptFailureCode, obj["outgoing_payment_attempt_failure_code"]
244249
),
245250
failure_source_index=obj["outgoing_payment_attempt_failure_source_index"],
251+
attempted_at=datetime.fromisoformat(
252+
obj["outgoing_payment_attempt_attempted_at"]
253+
),
246254
resolved_at=datetime.fromisoformat(obj["outgoing_payment_attempt_resolved_at"])
247255
if obj["outgoing_payment_attempt_resolved_at"]
248256
else None,

lightspark/objects/WebhookEventType.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ class WebhookEventType(Enum):
99
___FUTURE_VALUE___ = "___FUTURE_VALUE___"
1010
"""This is an enum value that represents future values that could be added in the future. Clients should support unknown values as more of them could be added without notice."""
1111
PAYMENT_FINISHED = "PAYMENT_FINISHED"
12+
FORCE_CLOSURE = "FORCE_CLOSURE"
1213
WITHDRAWAL_FINISHED = "WITHDRAWAL_FINISHED"
1314
FUNDS_RECEIVED = "FUNDS_RECEIVED"
1415
NODE_STATUS = "NODE_STATUS"
16+
UMA_INVITATION_CLAIMED = "UMA_INVITATION_CLAIMED"
1517
WALLET_STATUS = "WALLET_STATUS"
1618
WALLET_OUTGOING_PAYMENT_FINISHED = "WALLET_OUTGOING_PAYMENT_FINISHED"
1719
WALLET_INCOMING_PAYMENT_FINISHED = "WALLET_INCOMING_PAYMENT_FINISHED"

lightspark/objects/all_entities.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@
117117
from lightspark.objects.Transaction import FRAGMENT as TransactionFragment
118118
from lightspark.objects.Transaction import Transaction
119119
from lightspark.objects.Transaction import from_json as Transaction_from_json
120+
from lightspark.objects.UmaInvitation import FRAGMENT as UmaInvitationFragment
121+
from lightspark.objects.UmaInvitation import UmaInvitation
122+
from lightspark.objects.UmaInvitation import from_json as UmaInvitation_from_json
120123
from lightspark.objects.Wallet import FRAGMENT as WalletFragment
121124
from lightspark.objects.Wallet import Wallet
122125
from lightspark.objects.Wallet import from_json as Wallet_from_json
@@ -236,6 +239,10 @@
236239
Transaction: """ ... on Transaction {
237240
...TransactionFragment
238241
}
242+
""",
243+
UmaInvitation: """ ... on UmaInvitation {
244+
...UmaInvitationFragment
245+
}
239246
""",
240247
Wallet: """ ... on Wallet {
241248
...WalletFragment
@@ -277,6 +284,7 @@
277284
Signable: SignableFragment,
278285
SignablePayload: SignablePayloadFragment,
279286
Transaction: TransactionFragment,
287+
UmaInvitation: UmaInvitationFragment,
280288
Wallet: WalletFragment,
281289
Withdrawal: WithdrawalFragment,
282290
WithdrawalRequest: WithdrawalRequestFragment,
@@ -307,6 +315,7 @@
307315
Signable: Signable_from_json,
308316
SignablePayload: SignablePayload_from_json,
309317
Transaction: Transaction_from_json,
318+
UmaInvitation: UmaInvitation_from_json,
310319
Wallet: Wallet_from_json,
311320
Withdrawal: Withdrawal_from_json,
312321
WithdrawalRequest: WithdrawalRequest_from_json,

0 commit comments

Comments
 (0)