mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 10:28:10 +01:00
scripts: Start example offer script.
This commit is contained in:
157
scripts/createoffers.py
Executable file
157
scripts/createoffers.py
Executable file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2023 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
"""
|
||||
Create offers
|
||||
"""
|
||||
|
||||
__version__ = '0.1'
|
||||
|
||||
import os
|
||||
import json
|
||||
import signal
|
||||
import urllib
|
||||
import logging
|
||||
import argparse
|
||||
import threading
|
||||
from urllib.request import urlopen
|
||||
|
||||
delay_event = threading.Event()
|
||||
|
||||
|
||||
def post_json_req(url, json_data):
|
||||
req = urllib.request.Request(url)
|
||||
req.add_header('Content-Type', 'application/json; charset=utf-8')
|
||||
post_bytes = json.dumps(json_data).encode('utf-8')
|
||||
req.add_header('Content-Length', len(post_bytes))
|
||||
return urlopen(req, post_bytes, timeout=300).read()
|
||||
|
||||
|
||||
def read_json_api(port, path=None, json_data=None):
|
||||
url = f'http://127.0.0.1:{port}/json'
|
||||
if path is not None:
|
||||
url += '/' + path
|
||||
|
||||
if json_data is not None:
|
||||
return json.loads(post_json_req(url, json_data))
|
||||
return json.loads(urlopen(url, timeout=300).read())
|
||||
|
||||
|
||||
def signal_handler(sig, frame) -> None:
|
||||
logging.info('Signal {} detected.'.format(sig))
|
||||
delay_event.set()
|
||||
|
||||
|
||||
def findCoin(coin: str, known_coins) -> str:
|
||||
for known_coin in known_coins:
|
||||
if known_coin['name'].lower() == coin.lower() or known_coin['ticker'].lower() == coin.lower():
|
||||
if known_coin['active'] is False:
|
||||
raise ValueError(f'Inactive coin {coin}')
|
||||
return known_coin['name']
|
||||
raise ValueError(f'Unknown coin {coin}')
|
||||
|
||||
|
||||
def readTemplates(known_coins):
|
||||
offer_templates = []
|
||||
with open('offer_rules.csv', 'r') as fp:
|
||||
for i, line in enumerate(fp):
|
||||
if i < 1:
|
||||
continue
|
||||
line = line.strip()
|
||||
if line[0] == '#':
|
||||
continue
|
||||
row_data = line.split(',')
|
||||
try:
|
||||
if len(row_data) < 6:
|
||||
raise ValueError('missing data')
|
||||
offer_template = {}
|
||||
offer_template['coin_from'] = findCoin(row_data[0], known_coins)
|
||||
offer_template['coin_to'] = findCoin(row_data[1], known_coins)
|
||||
offer_template['amount'] = row_data[2]
|
||||
offer_template['minrate'] = float(row_data[3])
|
||||
offer_template['ratetweakpercent'] = float(row_data[4])
|
||||
offer_template['amount_variable'] = row_data[5].lower() in ('true', 1)
|
||||
offer_templates.append(offer_template)
|
||||
except Exception as e:
|
||||
print(f'Warning: Skipping row {i}, {e}')
|
||||
continue
|
||||
return offer_templates
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('-v', '--version', action='version',
|
||||
version='%(prog)s {version}'.format(version=__version__))
|
||||
parser.add_argument('--port', dest='port', help='RPC port (default=12700)', type=int, default=12700, required=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not os.path.exists('offer_rules.csv'):
|
||||
with open('offer_rules.csv', 'w') as fp:
|
||||
fp.write('coin from,coin to,offer value,min rate,rate tweak percent,amount variable')
|
||||
|
||||
known_coins = read_json_api(args.port, 'coins')
|
||||
coins_map = {}
|
||||
for known_coin in known_coins:
|
||||
coins_map[known_coin['name']] = known_coin
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
while not delay_event.is_set():
|
||||
# Read templates each iteration so they can be modified without restarting
|
||||
offer_templates = readTemplates(known_coins)
|
||||
|
||||
try:
|
||||
sent_offers = read_json_api(args.port, 'sentoffers', {'active': 'active'})
|
||||
|
||||
for offer_template in offer_templates:
|
||||
offers_found = 0
|
||||
for offer in sent_offers:
|
||||
if offer['coin_from'] == offer_template['coin_from'] and offer['coin_to'] == offer_template['coin_to']:
|
||||
offers_found += 1
|
||||
|
||||
if offers_found > 0:
|
||||
continue
|
||||
coin_from_data = coins_map[offer_template['coin_from']]
|
||||
coin_to_data = coins_map[offer_template['coin_to']]
|
||||
|
||||
rates = read_json_api(args.port, 'rates', {'coin_from': coin_from_data['id'], 'coin_to': coin_to_data['id']})
|
||||
print('Rates', rates)
|
||||
coingecko_rate = float(rates['coingecko']['rate_inferred'])
|
||||
use_rate = coingecko_rate
|
||||
|
||||
if offer_template['ratetweakpercent'] != 0:
|
||||
print('Adjusting rate {} by {}%.'.format(use_rate, offer_template['ratetweakpercent']))
|
||||
tweak = offer_template['ratetweakpercent'] / 100.0
|
||||
use_rate += use_rate * tweak
|
||||
|
||||
if use_rate < offer_template['minrate']:
|
||||
print('Warning: Clamping rate to minimum.')
|
||||
use_rate = offer_template['minrate']
|
||||
|
||||
print('Creating offer for: {} at rate: {}'.format(offer_template, use_rate))
|
||||
offer_data = {
|
||||
'addr_from': '-1',
|
||||
'coin_from': coin_from_data['ticker'],
|
||||
'coin_to': coin_to_data['ticker'],
|
||||
'amt_from': offer_template['amount'],
|
||||
'amt_var': offer_template['amount_variable'],
|
||||
'rate': use_rate,
|
||||
'swap_type': 'adaptor_sig',
|
||||
'lockhrs': '24',
|
||||
'automation_strat_id': 1}
|
||||
new_offer = read_json_api(args.port, 'offers/new', offer_data)
|
||||
print('New offer: {}'.format(new_offer))
|
||||
except Exception as e:
|
||||
print('Error: Clamping rate to minimum.')
|
||||
|
||||
print('Looping indefinitely, ctrl+c to exit.')
|
||||
delay_event.wait(60)
|
||||
|
||||
print('Done.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user