hackbyte

send_stellar_asset.py

Jun 18th, 2021 (edited)
940
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.95 KB | None | 0 0
  1. #!/usr/bin/env python3.6
  2. # -*- coding: utf-8 -*-
  3. ################################################################################
  4. #
  5. ## send_stellar_asset.py v2021-06-18T20:12 prerelease or fu, hackbyte ([email protected])
  6. #
  7. # python send stellar asset stuff, barely working 20210618T201924
  8. # python send stellar asset stuff, finally working 20210620T163500
  9. # v20210622T131630 added options "--mainnet" and "--testnet", now mandatory, for reasons. ;)
  10. #
  11. # usage: send_stellar_asset.py [-h] [-d] [--testnet] [--mainnet]
  12. #                              [--secret SECRET] [--asset ASSET]
  13. #                              [--issuer ISSUER] [--amount AMOUNT]
  14. #                              [--destination DESTINATION] [--memo MEMO]
  15. #
  16. # send_stellar_asset.py commandline parameters.
  17. #
  18. # optional arguments:
  19. #   -h, --help            show this help message and exit
  20. #   -d, --debug           show heavy masses(!!) of debug output.
  21. #   --testnet             Enable TESTNET operation.
  22. #   --mainnet             Enable MAINNET operation.
  23. #   --secret SECRET       Secret to use
  24. #   --asset ASSET         Asset Code
  25. #   --issuer ISSUER       Issuer account id
  26. #   --amount AMOUNT       Amount to send
  27. #   --destination DESTINATION
  28. #                         Destination account id
  29. #   --memo MEMO           Memo
  30. #
  31. #
  32. # Documentation:
  33. #
  34. # --mainnet Use mainnet to create a real payment.
  35. #
  36. # --testnet Use testnet for testnet purposes.
  37. #
  38. # --secret the secret to use to sign transactions (probably your distribution account ;))
  39. #
  40. # --asset Asset code of the asset you want to sent.
  41. #
  42. # --issuer Issuer ID of the asset you want to sent.
  43. #
  44. # --amount Amount of asset you want to send.
  45. #
  46. # --destination The destination wallet you want to send to.
  47. #
  48. # --memo Memo to add to the transaction.
  49. #
  50.  
  51. ################################################################################
  52. import os, sys, inspect
  53. ################################################################################
  54. # barebone system stuff
  55. scriptpath  = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
  56. scriptname  = os.path.basename(inspect.getfile(inspect.currentframe()))
  57. if 'include' == os.path.basename(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))):
  58.     scriptpath = os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
  59. else:
  60.     scriptpath  = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
  61. includepath = scriptpath + '/include'
  62. if os.path.isdir(includepath):
  63.     sys.path.insert(0, includepath)
  64. ################################################################################
  65. import shutil, time, datetime, locale, logging, logging.handlers, argparse
  66. from pudb import set_trace
  67. ################################################################################
  68. log = logging.getLogger()
  69. log.setLevel(logging.INFO)
  70. logformatter_main = logging.Formatter(
  71.     '%(asctime)s.%(msecs)03d ' +
  72.     '%(levelname)-8s ' + '%(filename)-16s ' +
  73.     '%(funcName)-12s ' + '%(lineno)04d ' +
  74.     '%(message)s',
  75.     '%Y%m%d%H%M%S')
  76. logformatter_syslog = logging.Formatter(
  77.     '%(levelname)-8s ' +
  78.     '%(filename)-16s ' + '%(funcName)-12s ' +
  79.     '%(lineno)04d ' + '%(message)s')
  80. logcons = logging.StreamHandler()
  81. logcons.setLevel(logging.DEBUG)
  82. logcons.setFormatter(logformatter_main)
  83. log.addHandler(logcons)
  84.  
  85. #logfile = logging.FileHandler(scriptpath+'/'+scriptname+'.log')
  86. #logfile.setLevel(logging.DEBUG)
  87. #logfile.setFormatter(logformatter_main)
  88. #log.addHandler(logfile)
  89.  
  90. #logsys = logging.handlers.SysLogHandler(address = '/dev/log')
  91. #logsys.setLevel(logging.INFO)
  92. #logsys.setFormatter(logformatter_syslog)
  93. #log.addHandler(logsys)
  94.  
  95. ################################################################################
  96. from stellar_sdk.asset import Asset
  97. from stellar_sdk.keypair import Keypair
  98. from stellar_sdk.network import Network
  99. from stellar_sdk.server import Server
  100. from stellar_sdk.transaction_builder import TransactionBuilder
  101. from stellar_sdk.exceptions import NotFoundError, BadResponseError, BadRequestError
  102. ################################################################################
  103.  
  104. parser = argparse.ArgumentParser(description=scriptname + ' commandline parameters.')
  105.  
  106. parser.add_argument(
  107.     "-d", "--debug", dest="debug",
  108.     action="store_true", default=False,
  109.     help="show heavy masses(!!) of debug output.")
  110.  
  111. parser.add_argument(
  112.     "--testnet", dest="testnet",
  113.     action="store_true", default=False,
  114.     help="Enable TESTNET operation.")
  115.  
  116. parser.add_argument(
  117.     "--mainnet", dest="mainnet",
  118.     action="store_true", default=False,
  119.     help="Enable MAINNET operation.")
  120.  
  121. parser.add_argument(
  122.     "--secret", dest="secret",
  123.     action="store", default="NONE",
  124.     metavar="SECRET", help="Secret to use")
  125.  
  126. parser.add_argument(
  127.     "--asset", dest="asset",
  128.     action="store", default="NONE",
  129.     metavar="ASSET", help="Asset Code")
  130.  
  131. parser.add_argument(
  132.     "--issuer", dest="issuer",
  133.     action="store", default="NONE",
  134.     metavar="ISSUER", help="Issuer account id")
  135.  
  136. parser.add_argument(
  137.     "--amount", dest="amount",
  138.     action="store", default="NONE",
  139.     metavar="AMOUNT", help="Amount to send")
  140.  
  141. parser.add_argument(
  142.     "--destination", dest="destination",
  143.     action="store", default="NONE",
  144.     metavar="DESTINATION", help="Destination account id")
  145.  
  146. parser.add_argument(
  147.     "--memo", dest="memo",
  148.     action="store", default="NONE",
  149.     metavar="MEMO", help="Memo")
  150.  
  151. cmdline = parser.parse_args()
  152.  
  153. ################################################################################
  154. if cmdline.debug:
  155.     log.setLevel(logging.DEBUG)
  156. ################################################################################
  157. log.debug("python version "        + str(sys.version).replace('\n', ''))
  158. log.debug(scriptname+" START "     + '{:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now()))
  159. log.debug("cmdline.debug = "       + str(cmdline.debug))
  160. ################################################################################
  161.  
  162. if cmdline.testnet == False and cmdline.mainnet == False:
  163.     print("No --testnet or --mainnet option given, you need to specify the network.")
  164.     sys.exit(1)
  165.  
  166. if cmdline.testnet == True and cmdline.mainnet == True:
  167.     print("--testnet AND --mainnet option given, cannot work on both.")
  168.     sys.exit(1)
  169.  
  170. if cmdline.secret == 'NONE':
  171.     print("Error, no secret given!")
  172.     sys.exit(42)
  173.  
  174. if cmdline.asset == 'NONE':
  175.     print("Error, no asset given!")
  176.     sys.exit(42)
  177.  
  178. if cmdline.issuer == 'NONE':
  179.     print("Error, no issuer given!")
  180.     sys.exit(42)
  181.  
  182. if cmdline.amount == 'NONE':
  183.     print("Error, no amount given!")
  184.     sys.exit(42)
  185.  
  186. if cmdline.destination == 'NONE':
  187.     print("Error, no destination given!")
  188.     sys.exit(42)
  189.  
  190. ##testnet server
  191. if cmdline.testnet == True:
  192.     server = Server("https://horizon-testnet.stellar.org")
  193.     log.info( "Used Server TESTNET       : " + str(server.horizon_url))
  194.  
  195. ##mainnet server
  196. if cmdline.mainnet == True:
  197.     server = Server("https://horizon.stellar.org")
  198.     log.info( "Used Server MAINNET       : " + str(server.horizon_url))
  199.  
  200. distribution_source_key = Keypair.from_secret(cmdline.secret)
  201.  
  202. log.info( "Used Secret:              : " + cmdline.secret)
  203. log.info( "Used asset:               : " + cmdline.asset)
  204. log.info( "Used Issuer:              : " + cmdline.issuer)
  205. log.info( "Used amount:              : " + cmdline.amount)
  206. log.info( "Used Destination          : " + cmdline.destination)
  207. log.debug("distribution source public: " + distribution_source_key.public_key)
  208. log.debug("distribution source secret: " + distribution_source_key.secret)
  209.  
  210. ################################################################################
  211. ################################################################################
  212.  
  213. ### # Create an object to represent the new asset
  214. our_asset = Asset(str(cmdline.asset), str(cmdline.issuer) )
  215.  
  216. log.info("our asset: '" + str(our_asset) + "'")
  217.  
  218. # First, check to make sure that the destination account exists.
  219. # You could skip this, but if the account does not exist, you will be charged
  220. # the transaction fee when the transaction fails.
  221. try:
  222.     log.debug("trying 'server.load_account(cmdline.destination)'")
  223.     server.load_account(cmdline.destination)
  224. except NotFoundError:
  225.     # If the account is not found, surface an error message for logging.
  226.     raise Exception("The destination account does not exist!")
  227.  
  228. # If there was no error, load up-to-date information on your account.
  229. distribution_source_account = server.load_account(distribution_source_key.public_key)
  230.  
  231. # Let's fetch base_fee from network
  232. base_fee = server.fetch_base_fee()
  233.  
  234. # Start building the transaction.
  235.  
  236.  
  237. ##testnet server
  238. if cmdline.testnet == True:
  239.     our_network_passphrase=Network.TESTNET_NETWORK_PASSPHRASE
  240.  
  241. ##mainnet server
  242. if cmdline.mainnet == True:
  243.     our_network_passphrase=Network.PUBLIC_NETWORK_PASSPHRASE
  244.  
  245.  
  246. transaction = (
  247.     TransactionBuilder(
  248.         source_account=distribution_source_account,
  249.         network_passphrase=our_network_passphrase,
  250.         base_fee=base_fee,
  251.     )
  252.         .append_payment_op(
  253.             destination=str(cmdline.destination),
  254.             amount=str(cmdline.amount),
  255.             asset_code=our_asset.code,
  256.             asset_issuer=our_asset.issuer
  257.         )
  258.         .add_text_memo(str(cmdline.memo))
  259.  
  260.         # Wait a maximum of three minutes for the transaction
  261.         .set_timeout(10)
  262.         .build()
  263. )
  264.  
  265. # Sign the transaction to prove you are actually the person sending it.
  266. log.debug("SIGNING TRANSACTION WITH: distribution_source_key.secret " + str(distribution_source_key.secret))
  267.  
  268. transaction.sign(distribution_source_key.secret)
  269.  
  270. try:
  271.     # And finally, send it off to Stellar!
  272.     response = server.submit_transaction(transaction)
  273.     print(f"Response: {response}")
  274. except (BadRequestError, BadResponseError) as err:
  275.     print(f"Something went wrong!\n{err}")
  276.  
  277.  
  278. log.debug("program end...")
  279.  
  280. sys.exit()
  281.  
Advertisement
Add Comment
Please, Sign In to add comment