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))
@@ -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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp39-cp39-macosx_15_0_arm64
5
+
@@ -0,0 +1 @@
1
+ green_gdk