forked from BananoCoin/Banano-Discord-TipBot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwallet.py
More file actions
executable file
·122 lines (107 loc) · 4.09 KB
/
wallet.py
File metadata and controls
executable file
·122 lines (107 loc) · 4.09 KB
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
111
112
113
114
115
116
117
118
119
120
121
122
from io import BytesIO
import json
import pycurl
import util
import db
import datetime
import settings
import asyncio
wallet = settings.wallet
logger = util.get_logger('wallet')
balLock = asyncio.Semaphore()
def communicate_wallet(wallet_command):
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, '[::1]')
c.setopt(c.PORT, 7072)
c.setopt(c.POSTFIELDS, json.dumps(wallet_command))
c.setopt(c.WRITEFUNCTION, buffer.write)
c.setopt(c.TIMEOUT, 300)
c.perform()
c.close()
body = buffer.getvalue()
parsed_json = json.loads(body.decode('iso-8859-1'))
return parsed_json
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 asyncio.get_event_loop().run_in_executor(None, communicate_wallet, 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)
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 asyncio.get_event_loop().run_in_executor(None, communicate_wallet, wallet_command)
if 'balance' not in wallet_output:
# Ops
return None
actual_balance = int(wallet_output['balance'])
pending_balance = int(wallet_output['pending'])
# Equiv to rai_from_raw
try:
balLock.acquire()
db.update_pending(user)
finally:
balLock.release()
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 asyncio.get_event_loop().run_in_executor(None, communicate_wallet, 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