forked from bbedward/graham_discord_bot
-
Notifications
You must be signed in to change notification settings - Fork 5
/
wallet.py
executable file
·110 lines (97 loc) · 4.11 KB
/
wallet.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
import util
import db
import datetime
import settings
import asyncio
import aiohttp
import socket
wallet = settings.wallet
logger = util.get_logger('wallet')
logger_newuser = util.get_logger('usr', log_file='user_creation.log')
async def communicate_wallet_async(wallet_command):
conn = aiohttp.TCPConnector(family=socket.AF_INET6,resolver=aiohttp.AsyncResolver())
async with aiohttp.ClientSession(connector=conn) as session:
async with session.post('http://[::1]:7072', json=wallet_command, timeout=300) as resp:
return await resp.json()
async def get_blocks():
wallet_command = {'action':'block_count'}
wallet_output = await communicate_wallet_async(wallet_command)
return (wallet_output['count'], wallet_output['unchecked'])
async def create_or_fetch_user(user_id, user_name):
logger.info('attempting to fetch user %s ...', user_id)
user = db.get_user_by_id(user_id)
if user is None:
logger.info('user %s does not exist. creating new user ...',
user_id)
wallet_command = {'action': 'account_create', 'wallet': wallet}
wallet_output = await communicate_wallet_async(wallet_command)
address = wallet_output['account']
user = db.create_user(user_id=user_id, user_name=user_name,
wallet_address=address)
logger.info('user %s created.', user_id)
logger_newuser.info('user_id: %s, user_name: %s, wallet_address: %s', user_id, user_name, address)
return user
else:
logger.info('user %s fetched.', user_id)
return user
async def get_balance(user):
user_id = user.user_id
logger.info('getting balance for user %s', user_id)
if user is None:
logger.info('user %s does not exist.', user_id)
return {'actual':0,
'available':0,
'pending_send':0,
'pending':0}
else:
logger.info('Fetching balance from wallet for %s', user_id)
wallet_command = {'action': 'account_balance',
'account': user.wallet_address}
wallet_output = await communicate_wallet_async(wallet_command)
if 'balance' not in wallet_output:
# Ops
return None
actual_balance = int(wallet_output['balance'])
pending_balance = int(wallet_output['pending'])
actual_balance = actual_balance / 100000000000000000000000000000
pending_balance = pending_balance / 100000000000000000000000000000
return {'actual':int(actual_balance),
'available': int(actual_balance) - user.pending_send,
'pending_send': user.pending_send,
'pending':int(pending_balance) + user.pending_receive,
}
async def make_transaction_to_address(source_user, amount, withdraw_address, uid, target_id=None, giveaway_id=0, verify_address=False):
# Do not validate address for giveaway tx because we do not know it yet
if verify_address:
# Check to see if the withdraw address is valid
wallet_command = {'action': 'validate_account_number',
'account': withdraw_address}
address_validation = await communicate_wallet_async(wallet_command)
# If the address was the incorrect length, did not start with xrb_ or nano_ or was deemed invalid by the node, return an error.
address_prefix_valid = withdraw_address[:4] == 'ban_' \
or withdraw_address[:5] == 'ban_'
if len(withdraw_address) != 64 or not address_prefix_valid \
or address_validation['valid'] != '1':
raise util.TipBotException('invalid_address')
amount = int(amount)
if amount >= 1:
# See if destination address belongs to a user
if target_id is None:
user = db.get_user_by_wallet_address(withdraw_address)
if user is not None:
target_id=user.user_id
# Update pending send for user
db.create_transaction(source_user, uid, withdraw_address,amount, target_id, giveaway_id)
logger.info('TX queued, uid %s', uid)
else:
raise util.TipBotException('balance_error')
return amount
async def make_transaction_to_user(user, amount, target_user_id, target_user_name, uid):
target_user = await create_or_fetch_user(target_user_id, target_user_name)
try:
actual_tip_amount = await make_transaction_to_address(user, amount, target_user.wallet_address, uid, target_user_id)
except util.TipBotException as e:
return 0
logger.info('tip queued. (from: %s, to: %s, amount: %d, uid: %s)',
user.user_id, target_user.user_id, actual_tip_amount, uid)
return actual_tip_amount