green-gdk 0.76.2__cp39-cp39-macosx_15_0_arm64.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.
green_gdk/__init__.py
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
from ._green_gdk import *
|
|
2
|
+
from ._green_gdk import _python_set_callback_handler, _python_destroy_session
|
|
3
|
+
import atexit
|
|
4
|
+
import json
|
|
5
|
+
import queue
|
|
6
|
+
import weakref
|
|
7
|
+
|
|
8
|
+
# Unused: Provided for back compatibility only
|
|
9
|
+
GA_MEMO_USER = 0
|
|
10
|
+
GA_MEMO_BIP70 = 1
|
|
11
|
+
|
|
12
|
+
class Call(object):
|
|
13
|
+
"""Handler class to process a call potentally requiring twofactor.
|
|
14
|
+
|
|
15
|
+
Initialize the class with the auth_handler object returned from
|
|
16
|
+
functions that may require authentication. Then call resolve()
|
|
17
|
+
on the object, optionally passing in callables to select and enter
|
|
18
|
+
twofactor auth methods and codes.
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, call_obj):
|
|
23
|
+
self.call_obj = call_obj
|
|
24
|
+
|
|
25
|
+
def status(self):
|
|
26
|
+
return json.loads(auth_handler_get_status(self.call_obj))
|
|
27
|
+
|
|
28
|
+
def _select_method(self, methods):
|
|
29
|
+
# Default implementation just uses the first method provided
|
|
30
|
+
return methods[0]
|
|
31
|
+
|
|
32
|
+
def _resolve_code(self, method):
|
|
33
|
+
if isinstance(method, dict):
|
|
34
|
+
# Caller must provide their own handler for data requests
|
|
35
|
+
raise RuntimeError(f'Unhandled data request {method}')
|
|
36
|
+
# 2FA: Default implementation just uses localtest dummy 2fa code
|
|
37
|
+
return '555555'
|
|
38
|
+
|
|
39
|
+
def request_code(self, method):
|
|
40
|
+
auth_handler_request_code(self.call_obj, method)
|
|
41
|
+
|
|
42
|
+
def resolve(self, select_method_fn=None, resolve_code_fn=None):
|
|
43
|
+
select_method_fn = select_method_fn or self._select_method
|
|
44
|
+
resolve_code_fn = resolve_code_fn or self._resolve_code
|
|
45
|
+
while True:
|
|
46
|
+
status = self.status()
|
|
47
|
+
state = status['status']
|
|
48
|
+
if state == 'error':
|
|
49
|
+
self.call_obj = None
|
|
50
|
+
raise RuntimeError(status['error'])
|
|
51
|
+
if state == 'done':
|
|
52
|
+
self.call_obj = None
|
|
53
|
+
return status['result']
|
|
54
|
+
if state == 'request_code':
|
|
55
|
+
method = select_method_fn(status['methods'])
|
|
56
|
+
auth_handler_request_code(self.call_obj, method)
|
|
57
|
+
elif state == 'resolve_code':
|
|
58
|
+
if 'required_data' in status:
|
|
59
|
+
# Hardware device authorization requested
|
|
60
|
+
code = resolve_code_fn(status['required_data'])
|
|
61
|
+
elif status['method'] == 'data':
|
|
62
|
+
# Caller data requested
|
|
63
|
+
code = resolve_code_fn(status)
|
|
64
|
+
else:
|
|
65
|
+
# Twofactor authorization requested
|
|
66
|
+
code = resolve_code_fn(status['method'])
|
|
67
|
+
auth_handler_resolve_code(self.call_obj, code)
|
|
68
|
+
elif state == 'call':
|
|
69
|
+
auth_handler_call(self.call_obj)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Session(object):
|
|
73
|
+
"""A session representing either a Green multisig or a singlesig wallet.
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# A list of weak references of sessions to destroy.
|
|
78
|
+
# If not destroyed manually, via with-scope or garbage collection,
|
|
79
|
+
# any sessions alive at program exit are destroyed.
|
|
80
|
+
_to_destroy = []
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
@atexit.register
|
|
84
|
+
def destroy_all():
|
|
85
|
+
while len(Session._to_destroy):
|
|
86
|
+
session = Session._to_destroy.pop()() # Pop and resolve weakref
|
|
87
|
+
if session is not None:
|
|
88
|
+
session._destroy()
|
|
89
|
+
|
|
90
|
+
def __init__(self, net_params):
|
|
91
|
+
self.notifications = queue.Queue()
|
|
92
|
+
self.session_obj = create_session()
|
|
93
|
+
Session._to_destroy.append(weakref.ref(self))
|
|
94
|
+
_python_set_callback_handler(
|
|
95
|
+
self.session_obj,
|
|
96
|
+
weakref.WeakMethod(self._callback_handler)
|
|
97
|
+
)
|
|
98
|
+
return self.connect(net_params)
|
|
99
|
+
|
|
100
|
+
def _destroy(self):
|
|
101
|
+
obj = getattr(self, 'session_obj', None)
|
|
102
|
+
if obj:
|
|
103
|
+
self.session_obj = None
|
|
104
|
+
_python_set_callback_handler(obj, None)
|
|
105
|
+
_python_destroy_session(obj)
|
|
106
|
+
|
|
107
|
+
def destroy(self):
|
|
108
|
+
for s in Session._to_destroy:
|
|
109
|
+
session = s() # Resolve weakref
|
|
110
|
+
if session == self:
|
|
111
|
+
Session._to_destroy.remove(s)
|
|
112
|
+
self._destroy()
|
|
113
|
+
break
|
|
114
|
+
|
|
115
|
+
def __enter__(self):
|
|
116
|
+
return self
|
|
117
|
+
|
|
118
|
+
def __exit__(self, *args):
|
|
119
|
+
self.destroy()
|
|
120
|
+
|
|
121
|
+
def __del__(self):
|
|
122
|
+
self.destroy()
|
|
123
|
+
|
|
124
|
+
def _callback_handler(self, obj, event):
|
|
125
|
+
assert obj is self.session_obj
|
|
126
|
+
try:
|
|
127
|
+
if obj:
|
|
128
|
+
self.callback_handler(json.loads(event))
|
|
129
|
+
except Exception as e:
|
|
130
|
+
print('exception {}\n'.format(e))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def callback_handler(self, event):
|
|
134
|
+
"""Callback handler.
|
|
135
|
+
|
|
136
|
+
Override or monkey patch to handle notifications, or read the
|
|
137
|
+
self.notification queue to receive events.
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
timeout_seconds = 60
|
|
141
|
+
self.notifications.put(event, timeout_seconds)
|
|
142
|
+
|
|
143
|
+
@staticmethod
|
|
144
|
+
def _to_json(obj):
|
|
145
|
+
return obj if isinstance(obj, str) else json.dumps(obj)
|
|
146
|
+
|
|
147
|
+
def connect(self, net_params):
|
|
148
|
+
return connect(self.session_obj, self._to_json(net_params))
|
|
149
|
+
|
|
150
|
+
def disconnect(self):
|
|
151
|
+
raise RuntimeError('use reconnect_hint() to disconnect a session')
|
|
152
|
+
|
|
153
|
+
def reconnect_hint(self, hint):
|
|
154
|
+
return reconnect_hint(self.session_obj, self._to_json(hint))
|
|
155
|
+
|
|
156
|
+
def get_proxy_settings(self):
|
|
157
|
+
return json.loads(get_proxy_settings(self.session_obj))
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def get_wallet_identifier(net_params, params):
|
|
161
|
+
return json.loads(get_wallet_identifier(Session._to_json(net_params), Session._to_json(params)))
|
|
162
|
+
|
|
163
|
+
def register_user(self, hw_device, details):
|
|
164
|
+
return Call(register_user(self.session_obj, self._to_json(hw_device), self._to_json(details)))
|
|
165
|
+
|
|
166
|
+
def login_user(self, hw_device, details):
|
|
167
|
+
return Call(login_user(self.session_obj, self._to_json(hw_device), self._to_json(details)))
|
|
168
|
+
|
|
169
|
+
def get_watch_only_username(self):
|
|
170
|
+
return get_watch_only_username(self.session_obj)
|
|
171
|
+
|
|
172
|
+
def remove_account(self):
|
|
173
|
+
return Call(remove_account(self.session_obj))
|
|
174
|
+
|
|
175
|
+
def encrypt_with_pin(self, details):
|
|
176
|
+
return Call(encrypt_with_pin(self.session_obj, self._to_json(details)))
|
|
177
|
+
|
|
178
|
+
def decrypt_with_pin(self, details):
|
|
179
|
+
return Call(decrypt_with_pin(self.session_obj, self._to_json(details)))
|
|
180
|
+
|
|
181
|
+
def rsa_verify(self, details):
|
|
182
|
+
return Call(rsa_verify(self.session_obj, self._to_json(details)))
|
|
183
|
+
|
|
184
|
+
def disable_all_pin_logins(self):
|
|
185
|
+
return disable_all_pin_logins(self.session_obj)
|
|
186
|
+
|
|
187
|
+
def create_subaccount(self, details):
|
|
188
|
+
return Call(create_subaccount(self.session_obj, self._to_json(details)))
|
|
189
|
+
|
|
190
|
+
def update_subaccount(self, details):
|
|
191
|
+
return Call(update_subaccount(self.session_obj, self._to_json(details)))
|
|
192
|
+
|
|
193
|
+
def get_subaccounts(self, details=None):
|
|
194
|
+
details = details or {}
|
|
195
|
+
return Call(get_subaccounts(self.session_obj, self._to_json(details)))
|
|
196
|
+
|
|
197
|
+
def get_subaccount(self, subaccount):
|
|
198
|
+
return Call(get_subaccount(self.session_obj, subaccount))
|
|
199
|
+
|
|
200
|
+
def get_transactions(self, details={'subaccount': 0, 'first': 0, 'count': 30}):
|
|
201
|
+
return Call(get_transactions(self.session_obj, self._to_json(details)))
|
|
202
|
+
|
|
203
|
+
def get_receive_address(self, details=None):
|
|
204
|
+
details = details or {}
|
|
205
|
+
return Call(get_receive_address(self.session_obj, self._to_json(details)))
|
|
206
|
+
|
|
207
|
+
def get_previous_addresses(self, details={'subaccount': 0, 'last_pointer': 0}):
|
|
208
|
+
return Call(get_previous_addresses(self.session_obj, self._to_json(details)))
|
|
209
|
+
|
|
210
|
+
def get_unspent_outputs(self, details={'subaccount': 0, 'num_confs': 1}):
|
|
211
|
+
return Call(get_unspent_outputs(self.session_obj, self._to_json(details)))
|
|
212
|
+
|
|
213
|
+
def get_unspent_outputs_for_private_key(self, details):
|
|
214
|
+
return Call(get_unspent_outputs_for_private_key(self.session_obj, self._to_json(details)))
|
|
215
|
+
|
|
216
|
+
def set_unspent_outputs_status(self, details):
|
|
217
|
+
return Call(set_unspent_outputs_status(self.session_obj, self._to_json(details)))
|
|
218
|
+
|
|
219
|
+
def get_transaction_details(self, txhash_hex):
|
|
220
|
+
return json.loads(get_transaction_details(self.session_obj, txhash_hex))
|
|
221
|
+
|
|
222
|
+
def convert_amount(self, details):
|
|
223
|
+
return json.loads(convert_amount(self.session_obj, self._to_json(details)))
|
|
224
|
+
|
|
225
|
+
def get_balance(self, details={'subaccount': 0, 'num_confs': 0}):
|
|
226
|
+
return Call(get_balance(self.session_obj, self._to_json(details)))
|
|
227
|
+
|
|
228
|
+
def get_available_currencies(self):
|
|
229
|
+
return json.loads(get_available_currencies(self.session_obj))
|
|
230
|
+
|
|
231
|
+
def create_transaction(self, transaction_details):
|
|
232
|
+
return Call(create_transaction(self.session_obj, self._to_json(transaction_details)))
|
|
233
|
+
|
|
234
|
+
def blind_transaction(self, transaction_details):
|
|
235
|
+
return Call(blind_transaction(self.session_obj, self._to_json(transaction_details)))
|
|
236
|
+
|
|
237
|
+
def sign_transaction(self, transaction_details):
|
|
238
|
+
return Call(sign_transaction(self.session_obj, self._to_json(transaction_details)))
|
|
239
|
+
|
|
240
|
+
def create_swap_transaction(self, swap_details):
|
|
241
|
+
return Call(create_swap_transaction(self.session_obj, self._to_json(swap_details)))
|
|
242
|
+
|
|
243
|
+
def complete_swap_transaction(self, swap_details):
|
|
244
|
+
return Call(complete_swap_transaction(self.session_obj, self._to_json(swap_details)))
|
|
245
|
+
|
|
246
|
+
def create_redeposit_transaction(self, redeposit_details):
|
|
247
|
+
return Call(create_redeposit_transaction(self.session_obj, self._to_json(redeposit_details)))
|
|
248
|
+
|
|
249
|
+
def psbt_sign(self, details):
|
|
250
|
+
return Call(psbt_sign(self.session_obj, self._to_json(details)))
|
|
251
|
+
|
|
252
|
+
def psbt_from_json(self, details):
|
|
253
|
+
return Call(psbt_from_json(self.session_obj, self._to_json(details)))
|
|
254
|
+
|
|
255
|
+
def psbt_get_details(self, details):
|
|
256
|
+
return Call(psbt_get_details(self.session_obj, self._to_json(details)))
|
|
257
|
+
|
|
258
|
+
def send_transaction(self, details):
|
|
259
|
+
return Call(send_transaction(self.session_obj, self._to_json(details)))
|
|
260
|
+
|
|
261
|
+
def broadcast_transaction(self, details):
|
|
262
|
+
return Call(broadcast_transaction(self.session_obj, self._to_json(details)))
|
|
263
|
+
|
|
264
|
+
def sign_message(self, details):
|
|
265
|
+
return Call(sign_message(self.session_obj, self._to_json(details)))
|
|
266
|
+
|
|
267
|
+
def send_nlocktimes(self):
|
|
268
|
+
return send_nlocktimes(self.session_obj)
|
|
269
|
+
|
|
270
|
+
def set_csvtime(self, locktime_details):
|
|
271
|
+
return Call(set_csvtime(self.session_obj, self._to_json(locktime_details)))
|
|
272
|
+
|
|
273
|
+
def set_nlocktime(self, locktime_details):
|
|
274
|
+
return Call(set_nlocktime(self.session_obj, self._to_json(locktime_details)))
|
|
275
|
+
|
|
276
|
+
def set_transaction_memo(self, txhash_hex, memo, memo_type=0):
|
|
277
|
+
return set_transaction_memo(self.session_obj, txhash_hex, memo, memo_type)
|
|
278
|
+
|
|
279
|
+
def get_fee_estimates(self):
|
|
280
|
+
return json.loads(get_fee_estimates(self.session_obj))
|
|
281
|
+
|
|
282
|
+
def get_credentials(self, details):
|
|
283
|
+
return Call(get_credentials(self.session_obj, self._to_json(details)))
|
|
284
|
+
|
|
285
|
+
def get_system_message(self):
|
|
286
|
+
return get_system_message(self.session_obj)
|
|
287
|
+
|
|
288
|
+
def ack_system_message(self, message_text):
|
|
289
|
+
return Call(ack_system_message(self.session_obj, message_text))
|
|
290
|
+
|
|
291
|
+
def cache_control(self, details):
|
|
292
|
+
return Call(cache_control(self.session_obj, self._to_json(details)))
|
|
293
|
+
|
|
294
|
+
def get_twofactor_config(self):
|
|
295
|
+
return json.loads(get_twofactor_config(self.session_obj))
|
|
296
|
+
|
|
297
|
+
def change_settings_twofactor(self, method, details):
|
|
298
|
+
return Call(change_settings_twofactor(self.session_obj, method, self._to_json(details)))
|
|
299
|
+
|
|
300
|
+
def get_settings(self):
|
|
301
|
+
return json.loads(get_settings(self.session_obj))
|
|
302
|
+
|
|
303
|
+
def change_settings(self, settings):
|
|
304
|
+
return Call(change_settings(self.session_obj, self._to_json(settings)))
|
|
305
|
+
|
|
306
|
+
def twofactor_reset(self, email, is_dispute):
|
|
307
|
+
return Call(twofactor_reset(self.session_obj, email, is_dispute))
|
|
308
|
+
|
|
309
|
+
def twofactor_undo_reset(self, email):
|
|
310
|
+
return Call(twofactor_undo_reset(self.session_obj, email))
|
|
311
|
+
|
|
312
|
+
def twofactor_cancel_reset(self):
|
|
313
|
+
return Call(twofactor_cancel_reset(self.session_obj))
|
|
314
|
+
|
|
315
|
+
def twofactor_change_limits(self, details):
|
|
316
|
+
return Call(twofactor_change_limits(self.session_obj, self._to_json(details)))
|
|
317
|
+
|
|
318
|
+
def bcur_encode(self, details):
|
|
319
|
+
return Call(bcur_encode(self.session_obj, self._to_json(details)))
|
|
320
|
+
|
|
321
|
+
def bcur_decode(self, details):
|
|
322
|
+
return Call(bcur_decode(self.session_obj, self._to_json(details)))
|
|
323
|
+
|
|
324
|
+
def http_request(self, params):
|
|
325
|
+
return json.loads(http_request(self.session_obj, self._to_json(params)))
|
|
326
|
+
|
|
327
|
+
def refresh_assets(self, params):
|
|
328
|
+
return refresh_assets(self.session_obj, self._to_json(params))
|
|
329
|
+
|
|
330
|
+
def get_assets(self, params):
|
|
331
|
+
return json.loads(get_assets(self.session_obj, self._to_json(params)))
|
|
332
|
+
|
|
333
|
+
def validate_asset_domain_name(self, params):
|
|
334
|
+
return json.loads(validate_asset_domain_name(self.session_obj, self._to_json(params)))
|
|
335
|
+
|
|
336
|
+
def validate(self, details):
|
|
337
|
+
return Call(validate(self.session_obj, self._to_json(details)))
|
|
338
|
+
|
|
339
|
+
_old_get_networks = get_networks
|
|
340
|
+
def get_networks():
|
|
341
|
+
return json.loads(_old_get_networks())
|
|
342
|
+
|
|
343
|
+
_old_register_network = register_network
|
|
344
|
+
def register_network(name, details):
|
|
345
|
+
return _old_register_network(name, Session._to_json(details))
|
|
346
|
+
|
|
347
|
+
_old_get_random_bytes = get_random_bytes
|
|
348
|
+
def get_random_bytes(n):
|
|
349
|
+
out = bytearray(n)
|
|
350
|
+
_old_get_random_bytes(n, out)
|
|
351
|
+
return bytes(out)
|
|
352
|
+
|
|
353
|
+
_old_init = init
|
|
354
|
+
def init(config):
|
|
355
|
+
import os, os.path
|
|
356
|
+
if not config.get('datadir', None):
|
|
357
|
+
try:
|
|
358
|
+
datadir = os.path.join(os.path.expanduser('~'), '.blockstream', 'gdk')
|
|
359
|
+
os.makedirs(os.path.join(datadir, 'assets'), exist_ok = True);
|
|
360
|
+
config['datadir'] = datadir
|
|
361
|
+
except:
|
|
362
|
+
pass
|
|
363
|
+
return _old_init(json.dumps(config))
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: green_gdk
|
|
3
|
+
Version: 0.76.2
|
|
4
|
+
Summary: Blockstream Green Development Kit
|
|
5
|
+
Author-email: Blockstream <inquiries@blockstream.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: repository, https://github.com/blockstream/gdk
|
|
8
|
+
Project-URL: documentation, https://gdk.readthedocs.io/en/release_0.76.2
|
|
9
|
+
Project-URL: tracker, https://github.com/blockstream/gdk/issues
|
|
10
|
+
Keywords: Bitcoin,wallet,library,BIP32,BIP38,BIP39,secp256k1
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
Python bindings for the gdk Bitcoin library
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
green_gdk/__init__.py,sha256=wl-8MzXTiGDXNzMv3ikLRe35BVa4kIfXuK2UNDi-2Po,13491
|
|
2
|
+
green_gdk/_green_gdk.cpython-39-darwin.so,sha256=dhXELXGIxwLRT31EJYxvomGuR54COWmaFwEbOMufvLM,31783680
|
|
3
|
+
green_gdk-0.76.2.dist-info/METADATA,sha256=MxGqWLQdshho_RLO6NlFUGLYcg2VSl3RMEd7YqoqxjY,873
|
|
4
|
+
green_gdk-0.76.2.dist-info/WHEEL,sha256=W6aqWzD645lPkqyDFbWDKgP9RPQ-7VqxbSavwr5v_sY,108
|
|
5
|
+
green_gdk-0.76.2.dist-info/top_level.txt,sha256=Xe5CQrUkf885laA8xvVS_nRODRHCp0I-wvO3ueN3H2I,10
|
|
6
|
+
green_gdk-0.76.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
green_gdk
|