swig-developer-sdk 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swig_developer_sdk/__init__.py +180 -0
- swig_developer_sdk/client.py +36 -0
- swig_developer_sdk/common.py +104 -0
- swig_developer_sdk/core.py +162 -0
- swig_developer_sdk/evm.py +64 -0
- swig_developer_sdk/one_business.py +163 -0
- swig_developer_sdk/passkeys.py +122 -0
- swig_developer_sdk/paymaster.py +106 -0
- swig_developer_sdk/proxy.py +724 -0
- swig_developer_sdk/ramp.py +724 -0
- swig_developer_sdk/signing.py +461 -0
- swig_developer_sdk/transactions.py +277 -0
- swig_developer_sdk/wallets.py +1393 -0
- swig_developer_sdk-0.6.0.dist-info/METADATA +89 -0
- swig_developer_sdk-0.6.0.dist-info/RECORD +16 -0
- swig_developer_sdk-0.6.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,724 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping, Sequence
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Literal, TypeAlias
|
|
6
|
+
from urllib.parse import quote, urlencode
|
|
7
|
+
|
|
8
|
+
from .common import Network, require_network, to_proto_network
|
|
9
|
+
from .core import HttpClient
|
|
10
|
+
|
|
11
|
+
RampDirection: TypeAlias = Literal["onramp", "offramp", "transfer", "unspecified"]
|
|
12
|
+
ActiveRampDirection: TypeAlias = Literal["onramp", "offramp", "transfer"]
|
|
13
|
+
RampCustomerType: TypeAlias = Literal["individual", "business", "unspecified"]
|
|
14
|
+
RampTransactionType: TypeAlias = Literal[
|
|
15
|
+
"crypto-purchase",
|
|
16
|
+
"crypto-sell",
|
|
17
|
+
"crypto-purchase-swap",
|
|
18
|
+
"crypto-sell-swap",
|
|
19
|
+
"transfer",
|
|
20
|
+
"unspecified",
|
|
21
|
+
]
|
|
22
|
+
RampTransactionStatus: TypeAlias = Literal[
|
|
23
|
+
"created",
|
|
24
|
+
"pending",
|
|
25
|
+
"settling",
|
|
26
|
+
"settled",
|
|
27
|
+
"failed",
|
|
28
|
+
"declined",
|
|
29
|
+
"cancelled",
|
|
30
|
+
"refunded",
|
|
31
|
+
"unspecified",
|
|
32
|
+
]
|
|
33
|
+
ActiveRampTransactionStatus: TypeAlias = Literal[
|
|
34
|
+
"created",
|
|
35
|
+
"pending",
|
|
36
|
+
"settling",
|
|
37
|
+
"settled",
|
|
38
|
+
"failed",
|
|
39
|
+
"declined",
|
|
40
|
+
"cancelled",
|
|
41
|
+
"refunded",
|
|
42
|
+
]
|
|
43
|
+
RampServiceProvider: TypeAlias = Literal["other", "unspecified"]
|
|
44
|
+
RampPaymentMethodType: TypeAlias = Literal[
|
|
45
|
+
"other",
|
|
46
|
+
"credit-debit-card",
|
|
47
|
+
"ach",
|
|
48
|
+
"bank-transfer",
|
|
49
|
+
"apple-pay",
|
|
50
|
+
"google-pay",
|
|
51
|
+
"pix",
|
|
52
|
+
"unspecified",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True, slots=True)
|
|
57
|
+
class RampCustomerContext:
|
|
58
|
+
customer_type: RampCustomerType
|
|
59
|
+
partner_application_id: str | None = None
|
|
60
|
+
swig_user_id: str | None = None
|
|
61
|
+
external_customer_id: str | None = None
|
|
62
|
+
external_business_id: str | None = None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True, slots=True)
|
|
66
|
+
class RampWalletContext:
|
|
67
|
+
wallet_id: str
|
|
68
|
+
wallet_address: str
|
|
69
|
+
network: Network
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True, slots=True)
|
|
73
|
+
class GetRampOptionsResult:
|
|
74
|
+
country_codes: tuple[str, ...]
|
|
75
|
+
fiat_currency_codes: tuple[str, ...]
|
|
76
|
+
payment_method_types: tuple[RampPaymentMethodType, ...]
|
|
77
|
+
crypto_currency_codes: tuple[str, ...]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True, slots=True)
|
|
81
|
+
class QuoteRampArgs:
|
|
82
|
+
customer: RampCustomerContext
|
|
83
|
+
wallet: RampWalletContext
|
|
84
|
+
direction: ActiveRampDirection
|
|
85
|
+
source_amount: str
|
|
86
|
+
source_currency_code: str
|
|
87
|
+
destination_currency_code: str
|
|
88
|
+
country_code: str
|
|
89
|
+
subdivision: str | None = None
|
|
90
|
+
payment_method_type: RampPaymentMethodType | None = None
|
|
91
|
+
service_providers: tuple[RampServiceProvider, ...] = ()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True, slots=True)
|
|
95
|
+
class RampQuote:
|
|
96
|
+
quote_id: str
|
|
97
|
+
direction: RampDirection
|
|
98
|
+
service_provider: RampServiceProvider
|
|
99
|
+
payment_method_type: RampPaymentMethodType
|
|
100
|
+
source_amount: str
|
|
101
|
+
source_currency_code: str
|
|
102
|
+
destination_amount: str
|
|
103
|
+
destination_currency_code: str
|
|
104
|
+
exchange_rate: str
|
|
105
|
+
total_fee: str
|
|
106
|
+
network_fee: str
|
|
107
|
+
transaction_fee: str
|
|
108
|
+
partner_fee: str
|
|
109
|
+
ramp_score: str | None = None
|
|
110
|
+
low_kyc: bool | None = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass(frozen=True, slots=True)
|
|
114
|
+
class QuoteRampResult:
|
|
115
|
+
quotes: tuple[RampQuote, ...]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclass(frozen=True, slots=True)
|
|
119
|
+
class CreateRampSessionArgs:
|
|
120
|
+
customer: RampCustomerContext
|
|
121
|
+
wallet: RampWalletContext
|
|
122
|
+
direction: ActiveRampDirection
|
|
123
|
+
selected_quote_id: str
|
|
124
|
+
source_amount: str
|
|
125
|
+
source_currency_code: str
|
|
126
|
+
destination_currency_code: str
|
|
127
|
+
country_code: str
|
|
128
|
+
service_provider: RampServiceProvider
|
|
129
|
+
subdivision: str | None = None
|
|
130
|
+
payment_method_type: RampPaymentMethodType | None = None
|
|
131
|
+
redirect_url: str | None = None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass(frozen=True, slots=True)
|
|
135
|
+
class CreateRampSessionResult:
|
|
136
|
+
local_session_id: str
|
|
137
|
+
meld_session_id: str
|
|
138
|
+
external_customer_id: str
|
|
139
|
+
external_session_id: str
|
|
140
|
+
launch_url: str
|
|
141
|
+
fallback_launch_url: str | None = None
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True, slots=True)
|
|
145
|
+
class RampTransaction:
|
|
146
|
+
transaction_id: str
|
|
147
|
+
wallet_id: str
|
|
148
|
+
direction: RampDirection
|
|
149
|
+
transaction_type: RampTransactionType
|
|
150
|
+
status: RampTransactionStatus
|
|
151
|
+
service_provider: RampServiceProvider
|
|
152
|
+
source_amount: str
|
|
153
|
+
source_currency_code: str
|
|
154
|
+
destination_currency_code: str
|
|
155
|
+
created_at: str
|
|
156
|
+
updated_at: str
|
|
157
|
+
meld_transaction_id: str | None = None
|
|
158
|
+
meld_session_id: str | None = None
|
|
159
|
+
payment_method_type: RampPaymentMethodType | None = None
|
|
160
|
+
destination_amount: str | None = None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass(frozen=True, slots=True)
|
|
164
|
+
class GetRampTransactionResult:
|
|
165
|
+
transaction: RampTransaction | None = None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@dataclass(frozen=True, slots=True)
|
|
169
|
+
class ListRampTransactionsResult:
|
|
170
|
+
transactions: tuple[RampTransaction, ...]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class _RampCustomerFactory:
|
|
174
|
+
def direct_swig_user(
|
|
175
|
+
self,
|
|
176
|
+
*,
|
|
177
|
+
swig_user_id: str,
|
|
178
|
+
partner_application_id: str | None = None,
|
|
179
|
+
) -> RampCustomerContext:
|
|
180
|
+
return RampCustomerContext(
|
|
181
|
+
swig_user_id=_non_empty(swig_user_id, "swig_user_id"),
|
|
182
|
+
partner_application_id=(
|
|
183
|
+
partner_application_id
|
|
184
|
+
if partner_application_id and partner_application_id.strip()
|
|
185
|
+
else None
|
|
186
|
+
),
|
|
187
|
+
customer_type="individual",
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def partner_customer(
|
|
191
|
+
self,
|
|
192
|
+
*,
|
|
193
|
+
partner_application_id: str,
|
|
194
|
+
external_customer_id: str,
|
|
195
|
+
) -> RampCustomerContext:
|
|
196
|
+
return RampCustomerContext(
|
|
197
|
+
partner_application_id=_non_empty(
|
|
198
|
+
partner_application_id, "partner_application_id"
|
|
199
|
+
),
|
|
200
|
+
external_customer_id=_non_empty(
|
|
201
|
+
external_customer_id, "external_customer_id"
|
|
202
|
+
),
|
|
203
|
+
customer_type="individual",
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def partner_business(
|
|
207
|
+
self,
|
|
208
|
+
*,
|
|
209
|
+
partner_application_id: str,
|
|
210
|
+
external_business_id: str,
|
|
211
|
+
) -> RampCustomerContext:
|
|
212
|
+
return RampCustomerContext(
|
|
213
|
+
partner_application_id=_non_empty(
|
|
214
|
+
partner_application_id, "partner_application_id"
|
|
215
|
+
),
|
|
216
|
+
external_business_id=_non_empty(
|
|
217
|
+
external_business_id, "external_business_id"
|
|
218
|
+
),
|
|
219
|
+
customer_type="business",
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
ramp_customer = _RampCustomerFactory()
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class RampClient:
|
|
227
|
+
def __init__(
|
|
228
|
+
self,
|
|
229
|
+
http: HttpClient,
|
|
230
|
+
default_network: Network | None = None,
|
|
231
|
+
) -> None:
|
|
232
|
+
self._http = http
|
|
233
|
+
self._default_network = default_network
|
|
234
|
+
|
|
235
|
+
async def get_options(
|
|
236
|
+
self,
|
|
237
|
+
*,
|
|
238
|
+
partner_application_id: str | None = None,
|
|
239
|
+
country_code: str | None = None,
|
|
240
|
+
fiat_currency_code: str | None = None,
|
|
241
|
+
) -> GetRampOptionsResult:
|
|
242
|
+
path = _path_with_query(
|
|
243
|
+
"/wallet/api/ramp/options",
|
|
244
|
+
{
|
|
245
|
+
"partnerApplicationId": partner_application_id,
|
|
246
|
+
"countryCode": country_code,
|
|
247
|
+
"fiatCurrencyCode": fiat_currency_code,
|
|
248
|
+
},
|
|
249
|
+
)
|
|
250
|
+
return normalize_ramp_options(await self._http.get(path))
|
|
251
|
+
|
|
252
|
+
async def quote(self, args: QuoteRampArgs) -> QuoteRampResult:
|
|
253
|
+
return normalize_quote_ramp_result(
|
|
254
|
+
await self._http.post("/wallet/api/ramp/quote", _quote_request(args))
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
async def create_session(
|
|
258
|
+
self,
|
|
259
|
+
args: CreateRampSessionArgs,
|
|
260
|
+
) -> CreateRampSessionResult:
|
|
261
|
+
request = _quote_request(
|
|
262
|
+
QuoteRampArgs(
|
|
263
|
+
customer=args.customer,
|
|
264
|
+
wallet=args.wallet,
|
|
265
|
+
direction=args.direction,
|
|
266
|
+
source_amount=args.source_amount,
|
|
267
|
+
source_currency_code=args.source_currency_code,
|
|
268
|
+
destination_currency_code=args.destination_currency_code,
|
|
269
|
+
country_code=args.country_code,
|
|
270
|
+
subdivision=args.subdivision,
|
|
271
|
+
payment_method_type=args.payment_method_type,
|
|
272
|
+
)
|
|
273
|
+
)
|
|
274
|
+
request.update(
|
|
275
|
+
{
|
|
276
|
+
"selectedQuoteId": args.selected_quote_id,
|
|
277
|
+
"serviceProvider": _service_provider_to_wire(args.service_provider),
|
|
278
|
+
"redirectUrl": args.redirect_url,
|
|
279
|
+
}
|
|
280
|
+
)
|
|
281
|
+
return normalize_create_ramp_session_result(
|
|
282
|
+
await self._http.post("/wallet/api/ramp/sessions", request)
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
async def get_transaction(
|
|
286
|
+
self,
|
|
287
|
+
*,
|
|
288
|
+
transaction_id: str,
|
|
289
|
+
) -> GetRampTransactionResult:
|
|
290
|
+
response = await self._http.get(
|
|
291
|
+
f"/wallet/api/ramp/transactions/{quote(transaction_id, safe='')}"
|
|
292
|
+
)
|
|
293
|
+
body = _mapping(response, "Ramp transaction response")
|
|
294
|
+
transaction = body.get("transaction")
|
|
295
|
+
return GetRampTransactionResult(
|
|
296
|
+
transaction=(
|
|
297
|
+
_normalize_ramp_transaction(transaction)
|
|
298
|
+
if transaction is not None
|
|
299
|
+
else None
|
|
300
|
+
)
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
async def list_transactions(
|
|
304
|
+
self,
|
|
305
|
+
*,
|
|
306
|
+
wallet_id: str,
|
|
307
|
+
network: Network | None = None,
|
|
308
|
+
direction: ActiveRampDirection | None = None,
|
|
309
|
+
status: ActiveRampTransactionStatus | None = None,
|
|
310
|
+
limit: int | None = None,
|
|
311
|
+
) -> ListRampTransactionsResult:
|
|
312
|
+
resolved_network = require_network(network, self._default_network)
|
|
313
|
+
path = _path_with_query(
|
|
314
|
+
f"/wallet/api/ramp/wallets/{quote(wallet_id, safe='')}/transactions",
|
|
315
|
+
{
|
|
316
|
+
"network": to_proto_network(resolved_network),
|
|
317
|
+
"direction": (_direction_to_wire(direction) if direction else None),
|
|
318
|
+
"status": _status_to_wire(status) if status else None,
|
|
319
|
+
"limit": limit,
|
|
320
|
+
},
|
|
321
|
+
)
|
|
322
|
+
body = _mapping(await self._http.get(path), "Ramp transaction response")
|
|
323
|
+
transactions = body.get("transactions", [])
|
|
324
|
+
if not isinstance(transactions, Sequence) or isinstance(
|
|
325
|
+
transactions, (str, bytes)
|
|
326
|
+
):
|
|
327
|
+
raise ValueError("Ramp transaction response has invalid transactions")
|
|
328
|
+
return ListRampTransactionsResult(
|
|
329
|
+
tuple(_normalize_ramp_transaction(item) for item in transactions)
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def normalize_ramp_options(response: object) -> GetRampOptionsResult:
|
|
334
|
+
body = _mapping(response, "Ramp options response")
|
|
335
|
+
return GetRampOptionsResult(
|
|
336
|
+
country_codes=_string_tuple(
|
|
337
|
+
body.get("countryCodes", body.get("country_codes", []))
|
|
338
|
+
),
|
|
339
|
+
fiat_currency_codes=_string_tuple(
|
|
340
|
+
body.get("fiatCurrencyCodes", body.get("fiat_currency_codes", []))
|
|
341
|
+
),
|
|
342
|
+
payment_method_types=tuple(
|
|
343
|
+
_normalize_payment_method(value)
|
|
344
|
+
for value in _sequence(
|
|
345
|
+
body.get(
|
|
346
|
+
"paymentMethodTypes",
|
|
347
|
+
body.get("payment_method_types", []),
|
|
348
|
+
),
|
|
349
|
+
"paymentMethodTypes",
|
|
350
|
+
)
|
|
351
|
+
),
|
|
352
|
+
crypto_currency_codes=_string_tuple(
|
|
353
|
+
body.get("cryptoCurrencyCodes", body.get("crypto_currency_codes", []))
|
|
354
|
+
),
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def normalize_quote_ramp_result(response: object) -> QuoteRampResult:
|
|
359
|
+
body = _mapping(response, "Ramp quote response")
|
|
360
|
+
return QuoteRampResult(
|
|
361
|
+
tuple(
|
|
362
|
+
_normalize_ramp_quote(item)
|
|
363
|
+
for item in _sequence(body.get("quotes", []), "quotes")
|
|
364
|
+
)
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def normalize_create_ramp_session_result(
|
|
369
|
+
response: object,
|
|
370
|
+
) -> CreateRampSessionResult:
|
|
371
|
+
body = _mapping(response, "Ramp session response")
|
|
372
|
+
return CreateRampSessionResult(
|
|
373
|
+
local_session_id=_required_string(
|
|
374
|
+
_pick(body, "localSessionId", "local_session_id"), "localSessionId"
|
|
375
|
+
),
|
|
376
|
+
meld_session_id=_required_string(
|
|
377
|
+
_pick(body, "meldSessionId", "meld_session_id"), "meldSessionId"
|
|
378
|
+
),
|
|
379
|
+
external_customer_id=_required_string(
|
|
380
|
+
_pick(body, "externalCustomerId", "external_customer_id"),
|
|
381
|
+
"externalCustomerId",
|
|
382
|
+
),
|
|
383
|
+
external_session_id=_required_string(
|
|
384
|
+
_pick(body, "externalSessionId", "external_session_id"),
|
|
385
|
+
"externalSessionId",
|
|
386
|
+
),
|
|
387
|
+
launch_url=_required_string(
|
|
388
|
+
_pick(body, "launchUrl", "launch_url"), "launchUrl"
|
|
389
|
+
),
|
|
390
|
+
fallback_launch_url=_optional_string(
|
|
391
|
+
_pick(body, "fallbackLaunchUrl", "fallback_launch_url")
|
|
392
|
+
),
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _quote_request(args: QuoteRampArgs) -> dict[str, object]:
|
|
397
|
+
return {
|
|
398
|
+
"customer": {
|
|
399
|
+
"partnerApplicationId": args.customer.partner_application_id,
|
|
400
|
+
"swigUserId": args.customer.swig_user_id,
|
|
401
|
+
"externalCustomerId": args.customer.external_customer_id,
|
|
402
|
+
"externalBusinessId": args.customer.external_business_id,
|
|
403
|
+
"customerType": _customer_type_to_wire(args.customer.customer_type),
|
|
404
|
+
},
|
|
405
|
+
"wallet": {
|
|
406
|
+
"walletId": args.wallet.wallet_id,
|
|
407
|
+
"walletAddress": args.wallet.wallet_address,
|
|
408
|
+
"network": to_proto_network(args.wallet.network),
|
|
409
|
+
},
|
|
410
|
+
"direction": _direction_to_wire(args.direction),
|
|
411
|
+
"sourceAmount": args.source_amount,
|
|
412
|
+
"sourceCurrencyCode": args.source_currency_code,
|
|
413
|
+
"destinationCurrencyCode": args.destination_currency_code,
|
|
414
|
+
"countryCode": args.country_code,
|
|
415
|
+
"subdivision": args.subdivision,
|
|
416
|
+
"paymentMethodType": (
|
|
417
|
+
_payment_method_to_wire(args.payment_method_type)
|
|
418
|
+
if args.payment_method_type is not None
|
|
419
|
+
else None
|
|
420
|
+
),
|
|
421
|
+
"serviceProviders": [
|
|
422
|
+
_service_provider_to_wire(value) for value in args.service_providers
|
|
423
|
+
],
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def _normalize_ramp_quote(value: object) -> RampQuote:
|
|
428
|
+
body = _mapping(value, "Ramp quote")
|
|
429
|
+
low_kyc = _pick(body, "lowKyc", "low_kyc")
|
|
430
|
+
if low_kyc is not None and not isinstance(low_kyc, bool):
|
|
431
|
+
raise ValueError("Ramp response has invalid lowKyc")
|
|
432
|
+
return RampQuote(
|
|
433
|
+
quote_id=_required_string(_pick(body, "quoteId", "quote_id"), "quoteId"),
|
|
434
|
+
direction=_normalize_direction(body.get("direction")),
|
|
435
|
+
service_provider=_normalize_service_provider(
|
|
436
|
+
_pick(body, "serviceProvider", "service_provider")
|
|
437
|
+
),
|
|
438
|
+
payment_method_type=_normalize_payment_method(
|
|
439
|
+
_pick(body, "paymentMethodType", "payment_method_type")
|
|
440
|
+
),
|
|
441
|
+
source_amount=_required_string(
|
|
442
|
+
_pick(body, "sourceAmount", "source_amount"), "sourceAmount"
|
|
443
|
+
),
|
|
444
|
+
source_currency_code=_required_string(
|
|
445
|
+
_pick(body, "sourceCurrencyCode", "source_currency_code"),
|
|
446
|
+
"sourceCurrencyCode",
|
|
447
|
+
),
|
|
448
|
+
destination_amount=_required_string(
|
|
449
|
+
_pick(body, "destinationAmount", "destination_amount"),
|
|
450
|
+
"destinationAmount",
|
|
451
|
+
),
|
|
452
|
+
destination_currency_code=_required_string(
|
|
453
|
+
_pick(body, "destinationCurrencyCode", "destination_currency_code"),
|
|
454
|
+
"destinationCurrencyCode",
|
|
455
|
+
),
|
|
456
|
+
exchange_rate=_required_string(
|
|
457
|
+
_pick(body, "exchangeRate", "exchange_rate"), "exchangeRate"
|
|
458
|
+
),
|
|
459
|
+
total_fee=_required_string(_pick(body, "totalFee", "total_fee"), "totalFee"),
|
|
460
|
+
network_fee=_required_string(
|
|
461
|
+
_pick(body, "networkFee", "network_fee"), "networkFee"
|
|
462
|
+
),
|
|
463
|
+
transaction_fee=_required_string(
|
|
464
|
+
_pick(body, "transactionFee", "transaction_fee"),
|
|
465
|
+
"transactionFee",
|
|
466
|
+
),
|
|
467
|
+
partner_fee=_required_string(
|
|
468
|
+
_pick(body, "partnerFee", "partner_fee"), "partnerFee"
|
|
469
|
+
),
|
|
470
|
+
ramp_score=_optional_string(_pick(body, "rampScore", "ramp_score")),
|
|
471
|
+
low_kyc=low_kyc,
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def _normalize_ramp_transaction(value: object) -> RampTransaction:
|
|
476
|
+
body = _mapping(value, "Ramp transaction")
|
|
477
|
+
payment_method = _pick(body, "paymentMethodType", "payment_method_type")
|
|
478
|
+
return RampTransaction(
|
|
479
|
+
transaction_id=_required_string(
|
|
480
|
+
_pick(body, "transactionId", "transaction_id"), "transactionId"
|
|
481
|
+
),
|
|
482
|
+
meld_transaction_id=_optional_string(
|
|
483
|
+
_pick(body, "meldTransactionId", "meld_transaction_id")
|
|
484
|
+
),
|
|
485
|
+
meld_session_id=_optional_string(
|
|
486
|
+
_pick(body, "meldSessionId", "meld_session_id")
|
|
487
|
+
),
|
|
488
|
+
wallet_id=_required_string(_pick(body, "walletId", "wallet_id"), "walletId"),
|
|
489
|
+
direction=_normalize_direction(body.get("direction")),
|
|
490
|
+
transaction_type=_normalize_transaction_type(
|
|
491
|
+
_pick(body, "transactionType", "transaction_type")
|
|
492
|
+
),
|
|
493
|
+
status=_normalize_status(body.get("status")),
|
|
494
|
+
service_provider=_normalize_service_provider(
|
|
495
|
+
_pick(body, "serviceProvider", "service_provider")
|
|
496
|
+
),
|
|
497
|
+
payment_method_type=(
|
|
498
|
+
_normalize_payment_method(payment_method)
|
|
499
|
+
if payment_method is not None
|
|
500
|
+
else None
|
|
501
|
+
),
|
|
502
|
+
source_amount=_required_string(
|
|
503
|
+
_pick(body, "sourceAmount", "source_amount"), "sourceAmount"
|
|
504
|
+
),
|
|
505
|
+
source_currency_code=_required_string(
|
|
506
|
+
_pick(body, "sourceCurrencyCode", "source_currency_code"),
|
|
507
|
+
"sourceCurrencyCode",
|
|
508
|
+
),
|
|
509
|
+
destination_amount=_optional_string(
|
|
510
|
+
_pick(body, "destinationAmount", "destination_amount")
|
|
511
|
+
),
|
|
512
|
+
destination_currency_code=_required_string(
|
|
513
|
+
_pick(body, "destinationCurrencyCode", "destination_currency_code"),
|
|
514
|
+
"destinationCurrencyCode",
|
|
515
|
+
),
|
|
516
|
+
created_at=_required_string(
|
|
517
|
+
_pick(body, "createdAt", "created_at"), "createdAt"
|
|
518
|
+
),
|
|
519
|
+
updated_at=_required_string(
|
|
520
|
+
_pick(body, "updatedAt", "updated_at"), "updatedAt"
|
|
521
|
+
),
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _direction_to_wire(value: ActiveRampDirection) -> str:
|
|
526
|
+
return {
|
|
527
|
+
"onramp": "RAMP_DIRECTION_ONRAMP",
|
|
528
|
+
"offramp": "RAMP_DIRECTION_OFFRAMP",
|
|
529
|
+
"transfer": "RAMP_DIRECTION_TRANSFER",
|
|
530
|
+
}[value]
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def _customer_type_to_wire(value: RampCustomerType) -> str:
|
|
534
|
+
return {
|
|
535
|
+
"individual": "RAMP_CUSTOMER_TYPE_INDIVIDUAL",
|
|
536
|
+
"business": "RAMP_CUSTOMER_TYPE_BUSINESS",
|
|
537
|
+
"unspecified": "RAMP_CUSTOMER_TYPE_UNSPECIFIED",
|
|
538
|
+
}[value]
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def _service_provider_to_wire(value: RampServiceProvider) -> str:
|
|
542
|
+
return {
|
|
543
|
+
"other": "RAMP_SERVICE_PROVIDER_OTHER",
|
|
544
|
+
"unspecified": "RAMP_SERVICE_PROVIDER_UNSPECIFIED",
|
|
545
|
+
}[value]
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def _payment_method_to_wire(value: RampPaymentMethodType) -> str:
|
|
549
|
+
return {
|
|
550
|
+
"other": "RAMP_PAYMENT_METHOD_TYPE_OTHER",
|
|
551
|
+
"credit-debit-card": "RAMP_PAYMENT_METHOD_TYPE_CREDIT_DEBIT_CARD",
|
|
552
|
+
"ach": "RAMP_PAYMENT_METHOD_TYPE_ACH",
|
|
553
|
+
"bank-transfer": "RAMP_PAYMENT_METHOD_TYPE_BANK_TRANSFER",
|
|
554
|
+
"apple-pay": "RAMP_PAYMENT_METHOD_TYPE_APPLE_PAY",
|
|
555
|
+
"google-pay": "RAMP_PAYMENT_METHOD_TYPE_GOOGLE_PAY",
|
|
556
|
+
"pix": "RAMP_PAYMENT_METHOD_TYPE_PIX",
|
|
557
|
+
"unspecified": "RAMP_PAYMENT_METHOD_TYPE_UNSPECIFIED",
|
|
558
|
+
}[value]
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def _status_to_wire(value: ActiveRampTransactionStatus) -> str:
|
|
562
|
+
return f"RAMP_TRANSACTION_STATUS_{value.upper()}"
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
def _normalize_direction(value: object) -> RampDirection:
|
|
566
|
+
values: dict[object, RampDirection] = {
|
|
567
|
+
"onramp": "onramp",
|
|
568
|
+
"RAMP_DIRECTION_ONRAMP": "onramp",
|
|
569
|
+
1: "onramp",
|
|
570
|
+
"offramp": "offramp",
|
|
571
|
+
"RAMP_DIRECTION_OFFRAMP": "offramp",
|
|
572
|
+
2: "offramp",
|
|
573
|
+
"transfer": "transfer",
|
|
574
|
+
"RAMP_DIRECTION_TRANSFER": "transfer",
|
|
575
|
+
3: "transfer",
|
|
576
|
+
"unspecified": "unspecified",
|
|
577
|
+
"RAMP_DIRECTION_UNSPECIFIED": "unspecified",
|
|
578
|
+
0: "unspecified",
|
|
579
|
+
None: "unspecified",
|
|
580
|
+
}
|
|
581
|
+
try:
|
|
582
|
+
return values[value]
|
|
583
|
+
except (KeyError, TypeError) as error:
|
|
584
|
+
raise ValueError("Ramp response has invalid direction") from error
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def _normalize_service_provider(value: object) -> RampServiceProvider:
|
|
588
|
+
if value in ("other", "RAMP_SERVICE_PROVIDER_OTHER", 1):
|
|
589
|
+
return "other"
|
|
590
|
+
if value in (None, "unspecified", "RAMP_SERVICE_PROVIDER_UNSPECIFIED", 0):
|
|
591
|
+
return "unspecified"
|
|
592
|
+
raise ValueError("Ramp response has invalid serviceProvider")
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def _normalize_payment_method(value: object) -> RampPaymentMethodType:
|
|
596
|
+
values: dict[object, RampPaymentMethodType] = {
|
|
597
|
+
"other": "other",
|
|
598
|
+
"RAMP_PAYMENT_METHOD_TYPE_OTHER": "other",
|
|
599
|
+
1: "other",
|
|
600
|
+
"credit-debit-card": "credit-debit-card",
|
|
601
|
+
"RAMP_PAYMENT_METHOD_TYPE_CREDIT_DEBIT_CARD": "credit-debit-card",
|
|
602
|
+
2: "credit-debit-card",
|
|
603
|
+
"ach": "ach",
|
|
604
|
+
"RAMP_PAYMENT_METHOD_TYPE_ACH": "ach",
|
|
605
|
+
3: "ach",
|
|
606
|
+
"bank-transfer": "bank-transfer",
|
|
607
|
+
"RAMP_PAYMENT_METHOD_TYPE_BANK_TRANSFER": "bank-transfer",
|
|
608
|
+
4: "bank-transfer",
|
|
609
|
+
"apple-pay": "apple-pay",
|
|
610
|
+
"RAMP_PAYMENT_METHOD_TYPE_APPLE_PAY": "apple-pay",
|
|
611
|
+
5: "apple-pay",
|
|
612
|
+
"google-pay": "google-pay",
|
|
613
|
+
"RAMP_PAYMENT_METHOD_TYPE_GOOGLE_PAY": "google-pay",
|
|
614
|
+
6: "google-pay",
|
|
615
|
+
"pix": "pix",
|
|
616
|
+
"RAMP_PAYMENT_METHOD_TYPE_PIX": "pix",
|
|
617
|
+
7: "pix",
|
|
618
|
+
"unspecified": "unspecified",
|
|
619
|
+
"RAMP_PAYMENT_METHOD_TYPE_UNSPECIFIED": "unspecified",
|
|
620
|
+
0: "unspecified",
|
|
621
|
+
None: "unspecified",
|
|
622
|
+
}
|
|
623
|
+
try:
|
|
624
|
+
return values[value]
|
|
625
|
+
except (KeyError, TypeError) as error:
|
|
626
|
+
raise ValueError("Ramp response has invalid paymentMethodType") from error
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def _normalize_transaction_type(value: object) -> RampTransactionType:
|
|
630
|
+
values: tuple[tuple[tuple[object, ...], RampTransactionType], ...] = (
|
|
631
|
+
(
|
|
632
|
+
("crypto-purchase", "RAMP_TRANSACTION_TYPE_CRYPTO_PURCHASE", 1),
|
|
633
|
+
"crypto-purchase",
|
|
634
|
+
),
|
|
635
|
+
(("crypto-sell", "RAMP_TRANSACTION_TYPE_CRYPTO_SELL", 2), "crypto-sell"),
|
|
636
|
+
(
|
|
637
|
+
("crypto-purchase-swap", "RAMP_TRANSACTION_TYPE_CRYPTO_PURCHASE_SWAP", 3),
|
|
638
|
+
"crypto-purchase-swap",
|
|
639
|
+
),
|
|
640
|
+
(
|
|
641
|
+
("crypto-sell-swap", "RAMP_TRANSACTION_TYPE_CRYPTO_SELL_SWAP", 4),
|
|
642
|
+
"crypto-sell-swap",
|
|
643
|
+
),
|
|
644
|
+
(("transfer", "RAMP_TRANSACTION_TYPE_TRANSFER", 5), "transfer"),
|
|
645
|
+
((None, "unspecified", "RAMP_TRANSACTION_TYPE_UNSPECIFIED", 0), "unspecified"),
|
|
646
|
+
)
|
|
647
|
+
for candidates, normalized in values:
|
|
648
|
+
if value in candidates:
|
|
649
|
+
return normalized
|
|
650
|
+
raise ValueError("Ramp response has invalid transactionType")
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
def _normalize_status(value: object) -> RampTransactionStatus:
|
|
654
|
+
normalized_values: tuple[RampTransactionStatus, ...] = (
|
|
655
|
+
"created",
|
|
656
|
+
"pending",
|
|
657
|
+
"settling",
|
|
658
|
+
"settled",
|
|
659
|
+
"failed",
|
|
660
|
+
"declined",
|
|
661
|
+
"cancelled",
|
|
662
|
+
"refunded",
|
|
663
|
+
)
|
|
664
|
+
for index, normalized in enumerate(normalized_values, start=1):
|
|
665
|
+
if value in (
|
|
666
|
+
normalized,
|
|
667
|
+
f"RAMP_TRANSACTION_STATUS_{normalized.upper()}",
|
|
668
|
+
index,
|
|
669
|
+
):
|
|
670
|
+
return normalized
|
|
671
|
+
if value in (None, "unspecified", "RAMP_TRANSACTION_STATUS_UNSPECIFIED", 0):
|
|
672
|
+
return "unspecified"
|
|
673
|
+
raise ValueError("Ramp response has invalid status")
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def _path_with_query(path: str, query_values: Mapping[str, object]) -> str:
|
|
677
|
+
query = {
|
|
678
|
+
key: str(value) for key, value in query_values.items() if value is not None
|
|
679
|
+
}
|
|
680
|
+
return f"{path}?{urlencode(query)}" if query else path
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
def _mapping(value: object, label: str) -> Mapping[str, object]:
|
|
684
|
+
if isinstance(value, Mapping):
|
|
685
|
+
return value
|
|
686
|
+
raise ValueError(f"{label} must be an object")
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
def _sequence(value: object, field: str) -> Sequence[object]:
|
|
690
|
+
if isinstance(value, Sequence) and not isinstance(value, (str, bytes)):
|
|
691
|
+
return value
|
|
692
|
+
raise ValueError(f"Ramp response has invalid {field}")
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
def _string_tuple(value: object) -> tuple[str, ...]:
|
|
696
|
+
sequence = _sequence(value, "string list")
|
|
697
|
+
if not all(isinstance(item, str) for item in sequence):
|
|
698
|
+
raise ValueError("Ramp response has invalid string list")
|
|
699
|
+
return tuple(item for item in sequence if isinstance(item, str))
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
def _required_string(value: object, field: str) -> str:
|
|
703
|
+
if isinstance(value, str):
|
|
704
|
+
return value
|
|
705
|
+
if isinstance(value, (int, bool)):
|
|
706
|
+
return str(value)
|
|
707
|
+
raise ValueError(f"Ramp response is missing {field}")
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
def _optional_string(value: object) -> str | None:
|
|
711
|
+
return value if isinstance(value, str) else None
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
def _pick(value: Mapping[str, object], *keys: str) -> object:
|
|
715
|
+
for key in keys:
|
|
716
|
+
if key in value:
|
|
717
|
+
return value[key]
|
|
718
|
+
return None
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
def _non_empty(value: str, field: str) -> str:
|
|
722
|
+
if not value.strip():
|
|
723
|
+
raise ValueError(f"{field} is required")
|
|
724
|
+
return value
|