SteemHub: Automated Token Emission

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@oaldamster·
0.000 HBD
SteemHub: Automated Token Emission
# Python3 version 0.0.0.1-beta by Oaldamster
_Forked from Steem Engine Airdrop Tool {[seairdrop](https://github.com/themarkymark-steem/seairdrop)} by [The Marky Mark](https://steemit.com/@themarkymark)._ 

## Load with Config and Airdrop file  
**Creating a Token on [Steem-Engine dot com](https://steem-engine.com) can be one thing, spreading the love is another. Thanks to a few fellow Steemians though, [The Marky Mark](https://steemit.com/@themarkymark) and [Holger80](https://steemit.com/@holger80), it now has become as easy as _Py(thon 3)_. This forked version, ATE, of the original go.py file can also load a separate config file, together with the airdrop file. Instead of _go.py_ it could be named _gogo.py_.** 

## About ATE  (Sounds like Aid) 
Easy emission of  any Token on Steem-Engine dot com in an airdrop alike fashion, using [the Beem Python Module](https://github.com/holgern/beem) and [Python3](https://www.python.org/downloads/) on Linux. This version adds user defined loading of Config.JSON in combination with an Airdrop.dat file. 

### Supported methods:

   * Transfer
   * Issue
   * Stake 

### Required: 

* Python3 :: https://www.python.org/downloads/
* Beem Python Module :: https://github.com/holgern/beem 

* Original version :: https://github.com/themarkymark-steem/seairdrop

### How to use 
**It is best to use Beem(PY) to first create a (Key-)Wallet. Only to store a Post and an Active key in there. Then secure it with a password. That will be used to unlock the (Key-)Wallet, instead of using the Post and or Active key. The Beem Python Module has all kinds of easy to use commands. And in $BASH (command-line) it is even easier to use beempy to create a (Key-)Wallet. (Use "beempy --help" first.)** 

After all the needed setups, create a _config.json_ file that has all the settings for a Token emission. First try a so called '_Dry-Run_' by setting _"dry_run" : true_. It all goes well, change it to _false_ and it goes live. Then create an _airdrop.dat_ file in a CSV {Comma Seperated Values} fashion. In there put the name of the Steem account first, then a comma and after that the amount to send. (See the example (s) below the gogo.py source.) 

### Notes 
This  version is mainly aimed at the '_Transfer_' of Steem-Engine dot com Tokens. Although it might seem relatively easy to add some functionality to it to '_Issue_' and/or '_Stake_'.  (Suggestion: Forked code can be put in a reply at '_SteemHub_') Maybe create a front-end in Kivy? In essence it is possible to use all kinds of different setups, using unique config and dat files. Even automate it more using data pulled from the Steem blockchain first. 

Please note that this is software is something that comes as it is. Use at your own responsibility. And keep the time-out at 10 seconds or more. 

Original copyrights by: _The Marky Mark_.  

Some tutorials on Python3, and the usage of Beem, can be found at fellow Steemian [Felixxx' his blog](https://steemit.com/busy/@felixxx/python-for-steem-how-to-beem). 

### 

- [x] Use it with a combination of unique config. json and airdrop.dat files. 
- [-] Make it work for '_Issue_' and '_Stake_', right out of the box. 
- [-] Switch between different servers. 
- [-] Create a GUI, in Kivy for instance. :: https://kivy.org/#download 
- [-] Grab data from Steem blockchain, then create a Transfer list, completely automated. 

#### Command line 

`python3 gogo.py config.json airdrop.dat` 

#### FILES 

* gogo.py 
The main file, will do the actual airdropping 
* config.json 
A JSON preferences file 
* airdrop.dat 
A CSV data file that holds the Steem accounts and the values 


#### File: gogo.py
```python
import csv
import json
import sys
import time

from beem import Steem
from beem.account import Account
from beem.exceptions import AccountDoesNotExistsException
from beem.instance import set_shared_steem_instance

config = {}
user_list = []


def load_config():
    global config 
    
    if len(sys.argv) == 1:
        print("ERROR: Please specify a config file")
        quit() 

    try:
        with open(sys.argv[1]) as config_file:
            config = json.load(config_file)
    except:
        print("Unable to open configuration file")
        quit()


def load_users():
    global user_list

    if len(sys.argv) == 2:
        print("ERROR: Please specify airdrop file")
        quit()

    try:
        with open(sys.argv[2]) as user_file:
            reader = csv.reader(user_file)
            user_list = list(reader)
    except:
        print("Unable to open airdrop file")
        quit()


def build_payload(user, amount):
    data = {}
    data['contractName'] = 'tokens'
    data['contractAction'] = config['mode']

    data['contractPayload'] = {}
    data['contractPayload']['to'] = user
    data['contractPayload']['symbol'] = config['token'].upper()
    data['contractPayload']['quantity'] = f"{amount}"
    data['contractPayload']['memo'] = config['memo']

    return data


def send_tokens(stm, user, amount, retries=0):
    data = build_payload(user, amount)

    if not config['dry_run']:
        try:
            stm.custom_json('ssc-mainnet1', data,
                            required_auths=[config['account_name']])
        except:
            if retries < 3:
                send_tokens(stm, user, amount, retries=retries)
            else:
                print(f"Airdrop aborted at user: {user[0]}")
                quit()


def do_airdrop(stm):
    estimated_time = round((len(user_list) * config['delay']) / 60, 1)

    estimated_tokens = 0
    for user in user_list:
        estimated_tokens += float(user[1])

    print("Starting Airdrop")

    if config['dry_run']:
        print("DRY RUN! - Tokens will not be transfered.")
    print(f"Estimated Time: {estimated_time} minutes")
    print(f"Estimated Tokens Used: {estimated_tokens}")
    print("")

    for x in range(10, -1, -1):
        print(f"Starting in {x} seconds...", end='\r')
        time.sleep(1)
        sys.stdout.flush()

    for user in user_list:
        try:
            Account(user[0])
        except AccountDoesNotExistsException:
            print(f"Skipping user {user[0]} - Does not exist")
            continue

        print(f"Sending {user[1]} {config['token']} tokens to @{user[0]}")
        if not config['dry_run']:
            send_tokens(stm, user[0], user[1])

        time.sleep(config['delay'])


def main():
    load_config()
    load_users()

    stm = Steem(node=["https://api.steemit.com"])
    stm.wallet.unlock(config['ww'])
    set_shared_steem_instance(stm) 

    do_airdrop(stm)


if __name__ == '__main__':
    main()
```
gogo.py

<hr/>

config.json
```json
{
	"account_name" : "yoursteemaccount",
	"ww" : "youkeywalletpwd",
	"token" : "TKN",
	"memo" : "Here's is some ToKeN for you to enjoy!.",
	"mode" : "transfer",
	"delay" : 10,
	"dry_run" : true
}
```
config.json

<hr/>

airdrop.dat
```cvs
holger80, 10000
themarkymark, 1000
felixxx, 1000
oaldamster, 1000
```
airdrop.dat 

<hr/> 

<center> 
**Python3 and Beem, a powerfull Steem team.** 
![2020-02-06-170119_1366x768_scrot.png](https://cdn.steemitimages.com/DQmXJsK1HCQzEU691pQJ479xuqBastwW4SYWJyupoVUDu7L/2020-02-06-170119_1366x768_scrot.png) 
_Screenshot taken at https://www.python.org/downloads/_
</center> 

***Please note that _SteemHub_ is merely an idea. Whomever is able to create it for real: Make it so!***
👍 , , , , , , , , , , , , , , , , , , ,