communex.cli.balance
1import re 2from typing import Optional 3 4import typer 5from typer import Context 6 7from communex._common import IPFS_REGEX, BalanceUnit, format_balance 8from communex.balance import to_nano 9from communex.cli._common import ( 10 make_custom_context, 11 print_table_from_plain_dict, 12) 13from communex.errors import ChainTransactionError 14from communex.faucet.powv2 import solve_for_difficulty_fast 15 16balance_app = typer.Typer(no_args_is_help=True) 17 18 19@balance_app.command() 20def free_balance( 21 ctx: Context, 22 key: str, 23 unit: BalanceUnit = BalanceUnit.joule, 24 password: Optional[str] = None, 25): 26 """ 27 Gets free balance of a key. 28 """ 29 context = make_custom_context(ctx) 30 client = context.com_client() 31 32 key_address = context.resolve_key_ss58(key, password) 33 34 with context.progress_status( 35 f"Getting free balance of key {key_address}..." 36 ): 37 balance = client.get_balance(key_address) 38 39 context.output(format_balance(balance, unit)) 40 41 42@balance_app.command() 43def staked_balance( 44 ctx: Context, 45 key: str, 46 unit: BalanceUnit = BalanceUnit.joule, 47 password: Optional[str] = None, 48): 49 """ 50 Gets the balance staked on the key itself. 51 """ 52 context = make_custom_context(ctx) 53 client = context.com_client() 54 55 key_address = context.resolve_key_ss58(key, password) 56 57 with context.progress_status( 58 f"Getting staked balance of key {key_address}..." 59 ): 60 result = sum(client.get_staketo(key=key_address).values()) 61 62 context.output(format_balance(result, unit)) 63 64 65@balance_app.command() 66def show( 67 ctx: Context, 68 key: str, 69 unit: BalanceUnit = BalanceUnit.joule, 70 password: Optional[str] = None, 71): 72 """ 73 Gets entire balance of a key (free balance + staked balance). 74 """ 75 context = make_custom_context(ctx) 76 client = context.com_client() 77 78 key_address = context.resolve_key_ss58(key, password) 79 80 with context.progress_status(f"Getting value of key {key_address}..."): 81 staked_balance = sum(client.get_staketo(key=key_address).values()) 82 free_balance = client.get_balance(key_address) 83 balance_sum = free_balance + staked_balance 84 85 print_table_from_plain_dict( 86 { 87 "Free": format_balance(free_balance, unit), 88 "Staked": format_balance(staked_balance, unit), 89 "Total": format_balance(balance_sum, unit), 90 }, 91 ["Result", "Amount"], 92 context.console, 93 ) 94 95 96@balance_app.command() 97def get_staked( 98 ctx: Context, 99 key: str, 100 unit: BalanceUnit = BalanceUnit.joule, 101 password: Optional[str] = None, 102): 103 """ 104 Gets total stake of a key it delegated across other keys. 105 """ 106 context = make_custom_context(ctx) 107 client = context.com_client() 108 109 key_address = context.resolve_key_ss58(key, password) 110 111 with context.progress_status(f"Getting stake of {key_address}..."): 112 result = sum(client.get_staketo(key=key_address).values()) 113 114 context.output(format_balance(result, unit)) 115 116 117@balance_app.command() 118def transfer(ctx: Context, key: str, amount: float, dest: str): 119 """ 120 Transfer amount to destination using key 121 """ 122 context = make_custom_context(ctx) 123 client = context.com_client() 124 125 nano_amount = to_nano(amount) 126 127 resolved_key = context.load_key(key, None) 128 resolved_dest = context.resolve_key_ss58(dest, None) 129 130 if not context.confirm( 131 f"Are you sure you want to transfer {amount} tokens to {dest}?" 132 ): 133 raise typer.Abort() 134 135 with context.progress_status(f"Transferring {amount} tokens to {dest}..."): 136 response = client.transfer( 137 key=resolved_key, amount=nano_amount, dest=resolved_dest 138 ) 139 140 if response.is_success: 141 context.info(f"Transferred {amount} tokens to {dest}") 142 else: 143 raise ChainTransactionError(response.error_message) # type: ignore 144 145 146@balance_app.command() 147def transfer_stake( 148 ctx: Context, key: str, amount: float, from_key: str, dest: str 149): 150 """ 151 Transfers stake of key from point A to point B 152 """ 153 context = make_custom_context(ctx) 154 client = context.com_client() 155 156 nano_amount = to_nano(amount) 157 keypair = context.load_key(key, None) 158 resolved_from = context.resolve_key_ss58(from_key) 159 resolved_dest = context.resolve_key_ss58(dest) 160 161 with context.progress_status( 162 f"Transferring {amount} tokens from {from_key} to {dest}' ..." 163 ): 164 response = client.transfer_stake( 165 key=keypair, 166 amount=nano_amount, 167 from_module_key=resolved_from, 168 dest_module_address=resolved_dest, 169 ) 170 171 if response.is_success: 172 context.info(f"Transferred {amount} tokens from {from_key} to {dest}") 173 else: 174 raise ChainTransactionError(response.error_message) # type: ignore 175 176 177@balance_app.command() 178def stake( 179 ctx: Context, 180 key: str, 181 amount: float, 182 dest: str, 183): 184 """ 185 Stake amount to destination using key 186 """ 187 context = make_custom_context(ctx) 188 client = context.com_client() 189 190 nano_amount = to_nano(amount) 191 keypair = context.load_key(key, None) 192 resolved_dest = context.resolve_key_ss58(dest, None) 193 194 delegating_message = ( 195 "By default you delegate DAO " 196 "voting power to the validator you stake to. " 197 "In case you want to change this, call: " 198 "`comx key power-delegation <key> --disable`." 199 ) 200 context.info("INFO: ", style="bold green", end="") # type: ignore 201 context.info(delegating_message) # type: ignore 202 203 with context.progress_status(f"Staking {amount} tokens to {dest}..."): 204 response = client.stake( 205 key=keypair, amount=nano_amount, dest=resolved_dest 206 ) 207 208 if response.is_success: 209 context.info(f"Staked {amount} tokens to {dest}") 210 else: 211 raise ChainTransactionError(response.error_message) # type: ignore 212 213 214@balance_app.command() 215def unstake(ctx: Context, key: str, amount: float, dest: str): 216 """ 217 Unstake amount from destination using key 218 """ 219 context = make_custom_context(ctx) 220 client = context.com_client() 221 222 nano_amount = to_nano(amount) 223 keypair = context.load_key(key, None) 224 resolved_dest = context.resolve_key_ss58(dest, None) 225 226 with context.progress_status(f"Unstaking {amount} tokens from {dest}'..."): 227 response = client.unstake( 228 key=keypair, amount=nano_amount, dest=resolved_dest 229 ) # TODO: is it right? 230 231 if response.is_success: 232 context.info(f"Unstaked {amount} tokens from {dest}") 233 else: 234 raise ChainTransactionError(response.error_message) # type: ignore 235 236 237@balance_app.command() 238def run_faucet( 239 ctx: Context, 240 key: str, 241 num_processes: Optional[int] = None, 242 num_executions: int = 1, 243): 244 context = make_custom_context(ctx) 245 use_testnet = ctx.obj.use_testnet 246 247 if not use_testnet: 248 context.error("Faucet only enabled on testnet") 249 raise typer.Exit(code=1) 250 251 resolved_key = context.load_key(key, None) 252 253 client = context.com_client() 254 for _ in range(num_executions): 255 with context.progress_status("Solving PoW..."): 256 solution = solve_for_difficulty_fast( 257 client, 258 resolved_key, 259 client.url, 260 num_processes=num_processes, 261 ) 262 with context.progress_status("Sending solution to blockchain"): 263 params = { 264 "block_number": solution.block_number, 265 "nonce": solution.nonce, 266 "work": solution.seal, 267 "key": resolved_key.ss58_address, 268 } 269 client.compose_call( 270 "faucet", 271 params=params, 272 unsigned=True, 273 module="FaucetModule", 274 key=resolved_key.ss58_address, # type: ignore 275 ) 276 277 278@balance_app.command() 279def transfer_dao_funds( 280 ctx: Context, 281 signer_key: str, 282 amount: float, 283 cid_hash: str, 284 dest: str, 285): 286 context = make_custom_context(ctx) 287 288 if not re.match(IPFS_REGEX, cid_hash): 289 context.error(f"CID provided is invalid: {cid_hash}") 290 raise typer.Exit(code=1) 291 292 ipfs_prefix = "ipfs://" 293 cid = ipfs_prefix + cid_hash 294 295 nano_amount = to_nano(amount) 296 keypair = context.load_key(signer_key, None) 297 dest = context.resolve_key_ss58(dest, None) 298 299 client = context.com_client() 300 client.add_transfer_dao_treasury_proposal(keypair, cid, nano_amount, dest)
balance_app =
<typer.main.Typer object>
@balance_app.command()
def
free_balance( ctx: typer.models.Context, key: str, unit: communex._common.BalanceUnit = <BalanceUnit.joule: 'joule'>, password: Optional[str] = None):
20@balance_app.command() 21def free_balance( 22 ctx: Context, 23 key: str, 24 unit: BalanceUnit = BalanceUnit.joule, 25 password: Optional[str] = None, 26): 27 """ 28 Gets free balance of a key. 29 """ 30 context = make_custom_context(ctx) 31 client = context.com_client() 32 33 key_address = context.resolve_key_ss58(key, password) 34 35 with context.progress_status( 36 f"Getting free balance of key {key_address}..." 37 ): 38 balance = client.get_balance(key_address) 39 40 context.output(format_balance(balance, unit))
Gets free balance of a key.
@balance_app.command()
def
staked_balance( ctx: typer.models.Context, key: str, unit: communex._common.BalanceUnit = <BalanceUnit.joule: 'joule'>, password: Optional[str] = None):
43@balance_app.command() 44def staked_balance( 45 ctx: Context, 46 key: str, 47 unit: BalanceUnit = BalanceUnit.joule, 48 password: Optional[str] = None, 49): 50 """ 51 Gets the balance staked on the key itself. 52 """ 53 context = make_custom_context(ctx) 54 client = context.com_client() 55 56 key_address = context.resolve_key_ss58(key, password) 57 58 with context.progress_status( 59 f"Getting staked balance of key {key_address}..." 60 ): 61 result = sum(client.get_staketo(key=key_address).values()) 62 63 context.output(format_balance(result, unit))
Gets the balance staked on the key itself.
@balance_app.command()
def
show( ctx: typer.models.Context, key: str, unit: communex._common.BalanceUnit = <BalanceUnit.joule: 'joule'>, password: Optional[str] = None):
66@balance_app.command() 67def show( 68 ctx: Context, 69 key: str, 70 unit: BalanceUnit = BalanceUnit.joule, 71 password: Optional[str] = None, 72): 73 """ 74 Gets entire balance of a key (free balance + staked balance). 75 """ 76 context = make_custom_context(ctx) 77 client = context.com_client() 78 79 key_address = context.resolve_key_ss58(key, password) 80 81 with context.progress_status(f"Getting value of key {key_address}..."): 82 staked_balance = sum(client.get_staketo(key=key_address).values()) 83 free_balance = client.get_balance(key_address) 84 balance_sum = free_balance + staked_balance 85 86 print_table_from_plain_dict( 87 { 88 "Free": format_balance(free_balance, unit), 89 "Staked": format_balance(staked_balance, unit), 90 "Total": format_balance(balance_sum, unit), 91 }, 92 ["Result", "Amount"], 93 context.console, 94 )
Gets entire balance of a key (free balance + staked balance).
@balance_app.command()
def
get_staked( ctx: typer.models.Context, key: str, unit: communex._common.BalanceUnit = <BalanceUnit.joule: 'joule'>, password: Optional[str] = None):
97@balance_app.command() 98def get_staked( 99 ctx: Context, 100 key: str, 101 unit: BalanceUnit = BalanceUnit.joule, 102 password: Optional[str] = None, 103): 104 """ 105 Gets total stake of a key it delegated across other keys. 106 """ 107 context = make_custom_context(ctx) 108 client = context.com_client() 109 110 key_address = context.resolve_key_ss58(key, password) 111 112 with context.progress_status(f"Getting stake of {key_address}..."): 113 result = sum(client.get_staketo(key=key_address).values()) 114 115 context.output(format_balance(result, unit))
Gets total stake of a key it delegated across other keys.
@balance_app.command()
def
transfer(ctx: typer.models.Context, key: str, amount: float, dest: str):
118@balance_app.command() 119def transfer(ctx: Context, key: str, amount: float, dest: str): 120 """ 121 Transfer amount to destination using key 122 """ 123 context = make_custom_context(ctx) 124 client = context.com_client() 125 126 nano_amount = to_nano(amount) 127 128 resolved_key = context.load_key(key, None) 129 resolved_dest = context.resolve_key_ss58(dest, None) 130 131 if not context.confirm( 132 f"Are you sure you want to transfer {amount} tokens to {dest}?" 133 ): 134 raise typer.Abort() 135 136 with context.progress_status(f"Transferring {amount} tokens to {dest}..."): 137 response = client.transfer( 138 key=resolved_key, amount=nano_amount, dest=resolved_dest 139 ) 140 141 if response.is_success: 142 context.info(f"Transferred {amount} tokens to {dest}") 143 else: 144 raise ChainTransactionError(response.error_message) # type: ignore
Transfer amount to destination using key
@balance_app.command()
def
transfer_stake( ctx: typer.models.Context, key: str, amount: float, from_key: str, dest: str):
147@balance_app.command() 148def transfer_stake( 149 ctx: Context, key: str, amount: float, from_key: str, dest: str 150): 151 """ 152 Transfers stake of key from point A to point B 153 """ 154 context = make_custom_context(ctx) 155 client = context.com_client() 156 157 nano_amount = to_nano(amount) 158 keypair = context.load_key(key, None) 159 resolved_from = context.resolve_key_ss58(from_key) 160 resolved_dest = context.resolve_key_ss58(dest) 161 162 with context.progress_status( 163 f"Transferring {amount} tokens from {from_key} to {dest}' ..." 164 ): 165 response = client.transfer_stake( 166 key=keypair, 167 amount=nano_amount, 168 from_module_key=resolved_from, 169 dest_module_address=resolved_dest, 170 ) 171 172 if response.is_success: 173 context.info(f"Transferred {amount} tokens from {from_key} to {dest}") 174 else: 175 raise ChainTransactionError(response.error_message) # type: ignore
Transfers stake of key from point A to point B
@balance_app.command()
def
stake(ctx: typer.models.Context, key: str, amount: float, dest: str):
178@balance_app.command() 179def stake( 180 ctx: Context, 181 key: str, 182 amount: float, 183 dest: str, 184): 185 """ 186 Stake amount to destination using key 187 """ 188 context = make_custom_context(ctx) 189 client = context.com_client() 190 191 nano_amount = to_nano(amount) 192 keypair = context.load_key(key, None) 193 resolved_dest = context.resolve_key_ss58(dest, None) 194 195 delegating_message = ( 196 "By default you delegate DAO " 197 "voting power to the validator you stake to. " 198 "In case you want to change this, call: " 199 "`comx key power-delegation <key> --disable`." 200 ) 201 context.info("INFO: ", style="bold green", end="") # type: ignore 202 context.info(delegating_message) # type: ignore 203 204 with context.progress_status(f"Staking {amount} tokens to {dest}..."): 205 response = client.stake( 206 key=keypair, amount=nano_amount, dest=resolved_dest 207 ) 208 209 if response.is_success: 210 context.info(f"Staked {amount} tokens to {dest}") 211 else: 212 raise ChainTransactionError(response.error_message) # type: ignore
Stake amount to destination using key
@balance_app.command()
def
unstake(ctx: typer.models.Context, key: str, amount: float, dest: str):
215@balance_app.command() 216def unstake(ctx: Context, key: str, amount: float, dest: str): 217 """ 218 Unstake amount from destination using key 219 """ 220 context = make_custom_context(ctx) 221 client = context.com_client() 222 223 nano_amount = to_nano(amount) 224 keypair = context.load_key(key, None) 225 resolved_dest = context.resolve_key_ss58(dest, None) 226 227 with context.progress_status(f"Unstaking {amount} tokens from {dest}'..."): 228 response = client.unstake( 229 key=keypair, amount=nano_amount, dest=resolved_dest 230 ) # TODO: is it right? 231 232 if response.is_success: 233 context.info(f"Unstaked {amount} tokens from {dest}") 234 else: 235 raise ChainTransactionError(response.error_message) # type: ignore
Unstake amount from destination using key
@balance_app.command()
def
run_faucet( ctx: typer.models.Context, key: str, num_processes: Optional[int] = None, num_executions: int = 1):
238@balance_app.command() 239def run_faucet( 240 ctx: Context, 241 key: str, 242 num_processes: Optional[int] = None, 243 num_executions: int = 1, 244): 245 context = make_custom_context(ctx) 246 use_testnet = ctx.obj.use_testnet 247 248 if not use_testnet: 249 context.error("Faucet only enabled on testnet") 250 raise typer.Exit(code=1) 251 252 resolved_key = context.load_key(key, None) 253 254 client = context.com_client() 255 for _ in range(num_executions): 256 with context.progress_status("Solving PoW..."): 257 solution = solve_for_difficulty_fast( 258 client, 259 resolved_key, 260 client.url, 261 num_processes=num_processes, 262 ) 263 with context.progress_status("Sending solution to blockchain"): 264 params = { 265 "block_number": solution.block_number, 266 "nonce": solution.nonce, 267 "work": solution.seal, 268 "key": resolved_key.ss58_address, 269 } 270 client.compose_call( 271 "faucet", 272 params=params, 273 unsigned=True, 274 module="FaucetModule", 275 key=resolved_key.ss58_address, # type: ignore 276 )
@balance_app.command()
def
transfer_dao_funds( ctx: typer.models.Context, signer_key: str, amount: float, cid_hash: str, dest: str):
279@balance_app.command() 280def transfer_dao_funds( 281 ctx: Context, 282 signer_key: str, 283 amount: float, 284 cid_hash: str, 285 dest: str, 286): 287 context = make_custom_context(ctx) 288 289 if not re.match(IPFS_REGEX, cid_hash): 290 context.error(f"CID provided is invalid: {cid_hash}") 291 raise typer.Exit(code=1) 292 293 ipfs_prefix = "ipfs://" 294 cid = ipfs_prefix + cid_hash 295 296 nano_amount = to_nano(amount) 297 keypair = context.load_key(signer_key, None) 298 dest = context.resolve_key_ss58(dest, None) 299 300 client = context.com_client() 301 client.add_transfer_dao_treasury_proposal(keypair, cid, nano_amount, dest)