Update cryptowallet + rpc
This commit is contained in:
parent
df678c29b0
commit
c3e14a8d0d
|
@ -2,25 +2,25 @@
|
||||||
"types": {
|
"types": {
|
||||||
"LTC": {
|
"LTC": {
|
||||||
"name": "Litecoin",
|
"name": "Litecoin",
|
||||||
"abbr": "LTC",
|
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"username": "user",
|
"username": "user",
|
||||||
"password": "pass",
|
"password": "pass",
|
||||||
"port": 12893,
|
"port": 12893,
|
||||||
"precision": 8,
|
"precision": 8,
|
||||||
"reserve": 0.01,
|
"reserve": 0.01,
|
||||||
"link": "https://litecoin.org/"
|
"link": "https://litecoin.org/",
|
||||||
|
"addrfmt": "^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$"
|
||||||
},
|
},
|
||||||
"BTC": {
|
"BTC": {
|
||||||
"name": "Bitcoin",
|
"name": "Bitcoin",
|
||||||
"abbr": "BTC",
|
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"username": "user",
|
"username": "user",
|
||||||
"password": "pass",
|
"password": "pass",
|
||||||
"port": 48191,
|
"port": 48191,
|
||||||
"precision": 8,
|
"precision": 8,
|
||||||
"reserve": 0.001,
|
"reserve": 0.001,
|
||||||
"link": "http://bitcoin.org/"
|
"link": "http://bitcoin.org/",
|
||||||
|
"addrfmt": "^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pyircbot.modulebase import ModuleBase, ModuleHook
|
from pyircbot.modulebase import ModuleBase, command
|
||||||
|
from pyircbot.modules.ModInfo import info
|
||||||
|
from pyircbot.common import messageHasCommand
|
||||||
|
from decimal import Decimal
|
||||||
import time
|
import time
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
|
@ -15,305 +18,271 @@ import hashlib
|
||||||
class CryptoWallet(ModuleBase):
|
class CryptoWallet(ModuleBase):
|
||||||
def __init__(self, bot, moduleName):
|
def __init__(self, bot, moduleName):
|
||||||
ModuleBase.__init__(self, bot, moduleName)
|
ModuleBase.__init__(self, bot, moduleName)
|
||||||
self.hooks = [ModuleHook("PRIVMSG", self.handle_message)]
|
|
||||||
|
|
||||||
def getMods(self):
|
def getMods(self):
|
||||||
return (self.bot.getBestModuleForService("attributes"), self.bot.getBestModuleForService("bitcoinrpc"))
|
return (self.bot.getBestModuleForService("attributes"), self.bot.getBestModuleForService("bitcoinrpc"))
|
||||||
|
|
||||||
def handle_setaddr(self, args, prefix, trailing, cmd):
|
@info("setaddr <currency> <address> set withdraw address", cmds=["setaddr"])
|
||||||
usage = ".setaddr <currency> <address>"
|
@command("setaddr", require_args=2, allow_private=True)
|
||||||
attr, rpc = self.getMods()
|
def handle_setaddr(self, msg, cmd):
|
||||||
|
if not self.check_login(msg.prefix, msg.args[0]):
|
||||||
# Check for args
|
|
||||||
if not len(cmd.args) == 2:
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".setaddr: usage: %s" % usage)
|
|
||||||
# self.bot.act_PRIVMSG(args[0], ".setaddr: usage: .setaddr BTC 1xyWx6X5EABprhe3s9XduNxLn5NCtpSNB")
|
|
||||||
return
|
return
|
||||||
|
attr, rpc = self.getMods()
|
||||||
# Check if currency is known
|
# Check if currency is known
|
||||||
if not rpc.isSupported(cmd.args[0]):
|
if not rpc.isSupported(cmd.args[0]):
|
||||||
supportedStr = ', '.join(rpc.getSupported())
|
supportedStr = ', '.join(rpc.getSupported())
|
||||||
self.bot.act_PRIVMSG(args[0], ".setaddr: '%s' is not a supported currency. Supported currencies are: %s" %
|
self.bot.act_PRIVMSG(msg.args[0], ".setaddr: '{}' is not a supported currency. Supported currencies are: {}"
|
||||||
(cmd.args[0], supportedStr))
|
.format(cmd.args[0], supportedStr))
|
||||||
return
|
return
|
||||||
if len(cmd.args[1]) < 16 or len(cmd.args[1]) > 42:
|
if len(cmd.args[1]) < 16 or len(cmd.args[1]) > 42:
|
||||||
self.bot.act_PRIVMSG(args[0], ".setaddr: '%s' appears to be an invalid address." % (cmd.args[1]))
|
self.bot.act_PRIVMSG(msg.args[0], ".setaddr: '{}' appears to be an invalid address.".format(cmd.args[1]))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Just make sure they have a wallet
|
# Just make sure they have a wallet
|
||||||
self.checkUserHasWallet(prefix.nick, cmd.args[0])
|
self.checkUserHasWallet(msg.prefix.nick, cmd.args[0])
|
||||||
|
|
||||||
# Set their address
|
# Set their address
|
||||||
attr.setKey(prefix.nick, "cryptowallet-%s-address" % cmd.args[0].lower(), cmd.args[1])
|
attr.setKey(msg.prefix.nick, "cryptowallet-{}-address".format(cmd.args[0].lower()), cmd.args[1])
|
||||||
self.bot.act_PRIVMSG(args[0], ".setaddr: Your address has been saved as: %s. Please verify that this is correct"
|
self.bot.act_PRIVMSG(msg.args[0], ".setaddr: Your address has been saved as: {}. Please verify that this is "
|
||||||
" or your coins could be lost." % (cmd.args[1]))
|
"correct or your coins could be lost.".format(cmd.args[1]))
|
||||||
|
|
||||||
def handle_getbal(self, args, prefix, trailing, cmd):
|
@info("getbal <currency> retrieve your balance ", cmds=["getbal"])
|
||||||
|
@command("getbal", require_args=1, allow_private=True)
|
||||||
|
def handle_getbal(self, msg, cmd):
|
||||||
usage = ".getbal <currency>"
|
usage = ".getbal <currency>"
|
||||||
|
if not self.check_login(msg.prefix, msg.args[0]):
|
||||||
|
return
|
||||||
attr, rpc = self.getMods()
|
attr, rpc = self.getMods()
|
||||||
# Check for args
|
# Check for args
|
||||||
if not len(cmd.args) == 1:
|
if len(cmd.args) != 1:
|
||||||
self.bot.act_PRIVMSG(args[0], ".getbal: usage: %s" % usage)
|
self.bot.act_PRIVMSG(msg.args[0], ".getbal: usage: {}".format(usage))
|
||||||
self.bot.act_PRIVMSG(args[0], ".getbal: usage: .getbal BTC")
|
|
||||||
return
|
return
|
||||||
# Check if currency is known
|
# Check if currency is known
|
||||||
if not rpc.isSupported(cmd.args[0]):
|
if not rpc.isSupported(cmd.args[0]):
|
||||||
supportedStr = ', '.join(rpc.getSupported())
|
supportedStr = ', '.join(rpc.getSupported())
|
||||||
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" %
|
self.bot.act_PRIVMSG(msg.args[0],
|
||||||
(cmd.args[0], supportedStr))
|
".getbal: '{}' is not a supported currency. Supported currencies are: {}"
|
||||||
|
.format(cmd.args[0], supportedStr))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Just make sure they have a wallet
|
# Just make sure they have a wallet
|
||||||
self.checkUserHasWallet(prefix.nick, cmd.args[0])
|
self.checkUserHasWallet(msg.prefix.nick, cmd.args[0])
|
||||||
|
|
||||||
# fetch RPC and tell them the balance
|
# fetch RPC and tell them the balance
|
||||||
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s" % cmd.args[0].lower())
|
walletname = attr.getKey(msg.prefix.nick, "cryptowallet-account-{}".format(cmd.args[0].lower()))
|
||||||
amount = 0.0
|
amount = 0.0
|
||||||
if walletname:
|
if walletname:
|
||||||
client = rpc.getRpc(cmd.args[0].lower())
|
client = rpc.getRpc(cmd.args[0].lower())
|
||||||
amount = client.getBal(walletname)
|
amount = client.getBal(walletname)
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: your balance is: %s %s" % (prefix.nick, amount, cmd.args[0].upper()))
|
self.bot.act_PRIVMSG(msg.args[0],
|
||||||
|
"{}: your balance is: {} {}".format(msg.prefix.nick, amount, cmd.args[0].upper()))
|
||||||
|
|
||||||
def handle_withdraw(self, args, prefix, trailing, cmd):
|
@info("withdraw <currenyc> <amount> send coins to your withdraw address", cmds=["withdraw"])
|
||||||
usage = ".withdraw <currency> <amount>"
|
@command("withdraw", require_args=2, allow_private=True)
|
||||||
attr, rpc = self.getMods()
|
def handle_withdraw(self, msg, cmd):
|
||||||
# Check for args
|
if not self.check_login(msg.prefix, msg.args[0]):
|
||||||
if not len(cmd.args) == 2:
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: usage: %s" % usage)
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: usage: .getbal BTC 0.035")
|
|
||||||
return
|
return
|
||||||
|
attr, rpc = self.getMods()
|
||||||
# Check if currency is known
|
# Check if currency is known
|
||||||
if not rpc.isSupported(cmd.args[0]):
|
if not rpc.isSupported(cmd.args[0]):
|
||||||
supportedStr = ', '.join(rpc.getSupported())
|
supportedStr = ', '.join(rpc.getSupported())
|
||||||
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" %
|
self.bot.act_PRIVMSG(msg.args[0], ".getbal: '{}' is not a supported currency. Supported currencies are: {}"
|
||||||
(cmd.args[0], supportedStr))
|
.format(cmd.args[0], supportedStr))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Just make sure they have a wallet
|
# Just make sure they have a wallet
|
||||||
self.checkUserHasWallet(prefix.nick, cmd.args[0])
|
self.checkUserHasWallet(msg.prefix.nick, cmd.args[0])
|
||||||
|
|
||||||
# check that they have a withdraw addr
|
# check that they have a withdraw addr
|
||||||
withdrawaddr = attr.getKey(prefix.nick, "cryptowallet-%s-address" % cmd.args[0].lower())
|
withdrawaddr = attr.getKey(msg.prefix.nick, "cryptowallet-{}-address".format(cmd.args[0].lower()))
|
||||||
if withdrawaddr is None:
|
if withdrawaddr is None:
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: You need to set a withdraw address before withdrawing. "
|
self.bot.act_PRIVMSG(msg.args[0], ".withdraw: You need to set a withdraw address before withdrawing. "
|
||||||
"Try .setaddr")
|
"Try .setaddr")
|
||||||
return
|
return
|
||||||
|
|
||||||
# fetch RPC and check balance
|
# fetch RPC and check balance
|
||||||
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s" % cmd.args[0].lower())
|
walletname = attr.getKey(msg.prefix.nick, "cryptowallet-account-{}".format(cmd.args[0].lower()))
|
||||||
balance = 0.0
|
balance = 0.0
|
||||||
|
|
||||||
client = rpc.getRpc(cmd.args[0].lower())
|
client = rpc.getRpc(cmd.args[0].lower())
|
||||||
balance = client.getBal(walletname)
|
balance = client.getBal(walletname)
|
||||||
withdrawamount = float(cmd.args[1])
|
withdrawamount = Decimal(cmd.args[1])
|
||||||
|
|
||||||
if balance < withdrawamount or withdrawamount < 0:
|
if balance < withdrawamount or withdrawamount < 0:
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: You don't have enough %s to withdraw %s" %
|
self.bot.act_PRIVMSG(msg.args[0], ".withdraw: You don't have enough {} to withdraw {}"
|
||||||
(cmd.args[0].upper(), withdrawamount))
|
.format(cmd.args[0].upper(), withdrawamount))
|
||||||
return
|
return
|
||||||
|
|
||||||
if not client.reserve == 0 and balance - client.reserve < withdrawamount:
|
if not client.reserve == 0 and balance - client.reserve < withdrawamount:
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: Withdrawing that much would put you below the reserve (%s %s)." %
|
self.bot.act_PRIVMSG(msg.args[0], ".withdraw: Withdrawing that much would put you below the reserve "
|
||||||
(client.reserve, cmd.args[0].upper()))
|
"({} {}).".format(client.reserve, cmd.args[0].upper()))
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: The reserve is to cover network transaction fees. To recover it "
|
self.bot.act_PRIVMSG(msg.args[0], ".withdraw: The reserve is to cover network transaction fees. To recover "
|
||||||
"you must close your account. (Talk to an admin)")
|
"it you must close your account. (Talk to an admin)")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if the precision is wrong
|
# Check if the precision is wrong
|
||||||
if not client.checkPrecision(withdrawamount):
|
if not client.checkPrecision(withdrawamount):
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: %s has maximum %s decimal places" % (cmd.args[0].upper(),
|
self.bot.act_PRIVMSG(msg.args[0], ".withdraw: {} has maximum {} decimal places"
|
||||||
client.precision))
|
.format(cmd.args[0].upper(), client.precision))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create a transaction
|
# Create a transaction
|
||||||
txn = client.send(walletname, withdrawaddr, withdrawamount)
|
txn = client.send(walletname, withdrawaddr, withdrawamount)
|
||||||
if txn:
|
if txn:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: .withdraw: %s %s sent to %s. " %
|
self.bot.act_PRIVMSG(msg.args[0], "{}: .withdraw: {} {} sent to {}. "
|
||||||
(prefix.nick, withdrawamount, client.name, withdrawaddr))
|
.format(msg.prefix.nick, withdrawamount, client.name, withdrawaddr))
|
||||||
self.bot.act_PRIVMSG(prefix.nick, "Withdrawal: (You)->%s: Transaction ID: %s" %
|
self.bot.act_PRIVMSG(msg.prefix.nick, "Withdrawal: (You)->{}: Transaction ID: {}"
|
||||||
(prefix.nick, withdrawaddr, txn))
|
.format(withdrawaddr, txn))
|
||||||
else:
|
else:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: .withdraw: Transaction create failed. Maybe the transaction was too "
|
self.bot.act_PRIVMSG(msg.args[0], "{}: .withdraw: Transaction create failed. Maybe the transaction was too "
|
||||||
"large for the network? Try a smaller increment." % prefix.nick)
|
"large for the network? Try a smaller increment.".format(msg.prefix.nick))
|
||||||
|
|
||||||
def handle_send(self, args, prefix, trailing, cmd):
|
@info("send <currency> <amount> <nick_or_address> send coins elsewhere", cmds=["send"])
|
||||||
usage = ".send <currency> <amount> <nick or address>"
|
@command("send", require_args=3, allow_private=True)
|
||||||
attr, rpc = self.getMods()
|
def handle_send(self, msg, cmd):
|
||||||
# Check for args
|
if not self.check_login(msg.prefix, msg.args[0]):
|
||||||
if not len(cmd.args) == 3:
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: usage: %s" % usage)
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".withdraw: usage: .getbal BTC 0.035")
|
|
||||||
return
|
return
|
||||||
|
attr, rpc = self.getMods()
|
||||||
# Check if currency is known
|
# Check if currency is known
|
||||||
if not rpc.isSupported(cmd.args[0]):
|
curr_name = cmd.args[0].lower()
|
||||||
|
if not rpc.isSupported(curr_name):
|
||||||
supportedStr = ', '.join(rpc.getSupported())
|
supportedStr = ', '.join(rpc.getSupported())
|
||||||
self.bot.act_PRIVMSG(args[0], ".getbal: '%s' is not a supported currency. Supported currencies are: %s" %
|
self.bot.act_PRIVMSG(msg.args[0], ".getbal: '{}' is not a supported currency. Supported currencies are: {}"
|
||||||
(cmd.args[0], supportedStr))
|
.format(curr_name, supportedStr))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Just make sure they have a wallet
|
# Just make sure they have a wallet
|
||||||
self.checkUserHasWallet(prefix.nick, cmd.args[0])
|
self.checkUserHasWallet(msg.prefix.nick, curr_name)
|
||||||
|
|
||||||
# fetch RPC and check balance
|
# fetch RPC and check balance
|
||||||
walletname = attr.getKey(prefix.nick, "cryptowallet-account-%s" % cmd.args[0].lower())
|
walletname = attr.getKey(msg.prefix.nick, "cryptowallet-account-{}".format(curr_name))
|
||||||
balance = 0.0
|
balance = 0.0
|
||||||
|
|
||||||
client = rpc.getRpc(cmd.args[0].lower())
|
client = rpc.getRpc(curr_name.lower())
|
||||||
balance = client.getBal(walletname)
|
balance = client.getBal(walletname)
|
||||||
withdrawamount = float(cmd.args[1])
|
withdrawamount = Decimal(cmd.args[1])
|
||||||
|
tx_dest = cmd.args[2]
|
||||||
|
|
||||||
if balance < withdrawamount or withdrawamount < 0:
|
if balance < withdrawamount or withdrawamount < 0:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: .send: You don't have enough %s to send %s" %
|
self.bot.act_PRIVMSG(msg.args[0], "{}: .send: You don't have enough {} to send {}"
|
||||||
(prefix.nick, cmd.args[0].upper(), withdrawamount))
|
.format(msg.prefix.nick, curr_name.upper(), withdrawamount))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if the precision is wrong
|
# Check if the precision is wrong
|
||||||
if not client.checkPrecision(withdrawamount):
|
if not client.checkPrecision(withdrawamount):
|
||||||
self.bot.act_PRIVMSG(args[0], ".send: %s has maximum %s decimal places" %
|
self.bot.act_PRIVMSG(msg.args[0], ".send: {} has maximum {} decimal places"
|
||||||
(cmd.args[0].upper(), client.precision))
|
.format(curr_name.upper(), client.precision))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check if the recierver is a dogecoin address
|
# Check if the tx_dest is a valid address for the coin
|
||||||
if len(cmd.args[2]) == 34 and cmd.args[2][0:1] == "D":
|
if client.validate_addr(tx_dest):
|
||||||
# Check if we can cover network fees
|
# Check if we can cover network fees
|
||||||
if not client.reserve == 0 and balance - client.reserve < withdrawamount:
|
if not client.reserve == 0 and balance - client.reserve < withdrawamount:
|
||||||
self.bot.act_PRIVMSG(args[0], ".send: Sending that much would put you below the reserve (%s %s)." %
|
self.bot.act_PRIVMSG(msg.args[0], ".send: Sending that much would put you below the reserve ({} {})."
|
||||||
(client.reserve, cmd.args[0].upper()))
|
.format(client.reserve, curr_name.upper()))
|
||||||
self.bot.act_PRIVMSG(args[0], ".send: The reserve is to cover network transaction fees. To recover it "
|
self.bot.act_PRIVMSG(msg.args[0], ".send: The reserve is to cover network transaction fees. To recover it"
|
||||||
"you must close your account. (Talk to an admin)")
|
" you must close your account. (Talk to my owner)")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Create a transaction
|
# Create a transaction
|
||||||
txn = client.send(walletname, cmd.args[2], withdrawamount)
|
txn = client.send(walletname, tx_dest, withdrawamount)
|
||||||
if txn:
|
if txn:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: .send: %s %s sent to %s. " %
|
self.bot.act_PRIVMSG(msg.args[0], "{}: .send: {} {} sent to {}. "
|
||||||
(prefix.nick, withdrawamount, client.name, cmd.args[2]))
|
.format(msg.prefix.nick, withdrawamount, client.name, tx_dest))
|
||||||
self.bot.act_PRIVMSG(prefix.nick, "Send: (You)->%s: Transaction ID: %s" % (cmd.args[2], txn))
|
self.bot.act_PRIVMSG(msg.prefix.nick, "Send: (You)->{}: Transaction ID: {}".format(tx_dest, txn))
|
||||||
else:
|
else:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: .send: Transaction create failed. Maybe the address is invalid or "
|
self.bot.act_PRIVMSG(msg.args[0], "{}: .send: Transaction create failed. Maybe the address is invalid "
|
||||||
"transaction too large for the network? Try a smaller increment." %
|
"or transaction too large for the network?".format(msg.prefix.nick))
|
||||||
prefix.nick)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Move between local wallets
|
# Move between local wallets
|
||||||
# Check if dest user has a password set
|
# Check if dest user has a password set
|
||||||
destUserPassword = attr.getKey(cmd.args[2], "password")
|
destUserPassword = attr.getKey(tx_dest, "password")
|
||||||
if destUserPassword is None:
|
if destUserPassword is None:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s .send: %s doesn't have a password set." % (prefix.nick, cmd.args[2]))
|
self.bot.act_PRIVMSG(msg.args[0], "{} .send: {} doesn't have a password set."
|
||||||
|
.format(msg.prefix.nick, tx_dest))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Since the user has a password set, check that they have a wallet and create if not
|
# Since the user has a password set, check that they have a wallet and create if not
|
||||||
self.checkUserHasWallet(cmd.args[2], cmd.args[0])
|
self.checkUserHasWallet(tx_dest, curr_name)
|
||||||
|
|
||||||
srcWalletName = attr.getKey(prefix.nick, "cryptowallet-account-%s" % cmd.args[0])
|
srcWalletName = attr.getKey(msg.prefix.nick, "cryptowallet-account-{}".format(curr_name))
|
||||||
destWalletName = attr.getKey(cmd.args[2], "cryptowallet-account-%s" % cmd.args[0])
|
destWalletName = attr.getKey(tx_dest, "cryptowallet-account-{}".format(curr_name))
|
||||||
|
|
||||||
assert srcWalletName is not None
|
assert srcWalletName is not None
|
||||||
assert destWalletName is not None
|
assert destWalletName is not None
|
||||||
try:
|
if srcWalletName == destWalletName:
|
||||||
assert srcWalletName != destWalletName
|
self.bot.act_PRIVMSG(msg.args[0], "{}: you can't send to yourself!".format(msg.prefix.nick))
|
||||||
except:
|
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: you can't send to yourself!" % prefix.nick)
|
|
||||||
return
|
return
|
||||||
print(srcWalletName)
|
print(srcWalletName)
|
||||||
print(destWalletName)
|
print(destWalletName)
|
||||||
if client.canMove(srcWalletName, destWalletName, withdrawamount):
|
if client.canMove(srcWalletName, destWalletName, withdrawamount):
|
||||||
if client.move(srcWalletName, destWalletName, withdrawamount):
|
if client.move(srcWalletName, destWalletName, withdrawamount):
|
||||||
self.bot.act_PRIVMSG(args[0], "%s .send: %s %s sent to %s. " %
|
self.bot.act_PRIVMSG(msg.args[0], "{} .send: {} {} sent to {}. "
|
||||||
(prefix.nick, withdrawamount, client.name, cmd.args[2]))
|
.format(msg.prefix.nick, withdrawamount, client.name, tx_dest))
|
||||||
else:
|
else:
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: uh-oh, something went wrong doing that." % prefix.nick)
|
self.bot.act_PRIVMSG(msg.args[0], "{}: uh-oh, something went wrong doing that."
|
||||||
|
.format(msg.prefix.nick))
|
||||||
|
|
||||||
def handle_getaddr(self, args, prefix, trailing, cmd):
|
@info("getaddr <currency> get deposit address", cmds=["getaddr"])
|
||||||
attr, rpc = self.getMods()
|
@command("getaddr", require_args=1, allow_private=True)
|
||||||
usage = ".getaddr <currency>"
|
def handle_getaddr(self, msg, cmd):
|
||||||
# Check for args
|
if not self.check_login(msg.prefix, msg.args[0]):
|
||||||
if not len(cmd.args) == 1:
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".getaddr: usage: %s" % usage)
|
|
||||||
self.bot.act_PRIVMSG(args[0], ".getaddr: usage: .getaddr BTC")
|
|
||||||
return
|
return
|
||||||
|
attr, rpc = self.getMods()
|
||||||
# Check if currency is known
|
# Check if currency is known
|
||||||
if not rpc.isSupported(cmd.args[0]):
|
if not rpc.isSupported(cmd.args[0]):
|
||||||
supportedStr = ', '.join(rpc.getSupported())
|
supportedStr = ', '.join(rpc.getSupported())
|
||||||
self.bot.act_PRIVMSG(args[0], ".getaddr: '%s' is not a supported currency. Supported currencies are: %s" %
|
self.bot.act_PRIVMSG(msg.args[0], ".getaddr: '{}' is not a supported currency. Supported currencies are: {}"
|
||||||
(cmd.args[0], supportedStr))
|
.format(cmd.args[0], supportedStr))
|
||||||
return
|
return
|
||||||
|
|
||||||
# Just make sure they have a wallet
|
# Just make sure they have a wallet
|
||||||
self.checkUserHasWallet(prefix.nick, cmd.args[0])
|
self.checkUserHasWallet(msg.prefix.nick, cmd.args[0])
|
||||||
|
|
||||||
walletaddr = attr.getKey(prefix.nick, "cryptowallet-depoaddr-%s" % cmd.args[0].lower())
|
walletaddr = attr.getKey(msg.prefix.nick, "cryptowallet-depoaddr-{}".format(cmd.args[0].lower()))
|
||||||
self.bot.act_PRIVMSG(args[0], "%s: your %s deposit address is: %s" %
|
self.bot.act_PRIVMSG(msg.args[0], "{}: your {} deposit address is: {}"
|
||||||
(prefix.nick, cmd.args[0].upper(), walletaddr))
|
.format(msg.prefix.nick, cmd.args[0].upper(), walletaddr))
|
||||||
|
|
||||||
def handle_curinfo(self, args, prefix, trailing, cmd):
|
@info("curinfo list supported coins", cmds=["curinfo"])
|
||||||
|
@command("curinfo", allow_private=True)
|
||||||
|
def handle_curinfo(self, msg, cmd):
|
||||||
attr, rpc = self.getMods()
|
attr, rpc = self.getMods()
|
||||||
|
if not cmd.args:
|
||||||
# Check for args
|
self.bot.act_PRIVMSG(msg.args[0],
|
||||||
if len(cmd.args) == 0:
|
".curinfo: supported currencies: {}. Use '.curinfo BTC' to see details. "
|
||||||
self.bot.act_PRIVMSG(args[0], ".curinfo: supported currencies: %s. Use '.curinfo BTC' to see details. " %
|
.format(', '.join([x.upper() for x in rpc.getSupported()])))
|
||||||
', '.join([x.upper() for x in rpc.getSupported()]))
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
if not rpc.isSupported(cmd.args[0]):
|
if not rpc.isSupported(cmd.args[0]):
|
||||||
self.bot.act_PRIVMSG(args[0], ".curinfo: '%s' is not a supported currency. Supported currencies are: "
|
self.bot.act_PRIVMSG(msg.args[0],
|
||||||
"%s" % (cmd.args[0], ', '.join([x.upper() for x in rpc.getSupported()])))
|
".curinfo: '{}' is not a supported currency. Supported currencies are: {}"
|
||||||
|
.format(cmd.args[0], ', '.join([x.upper() for x in rpc.getSupported()])))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
info = rpc.getInfo(cmd.args[0])
|
info = rpc.getInfo(cmd.args[0])
|
||||||
self.bot.act_PRIVMSG(args[0], ".curinfo: %s - %s. More info: %s" %
|
self.bot.act_PRIVMSG(msg.args[0], ".curinfo: {} - {}. More info: {}"
|
||||||
(args[0], info["name"], info["link"]))
|
.format(cmd.args[0], info["name"], info["link"]))
|
||||||
|
|
||||||
def checkUserHasWallet(self, username, currency):
|
def checkUserHasWallet(self, username, currency):
|
||||||
# Ensure the user has a wallet in the client
|
# Ensure the user has a wallet in the client
|
||||||
attr, rpc = self.getMods()
|
attr, rpc = self.getMods()
|
||||||
currency = currency.lower()
|
currency = currency.lower()
|
||||||
username = username.lower()
|
username = username.lower()
|
||||||
if attr.getKey(username, "cryptowallet-account-%s" % currency) is None:
|
if attr.getKey(username, "cryptowallet-account-{}".format(currency)) is None:
|
||||||
randName = self.md5(str(time.time()))[0:16]
|
randName = self.md5(str(time.time()))[0:16]
|
||||||
attr.setKey(username, "cryptowallet-account-%s" % currency, randName)
|
attr.setKey(username, "cryptowallet-account-{}".format(currency), randName)
|
||||||
# Generate a deposit addr to nudge the wallet
|
# Generate a deposit addr to nudge the wallet
|
||||||
wallet = rpc.getRpc(currency.lower())
|
wallet = rpc.getRpc(currency.lower())
|
||||||
address = wallet.getAcctAddr(randName)
|
address = wallet.getAcctAddr(randName)
|
||||||
attr.setKey(username, "cryptowallet-depoaddr-%s" % currency, address)
|
attr.setKey(username, "cryptowallet-depoaddr-{}".format(currency), address)
|
||||||
elif attr.getKey(username, "cryptowallet-depoaddr-%s" % currency) is None:
|
elif attr.getKey(username, "cryptowallet-depoaddr-{}".format(currency)) is None:
|
||||||
walletName = attr.getKey(username, "cryptowallet-account-%s" % currency)
|
walletName = attr.getKey(username, "cryptowallet-account-{}".format(currency))
|
||||||
wallet = rpc.getRpc(currency.lower())
|
wallet = rpc.getRpc(currency.lower())
|
||||||
address = wallet.getAcctAddr(walletName)
|
address = wallet.getAcctAddr(walletName)
|
||||||
attr.setKey(username, "cryptowallet-depoaddr-%s" % currency, address)
|
attr.setKey(username, "cryptowallet-depoaddr-{}".format(currency), address)
|
||||||
|
|
||||||
def handle_message(self, args, prefix, trailing):
|
|
||||||
prefix = self.bot.decodePrefix(prefix)
|
|
||||||
|
|
||||||
# Free commands
|
|
||||||
cmd = self.bot.messageHasCommand(".curinfo", trailing)
|
|
||||||
if cmd:
|
|
||||||
self.handle_curinfo(args, prefix, trailing, cmd)
|
|
||||||
|
|
||||||
# Login protected commands
|
|
||||||
cmd = self.bot.messageHasCommand(".setaddr", trailing)
|
|
||||||
if cmd and self.check_login(prefix, args[0]):
|
|
||||||
self.handle_setaddr(args, prefix, trailing, cmd)
|
|
||||||
|
|
||||||
cmd = self.bot.messageHasCommand(".getbal", trailing)
|
|
||||||
if cmd and self.check_login(prefix, args[0]):
|
|
||||||
self.handle_getbal(args, prefix, trailing, cmd)
|
|
||||||
|
|
||||||
cmd = self.bot.messageHasCommand(".withdraw", trailing)
|
|
||||||
if cmd and self.check_login(prefix, args[0]):
|
|
||||||
self.handle_withdraw(args, prefix, trailing, cmd)
|
|
||||||
|
|
||||||
cmd = self.bot.messageHasCommand(".getaddr", trailing)
|
|
||||||
if cmd and self.check_login(prefix, args[0]):
|
|
||||||
self.handle_getaddr(args, prefix, trailing, cmd)
|
|
||||||
|
|
||||||
cmd = self.bot.messageHasCommand(".send", trailing)
|
|
||||||
if cmd and self.check_login(prefix, args[0]):
|
|
||||||
self.handle_send(args, prefix, trailing, cmd)
|
|
||||||
|
|
||||||
def check_login(self, prefix, replyTo):
|
def check_login(self, prefix, replyTo):
|
||||||
login = self.bot.getBestModuleForService("login")
|
login = self.bot.getBestModuleForService("login")
|
||||||
if not login.check(prefix.nick, prefix.hostname):
|
if not login.check(prefix.nick, prefix.hostname):
|
||||||
self.bot.act_PRIVMSG(replyTo, "%s: Please .login to use this command." % prefix.nick)
|
self.bot.act_PRIVMSG(replyTo, "{}: Please .login to use this command.".format(prefix.nick))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
from pyircbot.modulebase import ModuleBase
|
from pyircbot.modulebase import ModuleBase
|
||||||
from bitcoinrpc.authproxy import AuthServiceProxy
|
from bitcoinrpc.authproxy import AuthServiceProxy
|
||||||
|
import re
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,13 +23,17 @@ class CryptoWalletRPC(ModuleBase):
|
||||||
def loadrpcservices(self):
|
def loadrpcservices(self):
|
||||||
# Create a dict of abbreviation=>BitcoinRPC objcet relation
|
# Create a dict of abbreviation=>BitcoinRPC objcet relation
|
||||||
self.log.info("CryptoWalletRPC: loadrpcservices: connecting to RPCs")
|
self.log.info("CryptoWalletRPC: loadrpcservices: connecting to RPCs")
|
||||||
for key in self.config["types"]:
|
for abbr, coin in self.config["types"].items():
|
||||||
self.rpcservices[key.lower()] = BitcoinRPC(self, key, self.config["types"][key]["host"],
|
self.rpcservices[abbr.lower()] = BitcoinRPC(self,
|
||||||
self.config["types"][key]["port"],
|
abbr.lower(),
|
||||||
self.config["types"][key]["username"],
|
coin["name"],
|
||||||
self.config["types"][key]["password"],
|
coin["host"],
|
||||||
self.config["types"][key]["precision"],
|
coin["port"],
|
||||||
self.config["types"][key]["reserve"])
|
coin["username"],
|
||||||
|
coin["password"],
|
||||||
|
coin["precision"],
|
||||||
|
coin["reserve"],
|
||||||
|
re.compile(coin["addrfmt"]))
|
||||||
|
|
||||||
def getRpc(self, currencyAbbr):
|
def getRpc(self, currencyAbbr):
|
||||||
# Return the rpc for the currency requested
|
# Return the rpc for the currency requested
|
||||||
|
@ -47,14 +52,19 @@ class CryptoWalletRPC(ModuleBase):
|
||||||
supported = self.getSupported()
|
supported = self.getSupported()
|
||||||
return abbr.lower() in supported
|
return abbr.lower() in supported
|
||||||
|
|
||||||
|
# def validate_addr(self, coin_abbr, address):
|
||||||
|
# client = self.getRpc(coin_abbr.lower())
|
||||||
|
# if not client or not client.validate_addr(:
|
||||||
|
# return False
|
||||||
|
|
||||||
def getInfo(self, abbr):
|
def getInfo(self, abbr):
|
||||||
# return the coin's info from config
|
# return the coin's info from config
|
||||||
if self.isSupported(abbr):
|
if self.isSupported(abbr):
|
||||||
return self.config["types"][abbr.upper()]
|
return self.config["types"][abbr.upper()]
|
||||||
|
|
||||||
|
|
||||||
class BitcoinRPC:
|
class BitcoinRPC(object):
|
||||||
def __init__(self, parent, name, host, port, username, password, precision, reserve):
|
def __init__(self, parent, name, fullname, host, port, username, password, precision, reserve, addr_re):
|
||||||
# Store info and connect
|
# Store info and connect
|
||||||
self.master = parent
|
self.master = parent
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -64,12 +74,19 @@ class BitcoinRPC:
|
||||||
self.password = password
|
self.password = password
|
||||||
self.precision = precision
|
self.precision = precision
|
||||||
self.reserve = reserve
|
self.reserve = reserve
|
||||||
|
self.addr_re = addr_re
|
||||||
self.log = self.master.log
|
self.log = self.master.log
|
||||||
|
self.con = None # AuthServiceProxy (bitcoin json rpc client) stored here
|
||||||
|
Thread(target=self.ping).start() # Initiate rpc connection
|
||||||
|
|
||||||
# AuthServiceProxy (json client) stored here
|
def validate_addr(self, addr):
|
||||||
self.con = None
|
"""
|
||||||
# Connect
|
Validate an address string. Returns true if the `addr` provided is a valid address string
|
||||||
Thread(target=self.ping).start()
|
:param addr: address to validate
|
||||||
|
:type addr: str
|
||||||
|
:return: bool
|
||||||
|
"""
|
||||||
|
return True if type(addr) is str and self.addr_re.match(addr) else False
|
||||||
|
|
||||||
def getBal(self, acct):
|
def getBal(self, acct):
|
||||||
# get a balance of an address or an account
|
# get a balance of an address or an account
|
||||||
|
@ -91,7 +108,7 @@ class BitcoinRPC:
|
||||||
def canMove(self, fromAcct, toAcct, amount):
|
def canMove(self, fromAcct, toAcct, amount):
|
||||||
# true or false if fromAcct can afford to give toAcct an amount of coins
|
# true or false if fromAcct can afford to give toAcct an amount of coins
|
||||||
balfrom = self.getAcctBal(fromAcct)
|
balfrom = self.getAcctBal(fromAcct)
|
||||||
return balfrom >= amount
|
return (balfrom - self.reserve) >= amount
|
||||||
|
|
||||||
def move(self, fromAcct, toAcct, amount):
|
def move(self, fromAcct, toAcct, amount):
|
||||||
# move coins from one account to another
|
# move coins from one account to another
|
||||||
|
|
Loading…
Reference in New Issue