mirror of
https://github.com/curly60e/pyblock.git
synced 2026-08-20 13:28:10 +02:00
rc1v0.4.0
Reformed first start - Ask if node is remote or local (lnd - bitcoin-cli) Added view onchain txs - Local & Remote Added view invoices - Local & Remote Added view channels - Local & Remote Improved "getblockaininfo" Bug Fixes
This commit is contained in:
parent
7227c78818
commit
c23ef44a8d
9 changed files with 350 additions and 216 deletions
309
PyBlock.py
309
PyBlock.py
|
|
@ -29,18 +29,37 @@ def sysinfo(): #Cpu and memory usage
|
|||
|
||||
def getblock(): # get access to bitcoin-cli with the command getblockchaininfo
|
||||
bitcoincli = " getblockchaininfo"
|
||||
os.system(path + bitcoincli)
|
||||
a = os.popen(path['bitcoincli'] + bitcoincli).read()
|
||||
b = json.loads(a)
|
||||
d = b
|
||||
print(d)
|
||||
clear()
|
||||
print("\033[1;32;40m")
|
||||
blogo()
|
||||
print("\033[0;37;40m")
|
||||
print("<<< Back to the Main Menu Press Control + C.\n\n")
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
print("""
|
||||
Chain: {}
|
||||
Blocks: {}
|
||||
Best BlockHash: {}
|
||||
Difficulty: {}
|
||||
Verification Progress: {}
|
||||
Size on Disk: {}
|
||||
Pruned: {}
|
||||
""".format(d['chain'], d['blocks'], d['bestblockhash'], d['difficulty'], d['verificationprogress'], d['size_on_disk'], d['pruned']))
|
||||
print("----------------------------------------------------------------------------------------------------------------\n")
|
||||
|
||||
def getblockcount(): # get access to bitcoin-cli with the command getblockcount
|
||||
bitcoincli = " getblockcount"
|
||||
os.system(path + bitcoincli)
|
||||
os.system(path['bitcoincli'] + bitcoincli)
|
||||
|
||||
def clear(): # clear the screen
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
||||
def getgenesis(): # get and decode Genesis block
|
||||
bitcoincli = " getblock 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f 0 | xxd -r -p | hexyl -n 256"
|
||||
os.system(path + bitcoincli)
|
||||
os.system(path['bitcoincli'] + bitcoincli)
|
||||
|
||||
def close():
|
||||
print("<<< Back to the Main Menu Press Control + C.\n\n")
|
||||
|
|
@ -48,31 +67,27 @@ def close():
|
|||
def readHexBlock(): # Hex Decoder using Hexyl on local node
|
||||
hexa = input("Add the Block Hash you want to decode: ")
|
||||
blocknumber = input("Add the Block number: ")
|
||||
decodeBlock = path + " getblock {} {}".format(hexa, blocknumber) + " | xxd -r -p | hexyl -n 256"
|
||||
decodeBlock = path['bitcoincli'] + " getblock {} {}".format(hexa, blocknumber) + " | xxd -r -p | hexyl -n 256"
|
||||
os.system(decodeBlock)
|
||||
|
||||
def readHexTx(): # Hex Decoder using Hexyl on an external node
|
||||
hexa = input("Add the Transaction ID. you want to decode: ")
|
||||
decodeTX = path + " getrawtransaction {}".format(hexa) + " | xxd -r -p | hexyl -n 256"
|
||||
decodeTX = path['bitcoincli'] + " getrawtransaction {}".format(hexa) + " | xxd -r -p | hexyl -n 256"
|
||||
os.system(decodeTX)
|
||||
|
||||
def prt():
|
||||
print("\033[1;32;40m")
|
||||
blogo()
|
||||
#tprint("PyBLOCK", font="rnd-large") # random title design
|
||||
print("\033[0;37;40m")
|
||||
|
||||
def tmp():
|
||||
t.sleep(15)
|
||||
|
||||
#-----
|
||||
|
||||
|
||||
def console(): # get into the console from bitcoin-cli
|
||||
print("\t\033[0;37;40mThis is \033[1;33;40mBitcoin-cli's \033[0;37;40mconsole. Type your respective commands you want to display.\n\n")
|
||||
while True:
|
||||
cle = input("\033[1;32;40mconsole $>: \033[0;37;40m")
|
||||
lsd = os.popen(path + " " + cle)
|
||||
lsd = os.popen(path['bitcoincli'] + " " + cle)
|
||||
lsd0 = lsd.read()
|
||||
lsd1 = str(lsd0)
|
||||
print(lsd1)
|
||||
|
|
@ -127,117 +142,16 @@ def artist(): # here we convert the result of the command 'getblockcount' on a r
|
|||
raise
|
||||
|
||||
def design():
|
||||
bitcoinclient = path + " getblockcount"
|
||||
bitcoinclient = path['bitcoincli'] + " getblockcount"
|
||||
block = os.popen(str(bitcoinclient)).read() # 'getblockcount' convert to string
|
||||
b = block
|
||||
print("\033[1;32;40m")
|
||||
tprint(b, font="rnd-large")
|
||||
print("\033[0;37;40m")
|
||||
#------------------------------------------- SSH connection external node --------------------------------------------
|
||||
|
||||
def userconn(): # All the connection to a remote node
|
||||
option = input("\033[1;32;40mSelect option: \033[0;37;40m")
|
||||
if option == "A" or option == "a": # Execution of the secondary Menu menuUserConn
|
||||
user = input("\033[1;36;40mUSER\033[0;37;40m@\033[1;33;40mNODE: \033[0;37;40m")
|
||||
s = input("Do you want to continue Y/n: ")
|
||||
if s == "Y" or s == "y":
|
||||
clear()
|
||||
c = input("Do you want to see custom design? Y/n: ")
|
||||
if c == "Y" or c == "y":
|
||||
while True: # connection via ssh
|
||||
try:
|
||||
clear()
|
||||
close()
|
||||
sshb = "ssh " + user + " '" + "{}".format(path) + "'" + " getblockcount"
|
||||
sshc = os.popen(sshb)
|
||||
lsd0 = sshc.read()
|
||||
lsd1 = str(lsd0)
|
||||
sshd = lsd1
|
||||
print("\033[1;32;40m")
|
||||
tprint(sshd, font="rnd-large")
|
||||
print("\033[0;37;40m")
|
||||
tmp()
|
||||
sshc.close()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menuUserConn()
|
||||
raise
|
||||
else:
|
||||
menu()
|
||||
else:
|
||||
while True: # connection via ssh
|
||||
try:
|
||||
clear()
|
||||
close()
|
||||
sshb = "ssh " + user + " '" + "{}".format(path) + "'" + " getblockchaininfo"
|
||||
os.system(sshb)
|
||||
tmp()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menuUserConn()
|
||||
raise
|
||||
else:
|
||||
menu()
|
||||
elif option == "B" or option == "b": # Decode Block 0 on HEX for external node
|
||||
user = input("\033[1;36;40mUSER\033[0;37;40m@\033[1;33;40mNODE: \033[0;37;40m")
|
||||
while True:
|
||||
clear()
|
||||
prt()
|
||||
sshb = "ssh " + user + " '" + "{}".format(path) + "'" + " getblock 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f 0 | xxd -r -p | hexyl -n 256"
|
||||
os.system(sshb)
|
||||
a = input("Do you want to return to the Node Connection Menu? Y/n: ")
|
||||
if a == "Y" or a == "y":
|
||||
menuUserConn()
|
||||
else:
|
||||
b = input("Do you want to exit? Y/n: ")
|
||||
if b == "Y" or b == "y":
|
||||
exit()
|
||||
else:
|
||||
menuUserConn()
|
||||
tmp()
|
||||
elif option == "C" or option == "c": # Block decoder to HEX for external node
|
||||
readHexBlockSsh()
|
||||
while True:
|
||||
m = input("Do you want to continue decoding? Y/n: ")
|
||||
if m == "Y" or m == "y":
|
||||
readHexBlockSsh()
|
||||
else:
|
||||
menuUserConn()
|
||||
elif option == "D" or option == "d":
|
||||
readHexTXSsh()
|
||||
while True:
|
||||
m = input("Do you want to continue decoding? Y/n: ")
|
||||
if m == "Y" or m == "y":
|
||||
readHexTXSsh()
|
||||
else:
|
||||
menuUserConn()
|
||||
elif option == "R" or option == "r":
|
||||
menu()
|
||||
|
||||
#------------------------------------------- End SSH connection external node --------------------------------------------
|
||||
|
||||
|
||||
|
||||
#--------------------------------- Hex Block Decoder Functions -------------------------------------
|
||||
|
||||
def readHexBlockSsh(): # Hex Decoder using Hexyl on an external node
|
||||
user = input("\033[1;36;40mUSER\033[0;37;40m@\033[1;33;40mNODE: \033[0;37;40m")
|
||||
clear()
|
||||
prt()
|
||||
hexa = input("Add the Block Hash you want to decode: ")
|
||||
blocknumber = input("Add the Block number: ")
|
||||
decodeBlock = "ssh " + user + " '" + "{}".format(path) + "'" + " getblock {} {}".format(hexa, blocknumber) + " | xxd -r -p | hexyl -n 256"
|
||||
clear()
|
||||
prt()
|
||||
os.system(decodeBlock)
|
||||
|
||||
def readHexTXSsh(): # Hex Decoder using Hexyl on an external node
|
||||
user = input("\033[1;36;40mUSER\033[0;37;40m@\033[1;33;40mNODE: \033[0;37;40m")
|
||||
clear()
|
||||
prt()
|
||||
hexa = input("Add the Transaction ID. you want to decode: ")
|
||||
decodeTX = "ssh " + user + " '" + "{}".format(path) + "'" + " getrawtransaction {}".format(hexa) + " | xxd -r -p | hexyl -n 256"
|
||||
clear()
|
||||
prt()
|
||||
os.system(decodeTX)
|
||||
|
||||
def getrawtx(): # show confirmatins from transactions
|
||||
tx = input("Insert your TxID: ")
|
||||
while True:
|
||||
|
|
@ -251,7 +165,7 @@ def getrawtx(): # show confirmatins from transactions
|
|||
You can decode that block in HEX and see what's inside.\033[0;37;40m""")
|
||||
t.sleep(10)
|
||||
else:
|
||||
lsd = os.popen(path + bitcoincli + tx + " 1")
|
||||
lsd = os.popen(path['bitcoincli'] + bitcoincli + tx + " 1")
|
||||
lsd0 = lsd.read()
|
||||
lsd1 = str(lsd0)
|
||||
lsda = lsd1.split(',')
|
||||
|
|
@ -272,15 +186,15 @@ def menu(): #Main Menu
|
|||
sysinfo()
|
||||
print("""\t\t
|
||||
\033[1;31;40mPyBLOCK\033[0;37;40m Menu
|
||||
Local Node
|
||||
Version 0.4.0
|
||||
|
||||
\033[1;31;40mA.\033[0;37;40m Run PyBLOCK in your own node
|
||||
\033[1;32;40mB.\033[0;37;40m Show Blockchain information in your own node
|
||||
\033[1;31;40mA.\033[0;37;40m Run PyBLOCK
|
||||
\033[1;32;40mB.\033[0;37;40m Show Blockchain information
|
||||
\033[1;32;40mC.\033[0;37;40m Show the Genesis Block
|
||||
\033[1;32;40mD.\033[0;37;40m Decode in HEX any block
|
||||
\033[1;32;40mE.\033[0;37;40m Decode in HEX any transaction
|
||||
\033[1;32;40mF.\033[0;37;40m Show confirmations from a transaction
|
||||
\033[1;32;40mG.\033[0;37;40m Connect to an external node through SSH
|
||||
\033[1;32;40mH.\033[0;37;40m Advanced
|
||||
\033[1;33;40mL.\033[0;37;40m Lightning Network
|
||||
\033[1;34;40mS.\033[0;37;40m SatNode
|
||||
|
|
@ -295,15 +209,18 @@ def menuUserConn(): #Menu before connection over ssh
|
|||
sysinfo()
|
||||
print("""\t\t
|
||||
\033[1;31;40mPyBLOCK\033[0;37;40m Menu
|
||||
Remote Node RPC
|
||||
Version 0.4.0
|
||||
|
||||
\033[1;32;40mA.\033[0;37;40m Run PyBLOCK in this external node
|
||||
\033[1;32;40mB.\033[0;37;40m Show the Genesis Block
|
||||
\033[1;32;40mC.\033[0;37;40m Decode in HEX any block
|
||||
\033[1;32;40mD.\033[0;37;40m Decode in HEX any transaction
|
||||
\033[1;36;40mR.\033[0;37;40m Return Main Menu
|
||||
\033[1;31;40mA.\033[0;37;40m Run PyBLOCK
|
||||
\033[1;32;40mB.\033[0;37;40m Show Blockchain information
|
||||
\033[1;33;40mL.\033[0;37;40m Lightning Network
|
||||
\033[1;32;40mH.\033[0;37;40m Advanced
|
||||
\033[1;34;40mS.\033[0;37;40m SatNode
|
||||
\033[1;35;40mX.\033[0;37;40m Donate
|
||||
\033[1;33;40mQ.\033[0;37;40m Exit
|
||||
\n\n""")
|
||||
userconn()
|
||||
menuRemote(input("\033[1;32;40mSelect option: \033[0;37;40m"))
|
||||
|
||||
def advanceMenu(): # Advanced Menu
|
||||
clear()
|
||||
|
|
@ -392,7 +309,10 @@ def menuLND():
|
|||
\033[1;32;40mI.\033[0;37;40m New Invoice
|
||||
\033[1;31;40mP.\033[0;37;40m Pay Invoice
|
||||
\033[1;32;40mQ.\033[0;37;40m Channel Balance
|
||||
\033[1;31;40mL.\033[0;37;40m List Invoices
|
||||
\033[1;32;40mC.\033[0;37;40m Show Channels
|
||||
\033[1;33;40mB.\033[0;37;40m New Bitcoin Address
|
||||
\033[1;33;40mX.\033[0;37;40m List Onchain Transactions
|
||||
\033[1;32;40mS.\033[0;37;40m Check if invoice was paid
|
||||
\033[1;32;40mN.\033[0;37;40m Get Node Info
|
||||
\033[1;32;40mO.\033[0;37;40m Onchain Balance
|
||||
|
|
@ -424,9 +344,17 @@ def menuLNDLOCAL():
|
|||
\n\n""")
|
||||
menuLNlocal(input("\033[1;32;40mSelect option: \033[0;37;40m"))
|
||||
|
||||
def menuSelection():
|
||||
def menuSelection():
|
||||
path = {"ip_port":"", "rpcuser":"", "rpcpass":"", "bitcoincli":""}
|
||||
pathv = pickle.load(open("bclock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
path = pathv # Copy the variable pathv to 'path'
|
||||
if path['bitcoincli']:
|
||||
menu()
|
||||
else:
|
||||
menuUserConn()
|
||||
|
||||
def menuSelectionLN():
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "lncli":""}
|
||||
|
||||
lndconnectData = pickle.load(open("blndconnect.conf", "rb")) # Load the file 'bclock.conf'
|
||||
lndconnectload = lndconnectData # Copy the variable pathv to 'path'
|
||||
if lndconnectload['lncli']:
|
||||
|
|
@ -447,7 +375,7 @@ def menuA(menuS): #Execution of the Main Menu options
|
|||
getblock()
|
||||
tmp()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuS == "C" or menuS == "c":
|
||||
clear()
|
||||
|
|
@ -455,7 +383,7 @@ def menuA(menuS): #Execution of the Main Menu options
|
|||
getgenesis()
|
||||
a = input("Do you want to return to the Main Menu? Y/n: ")
|
||||
if a == "Y" or a == "y":
|
||||
menu()
|
||||
menuSelection()
|
||||
else:
|
||||
b = input("Do you want to exit? Y/n: ")
|
||||
if b == "Y" or b == "y":
|
||||
|
|
@ -469,7 +397,7 @@ def menuA(menuS): #Execution of the Main Menu options
|
|||
nodeconnection.close()
|
||||
exit()
|
||||
else:
|
||||
menu()
|
||||
menuSelection()
|
||||
elif menuS == "D" or menuS == "d":
|
||||
clear()
|
||||
prt()
|
||||
|
|
@ -481,7 +409,7 @@ def menuA(menuS): #Execution of the Main Menu options
|
|||
prt()
|
||||
readHexBlock()
|
||||
else:
|
||||
menu()
|
||||
menuSelection()
|
||||
elif menuS == "E" or menuS == "e":
|
||||
clear()
|
||||
prt()
|
||||
|
|
@ -494,7 +422,7 @@ def menuA(menuS): #Execution of the Main Menu options
|
|||
sysinfo()
|
||||
readHexTx()
|
||||
else:
|
||||
menu()
|
||||
menuSelection()
|
||||
elif menuS == "F" or menuS == "f":
|
||||
getrawtx()
|
||||
elif menuS == "H" or menuS == "h":
|
||||
|
|
@ -502,7 +430,54 @@ def menuA(menuS): #Execution of the Main Menu options
|
|||
elif menuS == "L" or menuS == "l":
|
||||
clear()
|
||||
prt()
|
||||
menuSelection()
|
||||
menuSelectionLN()
|
||||
elif menuS == "Q" or menuS == "q":
|
||||
os._exit(0)
|
||||
apisnd.close()
|
||||
donation.close()
|
||||
clone.close()
|
||||
logos.close()
|
||||
feed.close()
|
||||
sysinf.close()
|
||||
nodeconnection.close()
|
||||
exit()
|
||||
elif menuS == "S" or menuS == "s":
|
||||
clear()
|
||||
prt()
|
||||
satnodeMenu()
|
||||
elif menuS == "G" or menuS == "g":
|
||||
nodeinfo()
|
||||
elif menuS == "X" or menuS == "x":
|
||||
dnt()
|
||||
elif menuS == "T" or menuS == "t": #Test feature fast access
|
||||
print("This is a test access. \n")
|
||||
screensv()
|
||||
|
||||
def menuRemote(menuS): #Execution of the Main Menu options
|
||||
if menuS == "A" or menuS == "a":
|
||||
while True:
|
||||
try:
|
||||
clear()
|
||||
close()
|
||||
remotegetblock()
|
||||
tmp()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menuUserConn()
|
||||
elif menuS == "B" or menuS == "b":
|
||||
while True:
|
||||
try:
|
||||
clear()
|
||||
close()
|
||||
remotegetblockcount()
|
||||
tmp()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menuUserConn()
|
||||
elif menuS == "H" or menuS == "h":
|
||||
advanceMenu()
|
||||
elif menuS == "L" or menuS == "l":
|
||||
clear()
|
||||
prt()
|
||||
menuSelectionLN()
|
||||
elif menuS == "Q" or menuS == "q":
|
||||
os._exit(0)
|
||||
apisnd.close()
|
||||
|
|
@ -538,6 +513,18 @@ def menuLN(menuLL):
|
|||
clear()
|
||||
prt()
|
||||
channelbalance()
|
||||
elif menuLL == "L" or menuLL == "l":
|
||||
clear()
|
||||
prt()
|
||||
listinvoice()
|
||||
elif menuLL == "X" or menuLL == "x":
|
||||
clear()
|
||||
prt()
|
||||
listonchaintxs()
|
||||
elif menuLL == "C" or menuLL == "c":
|
||||
clear()
|
||||
prt()
|
||||
channels()
|
||||
elif menuLL == "B" or menuLL == "b":
|
||||
clear()
|
||||
prt()
|
||||
|
|
@ -555,7 +542,7 @@ def menuLN(menuLL):
|
|||
prt()
|
||||
balanceOC()
|
||||
elif menuLL == "R" or menuLL == "r":
|
||||
menu()
|
||||
menuUserConn()
|
||||
|
||||
|
||||
#------------------------------------------END REMOTE
|
||||
|
|
@ -607,7 +594,7 @@ def menuLNlocal(menuLL):
|
|||
prt()
|
||||
localkeysend()
|
||||
elif menuLL == "R" or menuLL == "r":
|
||||
menu()
|
||||
menuSelection()
|
||||
|
||||
|
||||
#------------------------------------------END LOCAL
|
||||
|
|
@ -671,7 +658,7 @@ def menuB(menuR): # Advanced access Menu
|
|||
raise
|
||||
elif menuR == "R" or menuR == "r":
|
||||
try:
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
os._exit(0)
|
||||
apisnd.close()
|
||||
|
|
@ -688,7 +675,7 @@ def menuC(menuO): # Donation access Menu
|
|||
elif menuO == "B" or menuO == "b":
|
||||
dntTst()
|
||||
elif menuO == "R" or menuO == "r":
|
||||
menu()
|
||||
menuSelection()
|
||||
|
||||
def menuD(menuN): # Satnode access Menu
|
||||
if menuN == "A" or menuN == "a":
|
||||
|
|
@ -706,9 +693,9 @@ def menuD(menuN): # Satnode access Menu
|
|||
close()
|
||||
apisenderFile()
|
||||
t.sleep(30)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif message == "T" or message == "t":
|
||||
try:
|
||||
|
|
@ -717,12 +704,12 @@ def menuD(menuN): # Satnode access Menu
|
|||
close()
|
||||
apisender()
|
||||
t.sleep(30)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuN == "C" or menuN == "c":
|
||||
print("\n\t This only will work on Linux or Unix systems.\n")
|
||||
|
|
@ -730,7 +717,9 @@ def menuD(menuN): # Satnode access Menu
|
|||
if a == "Y" or a == "y":
|
||||
gitclone()
|
||||
else:
|
||||
menu()
|
||||
menuSelection()
|
||||
elif menuN == "D" or menuN == "d":
|
||||
menuSelection()
|
||||
|
||||
def menuE(menuQ): # Dev Donation access Menu
|
||||
if menuQ == "A" or menuQ == "a":
|
||||
|
|
@ -740,9 +729,9 @@ def menuE(menuQ): # Dev Donation access Menu
|
|||
close()
|
||||
donationPN()
|
||||
t.sleep(50)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuQ == "B" or menuQ == "b":
|
||||
try:
|
||||
|
|
@ -751,9 +740,9 @@ def menuE(menuQ): # Dev Donation access Menu
|
|||
close()
|
||||
donationAddr()
|
||||
t.sleep(50)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuQ == "C" or menuQ == "c":
|
||||
try:
|
||||
|
|
@ -762,12 +751,12 @@ def menuE(menuQ): # Dev Donation access Menu
|
|||
close()
|
||||
donationLN()
|
||||
t.sleep(50)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuQ == "R" or menuQ == "r":
|
||||
menu()
|
||||
menuSelection()
|
||||
|
||||
def menuF(menuV): # Tester Donation access Menu
|
||||
if menuV == "A" or menuV == "a":
|
||||
|
|
@ -777,9 +766,9 @@ def menuF(menuV): # Tester Donation access Menu
|
|||
close()
|
||||
donationAddrTst()
|
||||
t.sleep(50)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuV == "B" or menuV == "b":
|
||||
try:
|
||||
|
|
@ -788,12 +777,12 @@ def menuF(menuV): # Tester Donation access Menu
|
|||
close()
|
||||
donationLNTst()
|
||||
t.sleep(50)
|
||||
menu()
|
||||
menuSelection()
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
menu()
|
||||
menuSelection()
|
||||
raise
|
||||
elif menuV == "R" or menuV == "r":
|
||||
menu()
|
||||
menuSelection()
|
||||
|
||||
#--------------------------------- End Main Menu execution --------------------------------
|
||||
|
||||
|
|
@ -801,14 +790,20 @@ def menuF(menuV): # Tester Donation access Menu
|
|||
|
||||
while True: # Loop
|
||||
clear()
|
||||
path = ""
|
||||
path = {"ip_port":"", "rpcuser":"", "rpcpass":"", "bitcoincli":""}
|
||||
|
||||
if os.path.isfile('bclock.conf') or os.path.isfile('blnclock.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
pathv = pickle.load(open("bclock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
path = pathv # Copy the variable pathv to 'path'
|
||||
menu()
|
||||
menuSelection()
|
||||
else:
|
||||
prt()
|
||||
print("Welcome to \033[1;31;40mPyBLOCK\033[0;37;40m\n\n")
|
||||
path = input("Insert the Path to Bitcoin-Cli: ")
|
||||
print("\n\tIf you are going to use your local node leave IP:PORT/USER/PASSWORD in blank.\n")
|
||||
path['ip_port'] = "http://{}".format(input("Insert IP:PORT to access your remote Bitcoin-Cli node: "))
|
||||
path['rpcuser'] = input("RPC User: ")
|
||||
path['rpcpass'] = input("RPC Password: ")
|
||||
print("\n\tLocal Bitcoin Core Node connection.\n")
|
||||
path['bitcoincli']= input("Insert the Path to Bitcoin-Cli: ")
|
||||
pickle.dump(path, open("bclock.conf", "wb"))
|
||||
menu()
|
||||
menuSelection()
|
||||
|
|
|
|||
|
|
@ -175,10 +175,10 @@ def devAddr():
|
|||
def donate():
|
||||
print("""\t\t
|
||||
\033[1;31;40mPyBLOCK\033[0;37;40m Menu
|
||||
Version 0.3.0
|
||||
Version 0.4.0
|
||||
|
||||
\033[1;32;40mA.\033[0;37;40m Make PyBLOCK Great Again
|
||||
\033[1;32;40mB.\033[0;37;40m <<< Back Press Control + C
|
||||
<<< Back Main Menu Press Control + C
|
||||
\n\n""")
|
||||
menuB = (input("\033[1;32;40mSelect option: \033[0;37;40m"))
|
||||
if menuB == "A" or menuB == "a":
|
||||
|
|
|
|||
3
clone.py
3
clone.py
|
|
@ -1,6 +1,6 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
#Version: 0.3.0
|
||||
#Version: 0.4.0
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
|
@ -21,7 +21,6 @@ def satnode():
|
|||
except (KeyboardInterrupt, SystemExit):
|
||||
os.system("ps -ef | grep demo-rx.py | grep -v grep | awk '{print $2}' | xargs kill -9")
|
||||
|
||||
|
||||
def matrixsc():
|
||||
if os.path.isdir('$HOME/pyblock/terminal_matrix'):
|
||||
print("OK Pass")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
#Version: 0.3.0
|
||||
#Version: 0.4.0
|
||||
|
||||
import requests
|
||||
import qrcode
|
||||
|
|
|
|||
2
feed.py
2
feed.py
|
|
@ -1,6 +1,6 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
#Version: 0.3.0
|
||||
#Version: 0.4.0
|
||||
|
||||
import os
|
||||
import os.path
|
||||
|
|
|
|||
2
logos.py
2
logos.py
|
|
@ -1,6 +1,6 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
#Version: 0.3.0
|
||||
#Version: 0.4.0
|
||||
|
||||
def logoA():
|
||||
print("""\n\n\033[1;33;40m
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import pickle
|
|||
import os
|
||||
import os.path
|
||||
import qrcode
|
||||
import simplejson as json
|
||||
import time as t
|
||||
from art import *
|
||||
from pblogo import *
|
||||
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "lncli":""}
|
||||
lndconnectload = {"ip_port":"", "tls":"", "macaroon":"", "ln":""}
|
||||
|
||||
def clear(): # clear the screen
|
||||
os.system('cls' if os.name=='nt' else 'clear')
|
||||
|
|
@ -26,8 +28,53 @@ else:
|
|||
lndconnectload["tls"] = input("Insert the path to tls.cert file: ")
|
||||
lndconnectload["macaroon"] = input("Insert the path to admin.macaroon: ")
|
||||
print("\n\tLocal Lightning Node connection.\n")
|
||||
lndconnectload["lncli"] = input("Insert the path to lncli: ")
|
||||
lndconnectload["ln"] = input("Insert the path to lncli: ")
|
||||
pickle.dump(lndconnectload, open("blndconnect.conf", "wb")) # Save the file 'bclock.conf'
|
||||
|
||||
#-------------------------RPC BITCOIN NODE CONNECTION
|
||||
|
||||
def rpc(method, params=[]):
|
||||
payload = json.dumps({
|
||||
"jsonrpc": "2.0",
|
||||
"id": "minebet",
|
||||
"method": method,
|
||||
"params": params
|
||||
})
|
||||
path = {"ip_port":"", "rpcuser":"", "rpcpass":"", "bitcoincli":""}
|
||||
if os.path.isfile('bclock.conf') or os.path.isfile('blnclock.conf'): # Check if the file 'bclock.conf' is in the same folder
|
||||
pathv = pickle.load(open("bclock.conf", "rb")) # Load the file 'bclock.conf'
|
||||
path = pathv # Copy the variable pathv to 'path'
|
||||
return requests.post(path['ip_port'], auth=(path['rpcuser'], path['rpcpass']), data=payload).json()['result']
|
||||
|
||||
def remotegetblock():
|
||||
b = rpc('getblockcount')
|
||||
c = str(b)
|
||||
print("\033[1;32;40m")
|
||||
tprint(c, font="rnd-large")
|
||||
print("\033[0;37;40m")
|
||||
|
||||
def remotegetblockcount(): # get access to bitcoin-cli with the command getblockcount
|
||||
a = rpc('getblockchaininfo')
|
||||
d = a
|
||||
print(d)
|
||||
clear()
|
||||
print("\033[1;32;40m")
|
||||
blogo()
|
||||
print("\033[0;37;40m")
|
||||
print("<<< Back to the Main Menu Press Control + C.\n\n")
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
print("""
|
||||
Chain: {}
|
||||
Blocks: {}
|
||||
Best BlockHash: {}
|
||||
Difficulty: {}
|
||||
Verification Progress: {}
|
||||
Size on Disk: {}
|
||||
Pruned: {}
|
||||
""".format(d['chain'], d['blocks'], d['bestblockhash'], d['difficulty'], d['verificationprogress'], d['size_on_disk'], d['pruned']))
|
||||
print("----------------------------------------------------------------------------------------------------------------\n")
|
||||
|
||||
#-------------------------END RPC BITCOIN NODE CONNECTION
|
||||
|
||||
def locallistchaintxns():
|
||||
qr = qrcode.QRCode(
|
||||
|
|
@ -37,7 +84,7 @@ def locallistchaintxns():
|
|||
border=4,
|
||||
)
|
||||
lncli = " listchaintxns"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
n = d['transactions']
|
||||
|
|
@ -86,7 +133,7 @@ def locallistinvoices():
|
|||
border=4,
|
||||
)
|
||||
lncli = " listinvoices"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
n = d['invoices']
|
||||
|
|
@ -126,7 +173,7 @@ def locallistinvoices():
|
|||
|
||||
def locallistchannels():
|
||||
lncli = " listchannels"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
n = d['channels']
|
||||
|
|
@ -167,7 +214,7 @@ def locallistchannels():
|
|||
|
||||
def localgetinfo():
|
||||
lncli = " getinfo"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
|
|
@ -187,7 +234,7 @@ def localgetinfo():
|
|||
|
||||
def localaddinvoice():
|
||||
lncli = " addinvoice"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
qr = qrcode.QRCode(
|
||||
|
|
@ -198,7 +245,7 @@ def localaddinvoice():
|
|||
)
|
||||
amount = input("Amount in sats: ")
|
||||
memo = input("Memo: ")
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli + " --memo " + memo + "-PyBLOCK" + " --amt " + amount).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli + " --memo " + memo + "-PyBLOCK" + " --amt " + amount).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
print("\033[1;30;47m")
|
||||
|
|
@ -208,11 +255,11 @@ def localaddinvoice():
|
|||
print("Lightning Invoice: " + d['payment_request'])
|
||||
b = str(d['payment_request'])
|
||||
while True:
|
||||
lsd = os.popen(lndconnectload['lncli'] + " decodepayreq " + b).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + " decodepayreq " + b).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
r = d['payment_hash']
|
||||
lsdn = os.popen(lndconnectload['lncli'] + " lookupinvoice " + r).read()
|
||||
lsdn = os.popen(lndconnectload['ln'] + " lookupinvoice " + r).read()
|
||||
lsdn0 = str(lsdn)
|
||||
n = json.loads(lsdn0)
|
||||
if n['state'] == 'SETTLED':
|
||||
|
|
@ -235,21 +282,21 @@ def localaddinvoice():
|
|||
def localpayinvoice():
|
||||
invoice = input("Insert Invoice: ")
|
||||
lncli = " payinvoice "
|
||||
lsd = os.popen(lndconnectload['lncli'] + " decodepayreq " + invoice).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + " decodepayreq " + invoice).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
if d['num_satoshis'] == "0":
|
||||
amt = " --amt "
|
||||
amount = input("Amount in satoshis: ")
|
||||
os.system(lndconnectload['lncli'] + lncli + invoice + amt + amount)
|
||||
os.system(lndconnectload['ln'] + lncli + invoice + amt + amount)
|
||||
t.sleep(2)
|
||||
else:
|
||||
os.system(lndconnectload['lncli'] + lncli + invoice )
|
||||
os.system(lndconnectload['ln'] + lncli + invoice )
|
||||
t.sleep(2)
|
||||
|
||||
def localgetnetworkinfo():
|
||||
lncli = " getnetworkinfo"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
|
|
@ -276,11 +323,11 @@ def localkeysend():
|
|||
amount = input("\nAmount in sats: ")
|
||||
else:
|
||||
break
|
||||
os.system(lndconnectload['lncli'] + lncli + "--keysend --d=" + node + " --amt=" + amount + " --final_cltv_delta=40")
|
||||
os.system(lndconnectload['ln'] + lncli + "--keysend --d=" + node + " --amt=" + amount + " --final_cltv_delta=40")
|
||||
|
||||
def localchannelbalance():
|
||||
lncli = " channelbalance"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
|
|
@ -293,7 +340,7 @@ def localchannelbalance():
|
|||
|
||||
def localnewaddress():
|
||||
lncli = " newaddress p2wkh"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
qr = qrcode.QRCode(
|
||||
|
|
@ -311,7 +358,7 @@ def localnewaddress():
|
|||
|
||||
def localbalanceOC():
|
||||
lncli = " walletbalance"
|
||||
lsd = os.popen(lndconnectload['lncli'] + lncli).read()
|
||||
lsd = os.popen(lndconnectload['ln'] + lncli).read()
|
||||
lsd0 = str(lsd)
|
||||
d = json.loads(lsd0)
|
||||
print("\n------------------------------------------------------------------------------------")
|
||||
|
|
@ -418,14 +465,6 @@ def payinvoice():
|
|||
print("\033[0;37;40m")
|
||||
t.sleep(2)
|
||||
|
||||
def decodepayment():
|
||||
cert_path = lndconnectload["tls"]
|
||||
macaroon = codecs.encode(open(lndconnectload["macaroon"], 'rb').read(), 'hex')
|
||||
headers = {'Grpc-Metadata-macaroon': macaroon}
|
||||
dcd = input("Invoice: ")
|
||||
url = 'https://{}/v1/payreq/{}'.format(lndconnectload["ip_port"], dcd)
|
||||
r = requests.get(url, headers=headers, verify=cert_path)
|
||||
print(r.json())
|
||||
|
||||
def getnewaddress():
|
||||
cert_path = lndconnectload["tls"]
|
||||
|
|
@ -447,32 +486,54 @@ def getnewaddress():
|
|||
print("Bitcoin Address: " + addr['address'])
|
||||
input("\nContinue... ")
|
||||
|
||||
def listchaintxns():
|
||||
cert_path = lndconnectload["tls"]
|
||||
macaroon = codecs.encode(open(lndconnectload["macaroon"], 'rb').read(), 'hex')
|
||||
headers = {'Grpc-Metadata-macaroon': macaroon}
|
||||
url = 'https://{}/v1/transactions'.format(lndconnectload["ip_port"])
|
||||
r = requests.get(url, headers=headers, verify=cert_path)
|
||||
a = r.json()
|
||||
b = str(a)
|
||||
c = b.split(',')
|
||||
d = c
|
||||
for d in c:
|
||||
print(d)
|
||||
t.sleep(10)
|
||||
|
||||
def listinvoice():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
cert_path = lndconnectload["tls"]
|
||||
macaroon = codecs.encode(open(lndconnectload["macaroon"], 'rb').read(), 'hex')
|
||||
headers = {'Grpc-Metadata-macaroon': macaroon}
|
||||
url = 'https://{}/v1/invoices'.format(lndconnectload["ip_port"])
|
||||
r = requests.get(url, headers=headers, verify=cert_path)
|
||||
a = r.json()
|
||||
b = str(a)
|
||||
c = b.split(',')
|
||||
d = c
|
||||
for d in c:
|
||||
print(d)
|
||||
n = a['invoices']
|
||||
while True:
|
||||
clear()
|
||||
print("\033[1;32;40m")
|
||||
blogo()
|
||||
print("\033[0;37;40m")
|
||||
print("<<< Back to the Main Menu Press Control + C.\n\n")
|
||||
print("\tInvoices\n")
|
||||
try:
|
||||
for r in range(len(n)):
|
||||
s = n[r]
|
||||
print("Invoice: " + s['r_hash'] + " " + s['state'])
|
||||
|
||||
nd = input("\nSelect RHash: ")
|
||||
|
||||
for r in range(len(n)):
|
||||
s = n[r]
|
||||
nn = s['r_hash']
|
||||
if nd == nn:
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
print("""
|
||||
Memo: {}
|
||||
Invoice: {}
|
||||
Amount: {} sats
|
||||
State: {}
|
||||
""".format(s['memo'], s['payment_request'], s['amt_paid_sat'], s['state']))
|
||||
print("----------------------------------------------------------------------------------------------------------------\n")
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(s['payment_request'])
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
input("\nContinue... ")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
break
|
||||
input("\nContinue... ")
|
||||
|
||||
def invoicesettle():
|
||||
|
|
@ -533,13 +594,42 @@ def channels():
|
|||
url = 'https://{}/v1/channels'.format(lndconnectload["ip_port"])
|
||||
r = requests.get(url, headers=headers, verify=cert_path)
|
||||
a = r.json()
|
||||
b = str(a)
|
||||
c = b.split(',')
|
||||
d = c
|
||||
for d in c:
|
||||
print(d)
|
||||
input("\nContinue... ")
|
||||
n = a['channels']
|
||||
while True:
|
||||
clear()
|
||||
print("\033[1;32;40m")
|
||||
blogo()
|
||||
print("\033[0;37;40m")
|
||||
print("<<< Back to the Main Menu Press Control + C.\n\n")
|
||||
print("\t\nChannels\n")
|
||||
try:
|
||||
for r in range(len(n)):
|
||||
s = n[r]
|
||||
print("Node ID: " + s['remote_pubkey'])
|
||||
|
||||
nd = input("\nSelect a Node ID: ")
|
||||
|
||||
for r in range(len(n)):
|
||||
s = n[r]
|
||||
nn = s['remote_pubkey']
|
||||
if nd == nn:
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
print("""
|
||||
Active: {}
|
||||
Node ID: {}
|
||||
Channel Point: {}
|
||||
Channel Capacity: {} sats
|
||||
Local Balance: {} sats
|
||||
Remote Balance: {} sats
|
||||
Total Sent: {} sats
|
||||
Total Received: {} sats
|
||||
""".format(s['active'], s['remote_pubkey'], s['channel_point'], s['capacity'], s['local_balance'], s['remote_balance'], s['total_satoshis_sent'], s['total_satoshis_received']))
|
||||
print("----------------------------------------------------------------------------------------------------------------\n")
|
||||
|
||||
input("\nContinue... ")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
break
|
||||
|
||||
def channelbalance():
|
||||
cert_path = lndconnectload["tls"]
|
||||
macaroon = codecs.encode(open(lndconnectload["macaroon"], 'rb').read(), 'hex')
|
||||
|
|
@ -555,6 +645,56 @@ def channelbalance():
|
|||
print("----------------------------------------------------------------------------------------------------------------\n")
|
||||
input("\nContinue... ")
|
||||
|
||||
def listonchaintxs():
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_L,
|
||||
box_size=10,
|
||||
border=4,
|
||||
)
|
||||
cert_path = lndconnectload["tls"]
|
||||
macaroon = codecs.encode(open(lndconnectload["macaroon"], 'rb').read(), 'hex')
|
||||
headers = {'Grpc-Metadata-macaroon': macaroon}
|
||||
url = 'https://{}/v1/transactions'.format(lndconnectload["ip_port"])
|
||||
r = requests.get(url, headers=headers, verify=cert_path)
|
||||
a = r.json()
|
||||
n = a['transactions']
|
||||
while True:
|
||||
clear()
|
||||
print("\033[1;32;40m")
|
||||
blogo()
|
||||
print("\033[0;37;40m")
|
||||
print("<<< Back to the Main Menu Press Control + C.\n\n")
|
||||
print("\t\nTransactions\n")
|
||||
try:
|
||||
for r in range(len(n)):
|
||||
s = n[r]
|
||||
print("Transaction Hash: " + s['tx_hash'])
|
||||
nd = input("\nSelect RHash: ")
|
||||
|
||||
for r in range(len(n)):
|
||||
s = n[r]
|
||||
nn = s['tx_hash']
|
||||
trx = s['dest_addresses']
|
||||
if nd == nn:
|
||||
print("\n----------------------------------------------------------------------------------------------------------------")
|
||||
print("""
|
||||
Amount: {} sats
|
||||
Tx Hash: {}
|
||||
Block Hash: {}
|
||||
Block Height: {}
|
||||
Confirmations: {}
|
||||
Destination: {}
|
||||
""".format(s['amount'], s['tx_hash'], s['block_hash'], s['block_height'], s['num_confirmations'], trx))
|
||||
print("----------------------------------------------------------------------------------------------------------------\n")
|
||||
print("\nTransaction Hash")
|
||||
print("\033[1;30;47m")
|
||||
qr.add_data(s['tx_hash'])
|
||||
qr.print_ascii()
|
||||
print("\033[0;37;40m")
|
||||
input("\nContinue... ")
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
break
|
||||
|
||||
def balanceOC():
|
||||
cert_path = lndconnectload["tls"]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
#Version: 0.3.0
|
||||
#Version: 0.4.0
|
||||
|
||||
def blogo():
|
||||
print("""
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#Developer: Curly60e
|
||||
#PyBLOCK its a clock of the Bitcoin blockchain.
|
||||
#Version: 0.3.0
|
||||
#Version: 0.4.0
|
||||
|
||||
import psutil
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue