@@ -6,6 +6,10 @@ walkthrough examples of this section, you will be a master of PyOTA.
6
6
In each section below, a code snippet will be shown and discussed in detail
7
7
to help you understand how to carry out specific tasks with PyOTA.
8
8
9
+ The example scripts displayed here can also be found under ``examples/tutorials/ ``
10
+ directory in the repository. Run them in a Python environment that has PyOTA
11
+ installed. See :ref: `Install PyOTA ` for more info.
12
+
9
13
If you feel that something is missing or not clear, please post your questions
10
14
and suggestions in the `PyOTA Bug Tracker `_.
11
15
@@ -228,7 +232,282 @@ method to drop values we can't decode using ``utf-8``, or if the raw trytes
228
232
can't be decoded into legit bytes. A possible reason for the latter can be if
229
233
the attribute contains a signature rather than a message.
230
234
235
+ 4.a Generate Address
236
+ --------------------
237
+
238
+ In this example, you will learn how to:
239
+
240
+ - **Generate a random seed. **
241
+ - **Generate an IOTA address that belongs to your seed. **
242
+ - **Acquire free devnet IOTA tokens that you can use to play around with. **
243
+
244
+ Code
245
+ ~~~~
246
+ .. literalinclude :: ../examples/tutorials/04a_gen_address.py
247
+ :linenos:
248
+
249
+ Discussion
250
+ ~~~~~~~~~~
251
+ .. literalinclude :: ../examples/tutorials/04a_gen_address.py
252
+ :lines: 1-7
253
+ :lineno-start: 1
254
+
255
+ We start off by generating a random seed with the help of the library. You are
256
+ also free to use your own seed, just uncomment line 6 and put it there.
257
+
258
+ If you choose to generate one, your seed is written to the console so that you
259
+ can save it for later. Be prepared to do so, because you will have to use it
260
+ in the following tutorials.
261
+
262
+ .. literalinclude :: ../examples/tutorials/04a_gen_address.py
263
+ :lines: 9-14
264
+ :lineno-start: 9
265
+
266
+ Notice, how we pass the ``seed `` argument to the API class's init method.
267
+ Whenever the API needs to work with addresses or private keys, it will derive
268
+ them from this seed.
269
+
270
+ .. important ::
271
+
272
+ Your seed never leaves the library and your computer. Treat your (mainnet)
273
+ seed like any other password for a financial service: safe. If your seed is
274
+ compromised, attackers can steal your funds.
275
+
276
+ .. literalinclude :: ../examples/tutorials/04a_gen_address.py
277
+ :lines: 16-20
278
+ :lineno-start: 16
279
+
280
+ To generate a new address, we call :py:meth: `~Iota.get_new_addresses `
281
+ extended API method. Without arguments, this will return a ``dict `` with the
282
+ first unused address starting from ``index `` 0. An unused address is address
283
+ that has no transactions referencing it on the Tangle and was never spent from.
284
+
285
+ If we were to generate more addresses starting from a desired index,
286
+ we could specify the ``start `` and ``count `` parameters. Read more about how to
287
+ generate addresses in PyOTA at :ref: `Generating Addresses `.
288
+
289
+ On line 20 we access the first element of the list of addresses in the response
290
+ dictionary.
291
+
292
+ .. literalinclude :: ../examples/tutorials/04a_gen_address.py
293
+ :lines: 22-23
294
+ :lineno-start: 22
295
+
296
+ Lastly, the address is printed to the console, so that you can copy it.
297
+ Visit https://faucet.devnet.iota.org/ and enter the address to receive free
298
+ devnet tokens of 1000i.
299
+
300
+ You might need to wait 1-2 minutes until the sum arrives to you address. To
301
+ check your balance, go to `4.b Check Balance `_ or `4.c Get Account Data `_.
302
+
303
+ 4.b Check Balance
304
+ -----------------
305
+
306
+ In this example, you will learn how to:
307
+
308
+ - **Check the balance of a specific IOTA address. **
309
+
310
+ Code
311
+ ~~~~
312
+ .. literalinclude :: ../examples/tutorials/04b_check_balance.py
313
+ :linenos:
314
+
315
+ Discussion
316
+ ~~~~~~~~~~
317
+ .. literalinclude :: ../examples/tutorials/04b_check_balance.py
318
+ :lines: 1-8
319
+ :lineno-start: 1
320
+
321
+ The first step to check the balance of an address is to actually have an
322
+ address. Exchange the sample address on line 5 with your generated address from
323
+ `4.a Generate Address `_.
324
+
325
+ Since we don't need to generate an address, there is no need for a seed to be
326
+ employed in the API object. Note the ``time `` import, we need it for later.
327
+
328
+ .. literalinclude :: ../examples/tutorials/04b_check_balance.py
329
+ :lines: 10-25
330
+ :lineno-start: 10
331
+
332
+ Our script will poll the network for the address balance as long as the returned
333
+ balance is zero. Therefore, the address you declared as ``my_address `` should
334
+ have some balance. If you see the ``Zero balance found... `` message a couple of
335
+ times, head over to https://faucet.devnet.iota.org/ and load up your address.
336
+
337
+ :py:meth: `~Iota.get_balances ` returns the confirmed balance of the address.
338
+ You could supply multiple addresses at the same time and get their respective
339
+ balances in a single call. Don't forget, that the method returns a ``dict ``.
340
+ More details about it can be found at :py:meth: `~Iota.get_balances `.
341
+
342
+ 4.c Get Account Data
343
+ --------------------
344
+
345
+ In this example, you will learn how to:
346
+
347
+ - **Gather addresses, balance and bundles associated with your seed on the Tangle. **
348
+
349
+ .. warning ::
350
+
351
+ **Account ** in the context of this example is not to be confused with the
352
+ `Account Module `_, that is a feature yet to be implemented in PyOTA.
353
+
354
+ **Account ** here simply means the addresses and funds that belong to your
355
+ seed.
356
+
357
+ Code
358
+ ~~~~
359
+ .. literalinclude :: ../examples/tutorials/04c_get_acc_data.py
360
+ :linenos:
361
+
362
+ Discussion
363
+ ~~~~~~~~~~
364
+ .. literalinclude :: ../examples/tutorials/04c_get_acc_data.py
365
+ :lines: 1-3
366
+ :lineno-start: 1
367
+
368
+ We will need ``pprint `` for a prettified output of the response ``dict `` and
369
+ ``time `` for polling until we find non-zero balance.
370
+
371
+ .. literalinclude :: ../examples/tutorials/04c_get_acc_data.py
372
+ :lines: 5-13
373
+ :lineno-start: 5
374
+
375
+ Copy your seed from `4.a Generate Address `_ onto line 6. The API will use your
376
+ seed to generate addresses and look for corresponding transactions on the
377
+ Tangle.
378
+
379
+ .. literalinclude :: ../examples/tutorials/04c_get_acc_data.py
380
+ :lines: 15-30
381
+ :lineno-start: 15
382
+
383
+ Just like in the prevoius example, we will poll for information until we find
384
+ a non-zero balance. :py:meth: `~Iota.get_account_data ` without arguments
385
+ generates addresses from ``index `` 0 until it finds the first unused. Then, it
386
+ queries the node about bundles of those addresses and sums up their balance.
387
+
388
+ .. note ::
389
+
390
+ If you read :py:meth: `~Iota.get_account_data ` documentation carefully, you
391
+ notice that you can gain control over which addresses are checked during
392
+ the call by specifying the ``start `` and ``stop `` index parameters.
393
+
394
+ This can be useful when your addresses with funds do not follow each other
395
+ in the address namespace, or a snapshot removed transactions from the
396
+ Tangle. It is recommended that you keep a local database of your already
397
+ used address indices.
398
+
399
+ Once implemented in PyOTA, `Account Module `_ will address the aforementioned
400
+ problems.
401
+
402
+ The response ``dict `` contains the addresses, bundles and total balance of
403
+ your seed.
404
+
405
+ 5. Send Tokens
406
+ --------------
407
+
408
+ In this example, you will learn how to:
409
+
410
+ - **Construct a value transfer with PyOTA. **
411
+ - **Send a value transfer to an arbitrary IOTA address. **
412
+ - **Analyze a bundle of transactions on the Tangle. **
413
+
414
+ .. note ::
415
+
416
+ As a prerequisite to this tutorial, you need to have completed
417
+ `4.a Generate Address `_, and have a seed that owns devnet tokens.
418
+
419
+ Code
420
+ ~~~~
421
+ .. literalinclude :: ../examples/tutorials/05_send_tokens.py
422
+ :linenos:
423
+
424
+ Discussion
425
+ ~~~~~~~~~~
426
+ .. literalinclude :: ../examples/tutorials/05_send_tokens.py
427
+ :lines: 1-11
428
+ :lineno-start: 1
429
+
430
+ We are going to send a value transaction, that requires us to prove that we
431
+ own the address containg the funds to spend. Therefore, we need our seed from
432
+ which the address was generated.
433
+
434
+ Put your seed from `4.a Generate Address `_ onto line 4. We pass this seed to
435
+ the API object, that will utilize it for signing the transfer.
436
+
437
+ .. literalinclude :: ../examples/tutorials/05_send_tokens.py
438
+ :lines: 13-16
439
+ :lineno-start: 13
440
+
441
+ In IOTA, funds move accross addresses, therefore we need to define a **receiver
442
+ address **. For testing value transfers, you should send the funds only to
443
+ addresses that you control; if you use a randomly-generated receiver address,
444
+ you won't be able to recover the funds afterward!
445
+ Re-run `4.a Generate Address `_ for a new seed and a new address, or just paste
446
+ a valid IOTA address that you own onto line 16.
447
+
448
+ .. literalinclude :: ../examples/tutorials/05_send_tokens.py
449
+ :lines: 18-25
450
+ :lineno-start: 18
451
+
452
+ We declare a :py:class: `ProposedTransaction ` object like we did before, but
453
+ this time, with ``value=1 `` parameter. The smallest value you can send is 1
454
+ iota ("1i"), there is no way to break it into smaller chunks. It is a really small
455
+ value anyway. You can also attach a message to the transaction, for example a
456
+ little note to the beneficiary of the payment.
457
+
458
+ .. literalinclude :: ../examples/tutorials/05_send_tokens.py
459
+ :lines: 27-29
460
+ :lineno-start: 27
461
+
462
+ To actually send the transfer, all you need to do is call
463
+ :py:meth: `~Iota.send_transfer ` extended API method. This method will take care
464
+ of:
465
+
466
+ - Gathering ``inputs `` (addresses you own and have funds) to fund the 1i transfer.
467
+ - Generating a new ``change_address ``, and automatically sending the remaining
468
+ funds (``balance of chosen inputs `` - 1i) from ``inputs `` to ``change_address ``.
469
+
470
+ .. warning ::
471
+
472
+ This step is extremely important, as it prevents you from `spending twice
473
+ from the same address `_.
474
+
475
+ When an address is used as an input, all tokens will be withdrawn. Part
476
+ of the tokens will be used to fund your transaction, the rest will be
477
+ transferred to ``change_address ``.
478
+
479
+ - Constructing the transfer bundle with necessary input and output transactions.
480
+ - Finalizing the bundle and signing the spending transactions.
481
+ - Doing proof-of-work for each transaction in the bundle and sending it to the
482
+ network.
483
+
484
+ .. literalinclude :: ../examples/tutorials/05_send_tokens.py
485
+ :lines: 31-32
486
+ :lineno-start: 31
487
+
488
+ Open the link and observe the bundle you have just sent to the Tangle. Probably
489
+ it will take a couple of seconds for the network to confirm it.
490
+
491
+ What you see is a bundle with 4 transactions in total, 1 input and 3 outputs.
492
+ But why are there so many transactions?
493
+
494
+ - There is one transaction that withdraws iotas, this has negative value.
495
+ To authorize this spending, a valid signature is included in the transaction's
496
+ ``signature_message_fragment `` field. The signature however is too long to
497
+ fit into one transaction, therefore the library appends a new, zero-value
498
+ transaction to the bundle that holds the second part of the signature. This
499
+ you see on the output side of the bundle.
500
+ - A 1i transaction to the receiver address spends part of the withdrawn amount.
501
+ - The rest is transfered to ``change_address `` in a new output transaction.
502
+
503
+ Once the bundle is confirmed, try rerunning the script from
504
+ `4.c Get Account Data `_ with the same seed as in this tutorial. Your balance
505
+ should be decremented by 1i, and you should see a new address, which was
506
+ actually the ``change_address ``.
507
+
231
508
.. _PyOTA Bug Tracker : https://github.com/iotaledger/iota.py/issues
232
509
.. _bytestring : https://docs.python.org/3/library/stdtypes.html#bytes
233
510
.. _tryte alphabet : https://docs.iota.org/docs/getting-started/0.1/introduction/ternary#tryte-encoding
234
- .. _Tangle Explorer : https://utils.iota.org
511
+ .. _Tangle Explorer : https://utils.iota.org
512
+ .. _Account Module : https://docs.iota.org/docs/client-libraries/0.1/account-module/introduction/overview
513
+ .. _spending twice from the same address : https://docs.iota.org/docs/getting-started/0.1/clients/addresses#spent-addresses
0 commit comments