forked from decred/tinydecred
-
Notifications
You must be signed in to change notification settings - Fork 1
/
api.py
355 lines (316 loc) · 10.4 KB
/
api.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
"""
Copyright (c) 2019, Brian Stafford
See LICENSE for details
This module defines an API used by the wallet and implemented by each asset and
node type.
"""
class Unimplemented(Exception):
""" Unimplemented method. """
pass
class InsufficientFundsError(Exception):
"""Available account balance to low for requested funds."""
pass
class UTXO:
"""
Blockchain-implementing classes must know how to create and handle utxo
objects.
"""
def __init__(self, address, txid, vout):
"""
Args:
address (str): Base-58 encoded address string.
txid (str): Transaction ID.
vout (int): The transaction output index that this UTXO represents.
"""
self.address = address
self.txid = txid
self.vout = vout
def __tojson__(self):
"""
UTXO must be json-encodable and registered with the tinyjson module.
"""
raise Unimplemented("__tojson__ not implemented")
@staticmethod
def __fromjson__(obj):
"""
Decode the UTXO from the json encoding as returned by __tojson__
"""
raise Unimplemented("__fromjson__ not implemented")
def isSpendable(self, tipHeight):
"""
Determine whether this UTXO is currently spendable.
Args:
tipHeight (int): The height of the best block.
"""
raise Unimplemented("isSpendable not implemented")
def key(self):
"""
Return a key that is unique to this UTXO.
Returns:
str: A unique ID for this UTXO.
"""
raise Unimplemented("key not implemented")
@staticmethod
def makeKey(txid, vout):
return txid + "#" + str(vout)
class Blockchain:
"""
The Blockchain class defines an API to be implemented for each supported
asset.
"""
def __init__(self, db, params):
"""
Args:
db (KeyValueDatabase): A key-value database for storing blocks
and transactions.
params obj: Network parameters.
"""
self.db = db
self.params = params
# The blockReceiver and addressReceiver will be set when the respective
# subscribe* method is called.
self.blockReceiver = None
self.addressReceiver = None
def subscribeBlocks(self, receiver):
"""
Subscribe to new block notifications.
Args:
receiver (func(obj)): A function or method that accepts the block
notifications.
"""
raise Unimplemented("subscribeBlocks not implemented")
def subscribeAddresses(self, addrs, receiver):
"""
Subscribe to notifications for the provided addresses.
Args:
addrs (list(str)): List of base-58 encoded addresses.
receiver (func(obj)): A function or method that accepts the address
notifications.
"""
raise Unimplemented("subscribeAddresses not implemented")
def UTXOs(self, addrs):
"""
UTXOs will produce any known UTXOs for the list of addresses.
Args:
addrs (list(str)): List of base-58 encoded addresses.
"""
raise Unimplemented("UTXOs not implemented")
def tx(self, txid):
"""
tx will produce a transaction object which implements the Transaction
API.
Args:
txid (str): Hex-encoded transaction ID.
Returns:
Transaction: A transction object which implements the Transaction
API
"""
raise Unimplemented("tx not implemented")
def blockHeader(self, bHash):
"""
blockHeader will produce a blockHeader implements the BlockHeader API.
Args:
bHash (str): The block hash of the block header.
Returns:
BlockHeader: An object which implements the BlockHeader API.
"""
raise Unimplemented("blockHeader not implemented")
def blockHeaderByHeight(self, height):
"""
The blockHeader for the best block at the provided height.
Args:
height (int): The height of the block header.
Returns:
BlockHeader: An object which implements the BlockHeader API.
"""
raise Unimplemented("blockHeaderByHeight not implemented")
def bestBlock(self):
"""
bestBlock will produce a decoded block as a Python dict.
"""
raise Unimplemented("bestBlock not implemented")
def sendToAddress(self, value, address, feeRate=None):
"""
Send the amount in atoms to the specified address.
Args:
value int: The amount to send, in atoms.
address str: The base-58 encoded address.
feeRate float: The reeRate (atoms/byte) to pay. (optional. will have a default value per-blockchain)
Returns:
Transaction: The newly created transaction.
list(UTXO): The spent UTXOs.
list(UTXO): Any newly generated UTXOs, such as change.
"""
raise Unimplemented("sendToAddress not implemented")
class BlockHeader:
"""
BlockHeader defines an API that must be implemented within Blockchain for
block header objects.
"""
def __init__(self, height, timestamp):
self.height = height
self.timestamp = timestamp
@staticmethod
def deserialize(b):
"""
De-serialize the bytes into a BlockHeader.
Args:
b (ByteArray): A serialized block header.
"""
raise Unimplemented("deserialize not implemented")
def serialize(self):
"""
Serialize the BlockHeader into a ByteArray.
Returns:
ByteArray: The serialized block header.
"""
raise Unimplemented("serialize not implemented")
def blockHash(self):
"""
A hash of the serialized block.
Returns:
ByteArray: Hash of the serialized block header.
"""
raise Unimplemented("blockHash not implemented")
def id(self):
"""
A string ID of the block, usually an encoding of the blockHash.
Returns:
str: A block ID.
"""
raise Unimplemented("id not implemented")
class Transaction:
"""
Transaction defines an API that must be implemented within Blockchain for
transaction objects.
"""
def __eq__(self, tx):
"""
Check equality of this transaction with another.
Args:
tx (Transaction): Another object, presumably of the same class.
"""
raise Unimplemented("__eq__ not implemented")
def txHash(self):
"""
A hash of the serialized transaction.
Returns:
ByteArray: The hashed transaction.
"""
raise Unimplemented("txHash not implemented")
def txid(self):
"""
A transaction ID. Typically a string encoding of the txHash.
Returns:
str: The transaction id.
"""
raise Unimplemented("txid not implemented")
def serialize(self):
"""
Serialize the transaction into bytes according to it's network protocol.
Returns:
ByteArray: The serialized transaction.
"""
raise Unimplemented("serialize not implemented")
@staticmethod
def deserialize(b):
"""
Create a Transaction-implementing object from a serialized transaction,
such as that produced by serialize.
"""
raise Unimplemented("deserialize not implemented")
class Balance:
"""
Balance defines an API for balance information.
"""
def __init__(self, total=0, available=0):
# The total is the sum of all transactions.
self.total = total
# The available is the amount available to spend immediately.
self.available = available
def __tojson__(self):
"""
Balance must be json-encodable and registered with the tinyjson module.
"""
raise Unimplemented("__tojson__ not implemented")
@staticmethod
def __fromjson__(obj):
"""
Decode the Balance from the json encoding as returned by __tojson__
"""
raise Unimplemented("__fromjson__ not implemented")
class Signals:
"""
Signals defines an API for receiving asynchronous updates from a wallet
or Blockchain.
"""
def balance(self, balance):
"""
A receiver for balance updates.
Args:
balance (Balance): The updated balance.
"""
raise Unimplemented("Signals not implemented")
class PublicKey:
"""
A public key structure.
"""
def __init__(self, curve, x, y):
"""
Args:
curve (ECDSACurve): The ECDSA curve.
x (int): The x coordinate.
y (int): The y coordinate.
"""
self.curve = curve
self.x = x
self.y = y
def serializeCompressed(self):
"""
Compressed form of the private key serialization.
Returns:
ByteArray: Compressed public key.
"""
raise Unimplemented("serializeCompressed not implemented")
def serializeUncompressed(self):
"""
Uncompressed form of the public key serialization.
Returns:
ByteArray: Uncompressed public key
"""
raise Unimplemented("serializeUncompressed not implemented")
class PrivateKey:
"""
A private key structure. The associated public key information is stored
as an attribute.
"""
def __init__(self, curve, k, x, y):
"""
Args:
curve (ECDSACurve): The ECDSA curve.
k (ByteArray): The private key.
x (int): The x coordinate.
y (int): The y coordinate.
"""
self.key = k
self.pub = PublicKey(curve, x, y)
class KeySource:
"""
KeySource defines an API for retrieving `PrivateKey`s and change addresses.
"""
def priv(self, addr):
"""
Retreive the private key for a base-58 encoded address.
Args:
addr (str): An address.
Returns:
PrivateKey: Private key.
"""
raise Unimplemented("KeySource not implemented")
def change(self):
"""
Get a new change address.
Returns:
str: A new base-58 encoded change address.
"""
raise Unimplemented("change not implemented")