Skip to content

Commit cfe9e11

Browse files
committed
feat: README file updated
1 parent 80b4d36 commit cfe9e11

File tree

4 files changed

+233
-48
lines changed

4 files changed

+233
-48
lines changed

README.md

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,168 @@
1-
# cngn-pyhon-library
1+
# cngn-python-library
2+
3+
CNGnManager is a Python library for interacting with a CNGN API. It provides a simple interface for various operations such as checking balance, swapping between chains, depositing for redemption, creating virtual accounts, and more.
4+
5+
## Table of Contents
6+
7+
- [Installation](#installation)
8+
- [Usage](#usage)
9+
- [Available Methods](#available-methods)
10+
- [Testing](#testing)
11+
- [Error Handling](#error-handling)
12+
- [Types](#types)
13+
- [Security](#security)
14+
- [Contributing](#contributing)
15+
- [Support](#support)
16+
- [License](#license)
17+
18+
## Installation
19+
20+
To install CNGnManager and its dependencies, run:
21+
22+
```bash
23+
pip install cngn-manager
24+
```
25+
26+
## Usage
27+
28+
First, import the `CNGnManager` class using it namespace WrappedCBDC\CNGNManager: and all necessary constants.
29+
30+
```python
31+
from cngn_manager import CNGnManager, Network, ProviderType
32+
```
33+
34+
Then, create an instance of `CNGnManager` with your secrets:
35+
36+
```python
37+
import os
38+
39+
api_key = "cngn_live_sk**********"
40+
encryption_key = "yourencryptionkey"
41+
ssh_private_key = """-----BEGIN OPENSSH PRIVATE KEY-----
42+
your ssh key
43+
-----END OPENSSH PRIVATE KEY-----"""
44+
45+
# NOTE: You can also get your private key from a file using
46+
# ssh_private_key = os.open("/path/to/sshkey.key").read()
47+
48+
manager = CNGnManager(api_key, ssh_private_key, encryption_key)
49+
# Example: Get balance
50+
balance = manager.get_balance()
51+
print(balance)
52+
```
53+
54+
## Available Methods
55+
56+
### Get Balance
57+
58+
```python
59+
balance = manager.get_balance()
60+
print(balance)
61+
```
62+
63+
### Get Transaction History
64+
65+
```python
66+
transactions = manager.get_transaction_history()
67+
print(transactions)
68+
69+
```
70+
71+
### Swap Between Chains
72+
73+
```python
74+
swap_params = {
75+
"amount": 100,
76+
"address": "0x1234...",
77+
"network": Network.BSC
78+
}
79+
80+
swap_result = manager.swap_between_chains(swap_params)
81+
print(swap_result)
82+
83+
```
84+
85+
### Deposit for Redemption
86+
87+
```python
88+
deposit_params = {
89+
"amount": 1000,
90+
"bank": "Example Bank",
91+
"accountNumber": "1234567890"
92+
}
93+
94+
deposit_result = manager.deposit_for_redemption(deposit_params)
95+
print(deposit_result)
96+
97+
```
98+
99+
### Create Virtual Account
100+
101+
```python
102+
mint_params = {
103+
"provider": ProviderType.KORAPAY
104+
}
105+
106+
virtual_account = manager.create_virtual_account(mint_params)
107+
print(virtual_account)
108+
109+
```
110+
111+
### Whitelist Address
112+
113+
```python
114+
whitelist_params = {
115+
"bscAddress": "0x1234...",
116+
"bankName": "Example Bank",
117+
"bankAccountNumber": "1234567890"
118+
}
119+
120+
whitelist_result = manager.whitelist_address(whitelist_params)
121+
print(whitelist_result)
122+
123+
```
124+
125+
## Testing
126+
127+
This project uses Jest for testing. To run the tests, follow these steps:
128+
129+
1. Run the test command:
130+
131+
```bash
132+
python3 -m unittest discover tests
133+
```
134+
135+
This will run all tests in the `tests` directory.
136+
137+
### Test Structure
138+
139+
The tests are located in the `tests` directory. They cover various aspects of the CNGnManager class, including:
140+
141+
- API calls for different endpoints (GET and POST requests)
142+
- Encryption and decryption of data
143+
- Error handling for various scenarios
144+
145+
146+
## Error Handling
147+
148+
The library uses a custom error handling mechanism. All API errors are caught and thrown as `Error` objects with descriptive messages.
149+
150+
## Types
151+
152+
The library includes python definitions for all parameters and return types. Please refer to the type definitions in the source code for more details.
153+
154+
## Security
155+
156+
This library uses AES encryption for request payloads and Ed25519 decryption for response data. Ensure that your `encryptionKey` and `privateKey` are kept secure.
157+
158+
## Contributing
159+
160+
Contributions, issues, and feature requests are welcome. Feel free to check [issues page](https://github.com/wrappedcbdc/cngn-python-library/issues) if you want to contribute.
161+
162+
## Support
163+
164+
If you have any questions or need help using the library, please open an issue in the GitHub repository.
165+
166+
## License
167+
168+
[MIT](https://choosealicense.com/licenses/mit/)

cngn_manager/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# ____ _ _ ____ __ __
2+
# / ___| \ | |/ ___|_ __ | \/ | __ _ _ __ __ _ __ _ ___ _ __
3+
# | | | \| | | _| '_ \| |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '__|
4+
# | |___| |\ | |_| | | | | | | | (_| | | | | (_| | (_| | __/ |
5+
# \____|_| \_|\____|_| |_|_| |_|\__,_|_| |_|\__,_|\__, |\___|_|
6+
# |___/
7+
#
8+
9+
"""
10+
cNGN HTTP Library
11+
~~~~~~~~~~~~~~~~~~~~~
12+
13+
"""
14+
15+
from .main import CNGnManager
16+
from .constants import Network, ProviderType

cngn_manager/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
__title__ = "cngn_manager"
1111
__description__ = "Python HTTP for Humans."
1212
__url__ = "https://docs.cngn.co"
13-
__version__ = "0.0.1"
13+
__version__ = "0.0.2"
1414
__author__ = "Emmanuel Onyo"
1515
__author_email__ = "[email protected]"
1616
__license__ = "MIT License"

cngn_manager/main.py

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
#
88

99

10-
import requests # type: ignore
1110
import json
11+
from typing import Optional, Dict, Any
12+
import requests
13+
from requests.exceptions import RequestException, HTTPError
1214
from cngn_manager.AESCrypto import AESCrypto
1315
from cngn_manager.Ed25519Crypto import Ed25519Crypto
1416

17+
1518
"""
1619
CNGnManager class is a wrapper around the CNGn API.
1720
It provides methods to interact with the CNGn API endpoints.
@@ -27,6 +30,7 @@ class CNGnManager:
2730

2831
def __init__(self, api_key: str, private_key: str, encryption_key: str):
2932
self.api_key = api_key
33+
self.api_url = self.API_URL
3034
self.private_key = private_key
3135
self.encryption_key = encryption_key
3236
self.client = requests.Session()
@@ -36,57 +40,55 @@ def __init__(self, api_key: str, private_key: str, encryption_key: str):
3640
'Accept': 'application/json',
3741
})
3842

39-
def handle_api_error(self, error):
40-
# Handle the API error
41-
pass
42-
43-
def __make_calls(self, method: str, endpoint: str, data: dict = None) -> str:
44-
45-
43+
def __make_calls(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
4644
aes_crypto = AESCrypto()
4745
ed_crypto = Ed25519Crypto()
4846

4947
try:
50-
if data is not None:
51-
new_data = json.dumps(data)
52-
encrypted_data = aes_crypto.encrypt(new_data, self.encryption_key)
53-
data = encrypted_data
54-
response = self.client.request(method, f'{self.API_URL}/{self.API_CURRENT_VERSION}{endpoint}', json=data)
55-
else:
56-
response = self.client.request(method, f'{self.API_URL}/{self.API_CURRENT_VERSION}{endpoint}')
57-
58-
response_data = response.json()
59-
60-
if response_data.get("data") is not None:
61-
decrypted_response = ed_crypto.decrypt_with_private_key(self.private_key, response_data["data"])
62-
response_data["data"] = json.loads(decrypted_response)
63-
64-
return json.dumps(response_data)
65-
66-
except (requests.exceptions.RequestException, requests.exceptions.HTTPError) as e:
67-
error_body = {
68-
'success': False,
69-
'error': 'API request failed',
70-
'message': str(e),
71-
'status_code': e.response.status_code if e.response else None,
72-
}
73-
74-
if e.response:
75-
resp = e.response.json()
76-
message = json.loads(resp.get('message', '{}'))
77-
resp["message"] = message
78-
return json.dumps(resp)
79-
80-
return json.dumps(error_body)
48+
url = f'{self.api_url}/{self.API_CURRENT_VERSION}{endpoint}'
49+
request_data = self._prepare_request_data(data, aes_crypto)
50+
response = self._send_request(method, url, request_data)
51+
return self._process_response(response, ed_crypto)
8152

53+
except (RequestException, HTTPError) as e:
54+
return self._handle_request_error(e)
8255
except Exception as e:
83-
return json.dumps({
84-
'success': False,
85-
'error': 'An unexpected error occurred',
86-
'message': str(e.message if hasattr(e, 'message') else str(e)),
87-
'status_code': 500,
88-
})
89-
56+
return self._handle_unexpected_error(e)
57+
58+
def _prepare_request_data(self, data: Optional[Dict[str, Any]], aes_crypto: AESCrypto) -> Optional[str]:
59+
if data is None:
60+
return None
61+
json_data = json.dumps(data)
62+
return aes_crypto.encrypt(json_data, self.encryption_key)
63+
64+
def _send_request(self, method: str, url: str, data: Optional[str]) -> requests.Response:
65+
return self.client.request(method, url, json=data)
66+
67+
def _process_response(self, response: requests.Response, ed_crypto: Ed25519Crypto) -> Dict[str, Any]:
68+
response_data = response.json()
69+
if "data" in response_data:
70+
decrypted_response = ed_crypto.decrypt_with_private_key(self.private_key, response_data["data"])
71+
response_data["data"] = json.loads(decrypted_response)
72+
return response_data
73+
74+
def _handle_request_error(self, error: RequestException) -> Dict[str, Any]:
75+
if error.response:
76+
return error.response.json()
77+
return {
78+
'success': False,
79+
'error': 'API request failed',
80+
'message': str(error),
81+
'status_code': error.response.status_code if error.response else None,
82+
}
83+
84+
def _handle_unexpected_error(self, error: Exception) -> Dict[str, Any]:
85+
return {
86+
'success': False,
87+
'error': 'An unexpected error occurred',
88+
'message': str(error),
89+
'status_code': 500,
90+
}
91+
9092
def get_balance(self) -> str:
9193
return self.__make_calls("GET", "/api/balance")
9294

0 commit comments

Comments
 (0)