safeheron-api-sdk-python 1.1.13__tar.gz → 1.1.15__tar.gz
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.
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/PKG-INFO +1 -1
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/account_api.py +15 -4
- safeheron_api_sdk_python-1.1.15/safeheron_api_sdk_python/api/tools_api.py +32 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/web3_api.py +10 -5
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/cosigner/co_signer_converter.py +66 -11
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/tools.py +21 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python.egg-info/PKG-INFO +1 -1
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python.egg-info/SOURCES.txt +1 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/setup.py +1 -1
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/LICENSE +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/README.rst +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/coin_api.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/mpc_sign_api.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/transaction_api.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/webhook_api.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/api/whitelist_api.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/client.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python/webhook/webhook_converter.py +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python.egg-info/dependency_links.txt +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python.egg-info/requires.txt +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/safeheron_api_sdk_python.egg-info/top_level.txt +0 -0
- {safeheron_api_sdk_python-1.1.13 → safeheron_api_sdk_python-1.1.15}/setup.cfg +0 -0
|
@@ -31,7 +31,7 @@ class OneAccountRequest:
|
|
|
31
31
|
|
|
32
32
|
class CreateAccountRequest:
|
|
33
33
|
def __init__(self):
|
|
34
|
-
# Account name,
|
|
34
|
+
# Account name, 50 characters max
|
|
35
35
|
self.accountName = None
|
|
36
36
|
# Merchant unique business ID (100 characters max)
|
|
37
37
|
# The customerRefId uniquely represents a wallet. In the case of duplicate customerRefId values (for example, when resubmitting due to request timeouts or other errors), the data returned by the interface will remain consistent
|
|
@@ -49,7 +49,7 @@ class CreateAccountRequest:
|
|
|
49
49
|
|
|
50
50
|
class BatchCreateAccountRequest:
|
|
51
51
|
def __init__(self):
|
|
52
|
-
# The prefix of wallet account name,
|
|
52
|
+
# The prefix of wallet account name, 50 characters max
|
|
53
53
|
self.accountName = None
|
|
54
54
|
# Display status in Safeheron App
|
|
55
55
|
# True: not display
|
|
@@ -132,6 +132,11 @@ class InfoAccountCoinAddressRequest:
|
|
|
132
132
|
# Coin receiving address
|
|
133
133
|
self.address = None
|
|
134
134
|
|
|
135
|
+
class AccountCoinBalanceRequest:
|
|
136
|
+
def __init__(self):
|
|
137
|
+
# Coin Keys, max 10
|
|
138
|
+
self.coinKeyList = None
|
|
139
|
+
|
|
135
140
|
|
|
136
141
|
class RenameAccountCoinAddressRequest:
|
|
137
142
|
def __init__(self):
|
|
@@ -160,9 +165,9 @@ class BatchCreateAccountCoinUTXORequest:
|
|
|
160
165
|
self.coinKey = None
|
|
161
166
|
# Account key
|
|
162
167
|
self.accountKey = None
|
|
163
|
-
# Address group name, 30 characters max
|
|
164
|
-
self.count = None
|
|
165
168
|
# The number, max is 100
|
|
169
|
+
self.count = None
|
|
170
|
+
# Address group name, 30 characters max
|
|
166
171
|
self.addressGroupName = None
|
|
167
172
|
|
|
168
173
|
|
|
@@ -240,6 +245,12 @@ class AccountApi:
|
|
|
240
245
|
def info_account_coin_address(self, request: InfoAccountCoinAddressRequest):
|
|
241
246
|
return self.api_client.send_request(request, '/v1/account/coin/address/info')
|
|
242
247
|
|
|
248
|
+
# Retrieve Coin Balance
|
|
249
|
+
# Get the coin balance of all asset wallets under the team.
|
|
250
|
+
def account_coin_balance(self, request: AccountCoinBalanceRequest):
|
|
251
|
+
return self.api_client.send_request(request, '/v1/account/coin/balance')
|
|
252
|
+
|
|
253
|
+
|
|
243
254
|
# Rename Coin Address Group of a Wallet Account
|
|
244
255
|
# Rename a coin address group of a wallet account.
|
|
245
256
|
def rename_account_coin_address(self, request: RenameAccountCoinAddressRequest):
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from safeheron_api_sdk_python.client import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AmlCheckerRequestRequest:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
# Blockchain network, supports:
|
|
7
|
+
# Bitcoin
|
|
8
|
+
# Ethereum
|
|
9
|
+
# Tron
|
|
10
|
+
self.network = None
|
|
11
|
+
# Address
|
|
12
|
+
self.address = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AmlCheckerRetrievesRequest:
|
|
16
|
+
def __init__(self):
|
|
17
|
+
# Risk assessment request ID, which can be created through the Create AML Risk Assessment Request interface.
|
|
18
|
+
self.requestId = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ToolsApi:
|
|
22
|
+
|
|
23
|
+
def __init__(self, config):
|
|
24
|
+
self.api_client = Client(config)
|
|
25
|
+
|
|
26
|
+
# Create AML Risk Assessment Request
|
|
27
|
+
def aml_checker_request(self, request: AmlCheckerRequestRequest):
|
|
28
|
+
return self.api_client.send_request(request, '/v1/tools/aml-checker/request')
|
|
29
|
+
|
|
30
|
+
# Retrieve AML Risk Assessment Result
|
|
31
|
+
def aml_checker_retrieves(self, request: AmlCheckerRetrievesRequest):
|
|
32
|
+
return self.api_client.send_request(request, '/v1/tools/aml-checker/retrieves')
|
|
@@ -3,7 +3,7 @@ from safeheron_api_sdk_python.client import *
|
|
|
3
3
|
|
|
4
4
|
class CreateWeb3AccountRequest:
|
|
5
5
|
def __init__(self):
|
|
6
|
-
# Account name,
|
|
6
|
+
# Account name, 50 characters max
|
|
7
7
|
self.accountName = None
|
|
8
8
|
# Whether display in Safeheron Console
|
|
9
9
|
# True: not display
|
|
@@ -17,10 +17,15 @@ class CreateWeb3AccountRequest:
|
|
|
17
17
|
|
|
18
18
|
class BatchCreateWeb3AccountRequest:
|
|
19
19
|
def __init__(self):
|
|
20
|
-
#
|
|
21
|
-
self.
|
|
22
|
-
#
|
|
23
|
-
|
|
20
|
+
# The prefix of wallet account name, 50 characters max
|
|
21
|
+
self.accountName = None
|
|
22
|
+
# Whether display in Safeheron Console
|
|
23
|
+
# True: not display
|
|
24
|
+
# False: display
|
|
25
|
+
# Default: false
|
|
26
|
+
self.hiddenOnUI = None
|
|
27
|
+
# Number of wallets to be created, greater than 0, less than 100
|
|
28
|
+
self.count = None
|
|
24
29
|
|
|
25
30
|
|
|
26
31
|
class ListWeb3AccountRequest:
|
|
@@ -9,18 +9,33 @@ class CoSignerResponse:
|
|
|
9
9
|
self.txKey = None
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
class CoSignerResponseV3:
|
|
13
|
+
def __init__(self):
|
|
14
|
+
# action
|
|
15
|
+
self.action = None
|
|
16
|
+
# approvalId
|
|
17
|
+
self.approvalId = None
|
|
18
|
+
|
|
19
|
+
|
|
12
20
|
class CoSignerConverter:
|
|
13
21
|
|
|
14
22
|
def __init__(self, config):
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
# Supports both coSignerPubKey and apiPublKey
|
|
24
|
+
self.co_signer_pub_key = config.get('coSignerPubKey') or config.get('apiPubKey')
|
|
25
|
+
|
|
26
|
+
# Supports both approvalCallbackServicePrivateKey and bizPrivKey
|
|
27
|
+
private_key = config.get('approvalCallbackServicePrivateKey') or config.get('bizPrivKey')
|
|
28
|
+
if private_key:
|
|
29
|
+
self.approval_callback_service_private_key = PEM_PRIVATE_HEAD + private_key + PEM_PRIVATE_END
|
|
30
|
+
|
|
31
|
+
# Supports both approvalCallbackServicePrivateKeyPemFile and bizPrivKeyPemFile
|
|
32
|
+
pem_file = config.get('approvalCallbackServicePrivateKeyPemFile') or config.get('bizPrivKeyPemFile')
|
|
33
|
+
if pem_file:
|
|
34
|
+
self.approval_callback_service_private_key = load_rsa_private_key(pem_file)
|
|
20
35
|
|
|
21
36
|
def request_convert(self, co_signer_call_back):
|
|
22
|
-
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.
|
|
23
|
-
api_user_rsa_sk = get_rsa_key(self.
|
|
37
|
+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
|
|
38
|
+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
|
|
24
39
|
required_keys = {
|
|
25
40
|
'key',
|
|
26
41
|
'sig',
|
|
@@ -65,10 +80,50 @@ class CoSignerConverter:
|
|
|
65
80
|
|
|
66
81
|
return json.loads(r.decode())
|
|
67
82
|
|
|
83
|
+
def request_v3_convert(self, co_signer_call_back):
|
|
84
|
+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
|
|
85
|
+
required_keys = {
|
|
86
|
+
'version',
|
|
87
|
+
'sig',
|
|
88
|
+
'bizContent',
|
|
89
|
+
'timestamp',
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
missing_keys = required_keys.difference(co_signer_call_back.keys())
|
|
93
|
+
if missing_keys:
|
|
94
|
+
raise Exception(co_signer_call_back)
|
|
95
|
+
co_signer_call_back['version'] = 'v3'
|
|
96
|
+
sig = co_signer_call_back.pop('sig')
|
|
97
|
+
|
|
98
|
+
need_sign_message = sort_request(co_signer_call_back)
|
|
99
|
+
v = rsa_pass_verify(platform_rsa_pk, need_sign_message, sig)
|
|
100
|
+
if not v:
|
|
101
|
+
raise Exception("rsa verify: false")
|
|
102
|
+
return json.loads(b64decode(co_signer_call_back['bizContent']).decode())
|
|
103
|
+
|
|
104
|
+
def response_v3_converter(self, co_signer_response: CoSignerResponseV3):
|
|
105
|
+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
|
|
106
|
+
ret = dict()
|
|
107
|
+
response_data = json.dumps(co_signer_response.__dict__).replace('\'', '\"').replace('\n', '').encode('utf-8')
|
|
108
|
+
|
|
109
|
+
if response_data is not None:
|
|
110
|
+
ret['bizContent'] = b64encode(response_data).decode()
|
|
111
|
+
|
|
112
|
+
ret['timestamp'] = str(int(time.time() * 1000))
|
|
113
|
+
ret['code'] = str('200')
|
|
114
|
+
ret['version'] = str('v3')
|
|
115
|
+
ret['message'] = str('SUCCESS')
|
|
116
|
+
|
|
117
|
+
# 4 sign request
|
|
118
|
+
need_sign_message = sort_request(ret)
|
|
119
|
+
ret['sig'] = rsa_pss_sign(api_user_rsa_sk, need_sign_message)
|
|
120
|
+
return ret
|
|
121
|
+
|
|
122
|
+
|
|
68
123
|
# It has been Deprecated,Please use convertCoSignerResponseWithNewCryptoType
|
|
69
124
|
def response_converter(self, co_signer_response: CoSignerResponse):
|
|
70
|
-
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.
|
|
71
|
-
api_user_rsa_sk = get_rsa_key(self.
|
|
125
|
+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
|
|
126
|
+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
|
|
72
127
|
|
|
73
128
|
ret = dict()
|
|
74
129
|
|
|
@@ -98,8 +153,8 @@ class CoSignerConverter:
|
|
|
98
153
|
return ret
|
|
99
154
|
|
|
100
155
|
def response_converter_with_new_crypto_type(self, co_signer_response: CoSignerResponse):
|
|
101
|
-
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.
|
|
102
|
-
api_user_rsa_sk = get_rsa_key(self.
|
|
156
|
+
platform_rsa_pk = get_rsa_key(PEM_PUBLIC_HEAD + self.co_signer_pub_key + PEM_PUBLIC_END)
|
|
157
|
+
api_user_rsa_sk = get_rsa_key(self.approval_callback_service_private_key)
|
|
103
158
|
|
|
104
159
|
ret = dict()
|
|
105
160
|
|
|
@@ -8,6 +8,7 @@ from Cryptodome.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
|
|
|
8
8
|
from Cryptodome.Hash import SHA256, SHA1
|
|
9
9
|
from Cryptodome import Random
|
|
10
10
|
from Crypto.Cipher import PKCS1_OAEP
|
|
11
|
+
from Cryptodome.Signature import pss
|
|
11
12
|
import json
|
|
12
13
|
import time
|
|
13
14
|
import requests
|
|
@@ -147,6 +148,16 @@ def rsa_sign(private_key, message_hash: bytes):
|
|
|
147
148
|
except Exception as e:
|
|
148
149
|
raise Exception("rsa sign error: %s" % e)
|
|
149
150
|
|
|
151
|
+
def rsa_pss_sign(private_key, message_hash: bytes):
|
|
152
|
+
try:
|
|
153
|
+
signer = pss.new(private_key)
|
|
154
|
+
digest = SHA256.new()
|
|
155
|
+
digest.update(message_hash)
|
|
156
|
+
signed = signer.sign(digest)
|
|
157
|
+
return b64encode(signed).decode()
|
|
158
|
+
except Exception as e:
|
|
159
|
+
raise Exception("rsa sign error: %s" % e)
|
|
160
|
+
|
|
150
161
|
|
|
151
162
|
def rsa_verify(public_key, message_hash: bytes, signature):
|
|
152
163
|
try:
|
|
@@ -157,6 +168,16 @@ def rsa_verify(public_key, message_hash: bytes, signature):
|
|
|
157
168
|
except Exception as e:
|
|
158
169
|
raise Exception("rsa sign error: %s" % e)
|
|
159
170
|
|
|
171
|
+
def rsa_pass_verify(public_key, message_hash: bytes, signature):
|
|
172
|
+
try:
|
|
173
|
+
verifier = pss.new(public_key)
|
|
174
|
+
digest = SHA256.new()
|
|
175
|
+
digest.update(message_hash)
|
|
176
|
+
verifier.verify(digest, b64decode(signature))
|
|
177
|
+
return True
|
|
178
|
+
except Exception as e:
|
|
179
|
+
raise Exception("rsa sign error: %s" % e)
|
|
180
|
+
|
|
160
181
|
|
|
161
182
|
def sort_request(r: dict):
|
|
162
183
|
sortData = json.dumps(r, sort_keys=True).replace(' ', '')
|
|
@@ -11,6 +11,7 @@ safeheron_api_sdk_python.egg-info/top_level.txt
|
|
|
11
11
|
safeheron_api_sdk_python/api/account_api.py
|
|
12
12
|
safeheron_api_sdk_python/api/coin_api.py
|
|
13
13
|
safeheron_api_sdk_python/api/mpc_sign_api.py
|
|
14
|
+
safeheron_api_sdk_python/api/tools_api.py
|
|
14
15
|
safeheron_api_sdk_python/api/transaction_api.py
|
|
15
16
|
safeheron_api_sdk_python/api/web3_api.py
|
|
16
17
|
safeheron_api_sdk_python/api/webhook_api.py
|
|
@@ -3,7 +3,7 @@ from setuptools import find_packages
|
|
|
3
3
|
with open("README.rst", "r") as f:
|
|
4
4
|
long_description = f.read()
|
|
5
5
|
setup(name='safeheron_api_sdk_python',
|
|
6
|
-
version='1.1.
|
|
6
|
+
version='1.1.15',
|
|
7
7
|
description='Python for Safeheron API',
|
|
8
8
|
long_description=long_description,
|
|
9
9
|
author='safeheron',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|