Skip to content

Commit 74e536b

Browse files
authored
Merge pull request #357 from ton-blockchain/dev
Dev
2 parents 6cc6705 + 344f861 commit 74e536b

File tree

19 files changed

+880
-997
lines changed

19 files changed

+880
-997
lines changed

README.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
![GitHub stars](https://img.shields.io/github/stars/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub forks](https://img.shields.io/github/forks/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub issues](https://img.shields.io/github/issues/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub pull requests](https://img.shields.io/github/issues-pr/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub last commit](https://img.shields.io/github/last-commit/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub license](https://img.shields.io/github/license/ton-blockchain/mytonctrl?style=flat-square&logo=github)
22

3-
<!-- omit from toc -->
3+
<!-- omit from toc -->
44
# MyTonCtrl
55

66
<!-- omit from toc -->
@@ -58,12 +58,6 @@ Mytonctrl's documentation can be found at https://docs.ton.org/participate/run-n
5858
- [x] Show offers
5959
- [x] Vote for the proposal
6060
- [x] Automatic voting for previously voted proposals
61-
- [x] Domain management
62-
- [x] Rent a new domain
63-
- [x] Show rented domains
64-
- [x] Show domain status
65-
- [x] Delete domain
66-
- [ ] Automatic domain renewal
6761
- [x] Controlling the validator
6862
- [x] Participate in the election of a validator
6963
- [x] Return bet + reward

modules/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class Setting:
5454
'useDefaultCustomOverlays': Setting(None, True, 'Participate in default custom overlays node eligible to'),
5555
'defaultCustomOverlaysUrl': Setting(None, 'https://ton-blockchain.github.io/fallback_custom_overlays.json', 'Default custom overlays config url'),
5656
'debug': Setting(None, False, 'Debug mtc console mode. Prints Traceback on errors'),
57+
'subscribe_tg_channel': Setting('validator', False, 'Disables warning about subscribing to the `TON STATUS` channel'),
5758
}
5859

5960

modules/utilities.py

Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
import base64
2+
import json
3+
import os
4+
import subprocess
5+
import time
6+
7+
from mypylib.mypylib import color_print, print_table, color_text, timeago, bcolors
8+
from modules.module import MtcModule
9+
10+
11+
class UtilitiesModule(MtcModule):
12+
13+
description = ''
14+
default_value = False
15+
16+
def view_account_status(self, args):
17+
try:
18+
addrB64 = args[0]
19+
except:
20+
color_print("{red}Bad args. Usage:{endc} vas <account-addr>")
21+
return
22+
addrB64 = self.ton.get_destination_addr(addrB64)
23+
account = self.ton.GetAccount(addrB64)
24+
version = self.ton.GetVersionFromCodeHash(account.codeHash)
25+
statusTable = list()
26+
statusTable += [["Address", "Status", "Balance", "Version"]]
27+
statusTable += [[addrB64, account.status, account.balance, version]]
28+
codeHashTable = list()
29+
codeHashTable += [["Code hash"]]
30+
codeHashTable += [[account.codeHash]]
31+
historyTable = self.get_history_table(addrB64, 10)
32+
print_table(statusTable)
33+
print()
34+
print_table(codeHashTable)
35+
print()
36+
print_table(historyTable)
37+
# end define
38+
39+
def get_history_table(self, addr, limit):
40+
addr = self.ton.get_destination_addr(addr)
41+
account = self.ton.GetAccount(addr)
42+
history = self.ton.GetAccountHistory(account, limit)
43+
table = list()
44+
typeText = color_text("{red}{bold}{endc}")
45+
table += [["Time", typeText, "Coins", "From/To"]]
46+
for message in history:
47+
if message.srcAddr is None:
48+
continue
49+
srcAddrFull = f"{message.srcWorkchain}:{message.srcAddr}"
50+
destAddFull = f"{message.destWorkchain}:{message.destAddr}"
51+
if srcAddrFull == account.addrFull:
52+
type = color_text("{red}{bold}>>>{endc}")
53+
fromto = destAddFull
54+
else:
55+
type = color_text("{blue}{bold}<<<{endc}")
56+
fromto = srcAddrFull
57+
fromto = self.ton.AddrFull2AddrB64(fromto)
58+
# datetime = timestamp2datetime(message.time, "%Y.%m.%d %H:%M:%S")
59+
datetime = timeago(message.time)
60+
table += [[datetime, type, message.value, fromto]]
61+
return table
62+
# end define
63+
64+
def view_account_history(self, args):
65+
try:
66+
addr = args[0]
67+
limit = int(args[1])
68+
except:
69+
color_print("{red}Bad args. Usage:{endc} vah <account-addr> <limit>")
70+
return
71+
table = self.get_history_table(addr, limit)
72+
print_table(table)
73+
# end define
74+
75+
def create_new_bookmark(self, args):
76+
try:
77+
name = args[0]
78+
addr = args[1]
79+
except:
80+
color_print("{red}Bad args. Usage:{endc} nb <bookmark-name> <account-addr>")
81+
return
82+
if not self.ton.IsAddr(addr):
83+
raise Exception("Incorrect address")
84+
# end if
85+
86+
bookmark = dict()
87+
bookmark["name"] = name
88+
bookmark["addr"] = addr
89+
self.ton.AddBookmark(bookmark)
90+
color_print("CreatNewBookmark - {green}OK{endc}")
91+
# end define
92+
93+
def print_bookmarks_list(self, args):
94+
data = self.ton.GetBookmarks()
95+
if data is None or len(data) == 0:
96+
print("No data")
97+
return
98+
table = list()
99+
table += [["Name", "Address", "Balance / Exp. date"]]
100+
for item in data:
101+
name = item.get("name")
102+
addr = item.get("addr")
103+
bookmark_data = item.get("data")
104+
table += [[name, addr, bookmark_data]]
105+
print_table(table)
106+
# end define
107+
108+
def delete_bookmark(self, args):
109+
try:
110+
name = args[0]
111+
except:
112+
color_print("{red}Bad args. Usage:{endc} db <bookmark-name>")
113+
return
114+
self.ton.DeleteBookmark(name)
115+
color_print("DeleteBookmark - {green}OK{endc}")
116+
# end define
117+
118+
@staticmethod
119+
def reduct(item):
120+
item = str(item)
121+
if item is None:
122+
result = None
123+
else:
124+
end = len(item)
125+
result = item[0:6] + "..." + item[end - 6:end]
126+
return result
127+
# end define
128+
129+
def print_offers_list(self, args):
130+
data = self.ton.GetOffers()
131+
if data is None or len(data) == 0:
132+
print("No data")
133+
return
134+
if "--json" in args:
135+
text = json.dumps(data, indent=2)
136+
print(text)
137+
else:
138+
table = list()
139+
table += [["Hash", "Config", "Votes", "W/L", "Approved", "Is passed"]]
140+
for item in data:
141+
hash = item.get("hash")
142+
votedValidators = len(item.get("votedValidators"))
143+
wins = item.get("wins")
144+
losses = item.get("losses")
145+
wl = "{0}/{1}".format(wins, losses)
146+
approvedPercent = item.get("approvedPercent")
147+
approvedPercent_text = "{0}%".format(approvedPercent)
148+
isPassed = item.get("isPassed")
149+
if "hash" not in args:
150+
hash = self.reduct(hash)
151+
if isPassed == True:
152+
isPassed = bcolors.green_text("true")
153+
if isPassed == False:
154+
isPassed = bcolors.red_text("false")
155+
table += [[hash, item.config.id, votedValidators, wl, approvedPercent_text, isPassed]]
156+
print_table(table)
157+
# end define
158+
159+
def get_offer_diff(self, offer_hash):
160+
self.local.add_log("start GetOfferDiff function", "debug")
161+
offer = self.ton.GetOffer(offer_hash)
162+
config_id = offer["config"]["id"]
163+
config_value = offer["config"]["value"]
164+
165+
if '{' in config_value or '}' in config_value:
166+
start = config_value.find('{') + 1
167+
end = config_value.find('}')
168+
config_value = config_value[start:end]
169+
# end if
170+
171+
args = [self.ton.liteClient.appPath, "--global-config", self.ton.liteClient.configPath, "--verbosity", "0"]
172+
process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
173+
time.sleep(1)
174+
175+
fullConfigAddr = self.ton.GetFullConfigAddr()
176+
cmd = "runmethodfull {fullConfigAddr} list_proposals".format(fullConfigAddr=fullConfigAddr)
177+
process.stdin.write(cmd.encode() + b'\n')
178+
process.stdin.flush()
179+
time.sleep(1)
180+
181+
cmd = "dumpcellas ConfigParam{configId} {configValue}".format(configId=config_id, configValue=config_value)
182+
process.stdin.write(cmd.encode() + b'\n')
183+
process.stdin.flush()
184+
time.sleep(1)
185+
186+
process.terminate()
187+
text = process.stdout.read().decode()
188+
189+
lines = text.split('\n')
190+
b = len(lines)
191+
for i in range(b):
192+
line = lines[i]
193+
if "dumping cells as values of TLB type" in line:
194+
a = i + 2
195+
break
196+
# end for
197+
198+
for i in range(a, b):
199+
line = lines[i]
200+
if '(' in line:
201+
start = i
202+
break
203+
# end for
204+
205+
for i in range(a, b):
206+
line = lines[i]
207+
if '>' in line:
208+
end = i
209+
break
210+
# end for
211+
212+
buff = lines[start:end]
213+
text = "".join(buff)
214+
newData = self.ton.Tlb2Json(text)
215+
newFileName = self.ton.tempDir + "data1diff"
216+
file = open(newFileName, 'wt')
217+
newText = json.dumps(newData, indent=2)
218+
file.write(newText)
219+
file.close()
220+
221+
oldData = self.ton.GetConfig(config_id)
222+
oldFileName = self.ton.tempDir + "data2diff"
223+
file = open(oldFileName, 'wt')
224+
oldText = json.dumps(oldData, indent=2)
225+
file.write(oldText)
226+
file.close()
227+
228+
print(oldText)
229+
args = ["diff", "--color", oldFileName, newFileName]
230+
subprocess.run(args)
231+
# end define
232+
233+
def offer_diff(self, args):
234+
try:
235+
offer_hash = args[0]
236+
offer_hash = offer_hash
237+
except:
238+
color_print("{red}Bad args. Usage:{endc} od <offer-hash>")
239+
return
240+
self.get_offer_diff(offer_hash)
241+
# end define
242+
243+
def print_complaints_list(self, args):
244+
past = "past" in args
245+
data = self.ton.GetComplaints(past=past)
246+
if data is None or len(data) == 0:
247+
print("No data")
248+
return
249+
if "--json" in args:
250+
text = json.dumps(data, indent=2)
251+
print(text)
252+
else:
253+
table = list()
254+
table += [["Election id", "ADNL", "Fine (part)", "Votes", "Approved", "Is passed"]]
255+
for key, item in data.items():
256+
electionId = item.get("electionId")
257+
adnl = item.get("adnl")
258+
suggestedFine = item.get("suggestedFine")
259+
suggestedFinePart = item.get("suggestedFinePart")
260+
Fine_text = "{0} ({1})".format(suggestedFine, suggestedFinePart)
261+
votedValidators = len(item.get("votedValidators"))
262+
approvedPercent = item.get("approvedPercent")
263+
approvedPercent_text = "{0}%".format(approvedPercent)
264+
isPassed = item.get("isPassed")
265+
if "adnl" not in args:
266+
adnl = self.reduct(adnl)
267+
if isPassed:
268+
isPassed = bcolors.green_text("true")
269+
if not isPassed:
270+
isPassed = bcolors.red_text("false")
271+
table += [[electionId, adnl, Fine_text, votedValidators, approvedPercent_text, isPassed]]
272+
print_table(table)
273+
# end define
274+
275+
def print_election_entries_list(self, args):
276+
past = "past" in args
277+
data = self.ton.GetElectionEntries(past=past)
278+
if data is None or len(data) == 0:
279+
print("No data")
280+
return
281+
if "--json" in args:
282+
text = json.dumps(data, indent=2)
283+
print(text)
284+
else:
285+
table = list()
286+
table += [["ADNL", "Pubkey", "Wallet", "Stake", "Max-factor"]]
287+
for key, item in data.items():
288+
adnl = item.get("adnlAddr")
289+
pubkey = item.get("pubkey")
290+
walletAddr = item.get("walletAddr")
291+
stake = item.get("stake")
292+
maxFactor = item.get("maxFactor")
293+
if "adnl" not in args:
294+
adnl = self.reduct(adnl)
295+
if "pubkey" not in args:
296+
pubkey = self.reduct(pubkey)
297+
if "wallet" not in args:
298+
walletAddr = self.reduct(walletAddr)
299+
table += [[adnl, pubkey, walletAddr, stake, maxFactor]]
300+
print_table(table)
301+
# end define
302+
303+
def print_validator_list(self, args):
304+
past = "past" in args
305+
fast = "fast" in args
306+
data = self.ton.GetValidatorsList(past=past, fast=fast)
307+
if data is None or len(data) == 0:
308+
print("No data")
309+
return
310+
if "--json" in args:
311+
text = json.dumps(data, indent=2)
312+
print(text)
313+
else:
314+
table = list()
315+
table += [["id", "ADNL", "Pubkey", "Wallet", "Efficiency", "Online"]]
316+
for i, item in enumerate(data):
317+
adnl = item.get("adnlAddr")
318+
pubkey = item.get("pubkey")
319+
walletAddr = item.get("walletAddr")
320+
efficiency = item.get("efficiency")
321+
online = item.get("online")
322+
if "adnl" not in args:
323+
adnl = self.reduct(adnl)
324+
if "pubkey" not in args:
325+
pubkey = self.reduct(pubkey)
326+
if "wallet" not in args:
327+
walletAddr = self.reduct(walletAddr)
328+
if "offline" in args and online != False:
329+
continue
330+
if online:
331+
online = bcolors.green_text("true")
332+
if not online:
333+
online = bcolors.red_text("false")
334+
table += [[str(i), adnl, pubkey, walletAddr, efficiency, online]]
335+
print_table(table)
336+
# end define
337+
338+
def add_console_commands(self, console):
339+
console.AddItem("vas", self.view_account_status, self.local.translate("vas_cmd"))
340+
console.AddItem("vah", self.view_account_history, self.local.translate("vah_cmd"))
341+
342+
console.AddItem("nb", self.create_new_bookmark, self.local.translate("nb_cmd"))
343+
console.AddItem("bl", self.print_bookmarks_list, self.local.translate("bl_cmd"))
344+
console.AddItem("db", self.delete_bookmark, self.local.translate("db_cmd"))
345+
346+
console.AddItem("ol", self.print_offers_list, self.local.translate("ol_cmd"))
347+
console.AddItem("od", self.offer_diff, self.local.translate("od_cmd"))
348+
349+
console.AddItem("el", self.print_election_entries_list, self.local.translate("el_cmd"))
350+
console.AddItem("vl", self.print_validator_list, self.local.translate("vl_cmd"))
351+
console.AddItem("cl", self.print_complaints_list, self.local.translate("cl_cmd"))
352+

0 commit comments

Comments
 (0)