mm-sol 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mm_sol-0.4.0 → mm_sol-0.5.0}/.gitignore +1 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/PKG-INFO +3 -3
- {mm_sol-0.4.0 → mm_sol-0.5.0}/pyproject.toml +5 -6
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cli.py +2 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cli_utils.py +4 -6
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/transfer_cmd.py +65 -42
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/examples/balances.toml +2 -0
- mm_sol-0.5.0/src/mm_sol/cli/examples/transfer.toml +35 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/validators.py +3 -3
- {mm_sol-0.4.0 → mm_sol-0.5.0}/uv.lock +44 -66
- mm_sol-0.4.0/src/mm_sol/cli/examples/transfer.toml +0 -23
- {mm_sol-0.4.0 → mm_sol-0.5.0}/.env.example +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/README.md +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/dict.dic +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/justfile +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/account.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/balance.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/block.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/calcs.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/balance_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/balances_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/example_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/node_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/wallet/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/wallet/keypair_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/cli/cmd/wallet/mnemonic_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/constants.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/converters.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/py.typed +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/rpc.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/solana_cli.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/token.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/transfer.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/src/mm_sol/utils.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/cli/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/cli/cmd/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/cli/cmd/wallet/__init__.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/cli/cmd/wallet/test_keypair_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/cli/cmd/wallet/test_mnemonic_cmd.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/conftest.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/test_account.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/test_balance.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/test_client.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/test_converters.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/test_rpc.py +0 -0
- {mm_sol-0.4.0 → mm_sol-0.5.0}/tests/test_token.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mm-sol
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Requires-Python: >=3.12
|
|
5
5
|
Requires-Dist: base58~=2.1.1
|
|
6
6
|
Requires-Dist: jinja2>=3.1.5
|
|
7
|
-
Requires-Dist: mm-crypto-utils>=0.
|
|
7
|
+
Requires-Dist: mm-crypto-utils>=0.2.3
|
|
8
8
|
Requires-Dist: mnemonic==0.21
|
|
9
|
-
Requires-Dist: solana~=0.36.
|
|
9
|
+
Requires-Dist: solana~=0.36.5
|
|
10
10
|
Requires-Dist: typer>=0.15.1
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mm-sol"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.0"
|
|
4
4
|
description = ""
|
|
5
5
|
requires-python = ">=3.12"
|
|
6
6
|
dependencies = [
|
|
7
|
-
"mm-crypto-utils>=0.
|
|
8
|
-
"solana~=0.36.
|
|
7
|
+
"mm-crypto-utils>=0.2.3",
|
|
8
|
+
"solana~=0.36.5",
|
|
9
9
|
"base58~=2.1.1",
|
|
10
10
|
"mnemonic==0.21",
|
|
11
11
|
"typer>=0.15.1",
|
|
12
12
|
"jinja2>=3.1.5",
|
|
13
|
-
|
|
14
13
|
]
|
|
15
14
|
[project.scripts]
|
|
16
15
|
mm-sol = "mm_sol.cli.cli:app"
|
|
@@ -23,8 +22,8 @@ build-backend = "hatchling.build"
|
|
|
23
22
|
dev-dependencies = [
|
|
24
23
|
"pytest~=8.3.4",
|
|
25
24
|
"pytest-xdist~=3.6.1",
|
|
26
|
-
"ruff~=0.9.
|
|
27
|
-
"pip-audit~=2.
|
|
25
|
+
"ruff~=0.9.6",
|
|
26
|
+
"pip-audit~=2.8.0",
|
|
28
27
|
"bandit~=1.8.2",
|
|
29
28
|
"mypy~=1.15.0",
|
|
30
29
|
]
|
|
@@ -64,6 +64,7 @@ def balances_command(
|
|
|
64
64
|
def transfer_command(
|
|
65
65
|
config_path: Path,
|
|
66
66
|
print_balances: bool = typer.Option(False, "--balances", "-b", help="Print balances and exit"),
|
|
67
|
+
print_transfers: bool = typer.Option(False, "--transfers", "-t", help="Print transfers (from, to, value) and exit"),
|
|
67
68
|
print_config: bool = typer.Option(False, "--config", "-c", help="Print config and exit"),
|
|
68
69
|
config_verbose: bool = typer.Option(False, "--config-verbose", help="Print config in verbose mode and exit"),
|
|
69
70
|
emulate: bool = typer.Option(False, "--emulate", "-e", help="Emulate transaction posting"),
|
|
@@ -74,6 +75,7 @@ def transfer_command(
|
|
|
74
75
|
TransferCmdParams(
|
|
75
76
|
config_path=config_path,
|
|
76
77
|
print_balances=print_balances,
|
|
78
|
+
print_transfers=print_transfers,
|
|
77
79
|
debug=debug,
|
|
78
80
|
no_confirmation=no_confirmation,
|
|
79
81
|
emulate=emulate,
|
|
@@ -21,12 +21,10 @@ class BaseConfigParams(BaseModel):
|
|
|
21
21
|
print_config_and_exit: bool
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def print_config(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if not verbose and count_fields:
|
|
29
|
-
for k in count_fields:
|
|
24
|
+
def print_config(config: BaseConfig, exclude: set[str] | None = None, count: set[str] | None = None) -> None:
|
|
25
|
+
data = config.model_dump(exclude=exclude)
|
|
26
|
+
if count:
|
|
27
|
+
for k in count:
|
|
30
28
|
data[k] = len(data[k])
|
|
31
29
|
print_json(data)
|
|
32
30
|
|
|
@@ -5,30 +5,31 @@ from typing import Annotated, Self
|
|
|
5
5
|
|
|
6
6
|
import mm_crypto_utils
|
|
7
7
|
from loguru import logger
|
|
8
|
-
from mm_crypto_utils import AddressToPrivate,
|
|
8
|
+
from mm_crypto_utils import AddressToPrivate, Transfer
|
|
9
9
|
from mm_std import BaseConfig, Err, fatal, utc_now
|
|
10
10
|
from pydantic import AfterValidator, BeforeValidator, Field, model_validator
|
|
11
|
+
from rich.console import Console
|
|
11
12
|
from rich.live import Live
|
|
12
13
|
from rich.table import Table
|
|
13
14
|
from solders.signature import Signature
|
|
14
15
|
|
|
15
|
-
from mm_sol import transfer
|
|
16
16
|
from mm_sol.balance import get_sol_balance_with_retries, get_token_balance_with_retries
|
|
17
17
|
from mm_sol.cli import calcs, cli_utils
|
|
18
18
|
from mm_sol.cli.cli_utils import BaseConfigParams
|
|
19
19
|
from mm_sol.cli.validators import Validators
|
|
20
20
|
from mm_sol.converters import lamports_to_sol, to_token
|
|
21
21
|
from mm_sol.token import get_decimals_with_retries
|
|
22
|
+
from mm_sol.transfer import transfer_sol_with_retries, transfer_token_with_retries
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class Config(BaseConfig):
|
|
25
26
|
nodes: Annotated[list[str], BeforeValidator(Validators.nodes())]
|
|
26
|
-
|
|
27
|
+
transfers: Annotated[list[Transfer], BeforeValidator(Validators.sol_transfers())]
|
|
27
28
|
private_keys: Annotated[AddressToPrivate, BeforeValidator(Validators.sol_private_keys())]
|
|
28
29
|
proxies: Annotated[list[str], Field(default_factory=list), BeforeValidator(Validators.proxies())]
|
|
29
30
|
token: Annotated[str | None, AfterValidator(Validators.sol_address())] = None
|
|
30
31
|
token_decimals: int = -1
|
|
31
|
-
|
|
32
|
+
default_value: Annotated[str | None, AfterValidator(Validators.valid_sol_or_token_expression("balance"))] = None
|
|
32
33
|
value_min_limit: Annotated[str | None, AfterValidator(Validators.valid_sol_or_token_expression())] = None
|
|
33
34
|
delay: Annotated[str | None, AfterValidator(Validators.valid_calc_decimal_value())] = None # in seconds
|
|
34
35
|
round_ndigits: int = 5
|
|
@@ -37,19 +38,28 @@ class Config(BaseConfig):
|
|
|
37
38
|
|
|
38
39
|
@property
|
|
39
40
|
def from_addresses(self) -> list[str]:
|
|
40
|
-
return [r.from_address for r in self.
|
|
41
|
+
return [r.from_address for r in self.transfers]
|
|
41
42
|
|
|
42
43
|
@model_validator(mode="after")
|
|
43
44
|
def final_validator(self) -> Self:
|
|
44
45
|
if not self.private_keys.contains_all_addresses(self.from_addresses):
|
|
45
46
|
raise ValueError("private keys are not set for all addresses")
|
|
46
47
|
|
|
48
|
+
for transfer in self.transfers: # If value is not set for a transfer, then set it to the global value of the config.
|
|
49
|
+
if not transfer.value and self.default_value:
|
|
50
|
+
transfer.value = self.default_value
|
|
51
|
+
for transfer in self.transfers: # Check all transfers have a value.
|
|
52
|
+
if not transfer.value:
|
|
53
|
+
raise ValueError(f"{transfer.log_prefix}: value is not set")
|
|
54
|
+
|
|
47
55
|
if self.token:
|
|
48
|
-
|
|
56
|
+
if self.default_value:
|
|
57
|
+
Validators.valid_token_expression("balance")(self.default_value)
|
|
49
58
|
if self.value_min_limit:
|
|
50
59
|
Validators.valid_token_expression()(self.value_min_limit)
|
|
51
60
|
else:
|
|
52
|
-
|
|
61
|
+
if self.default_value:
|
|
62
|
+
Validators.valid_sol_expression("balance")(self.default_value)
|
|
53
63
|
if self.value_min_limit:
|
|
54
64
|
Validators.valid_sol_expression()(self.value_min_limit)
|
|
55
65
|
|
|
@@ -64,6 +74,7 @@ class Config(BaseConfig):
|
|
|
64
74
|
|
|
65
75
|
class TransferCmdParams(BaseConfigParams):
|
|
66
76
|
print_balances: bool
|
|
77
|
+
print_transfers: bool
|
|
67
78
|
debug: bool
|
|
68
79
|
no_confirmation: bool
|
|
69
80
|
emulate: bool
|
|
@@ -74,10 +85,12 @@ def run(cmd_params: TransferCmdParams) -> None:
|
|
|
74
85
|
config = Config.read_toml_config_or_exit(cmd_params.config_path)
|
|
75
86
|
|
|
76
87
|
if cmd_params.print_config_and_exit:
|
|
77
|
-
cli_utils.print_config(config,
|
|
88
|
+
cli_utils.print_config(config, exclude={"private_keys"}, count=None if cmd_params.debug else {"proxies"})
|
|
78
89
|
sys.exit(0)
|
|
79
90
|
|
|
80
|
-
|
|
91
|
+
if cmd_params.print_transfers:
|
|
92
|
+
_print_transfers(config)
|
|
93
|
+
sys.exit(0)
|
|
81
94
|
|
|
82
95
|
if cmd_params.print_balances:
|
|
83
96
|
_print_balances(config)
|
|
@@ -87,23 +100,25 @@ def run(cmd_params: TransferCmdParams) -> None:
|
|
|
87
100
|
|
|
88
101
|
|
|
89
102
|
def _run_transfers(config: Config, cmd_params: TransferCmdParams) -> None:
|
|
103
|
+
mm_crypto_utils.init_logger(cmd_params.debug, config.log_debug, config.log_info)
|
|
90
104
|
logger.info(f"transfer {cmd_params.config_path}: started at {utc_now()} UTC")
|
|
91
105
|
logger.debug(f"config={config.model_dump(exclude={'private_keys'}) | {'version': cli_utils.get_version()}}")
|
|
92
|
-
for i, route in enumerate(config.
|
|
106
|
+
for i, route in enumerate(config.transfers):
|
|
93
107
|
_transfer(route, config, cmd_params)
|
|
94
|
-
if
|
|
108
|
+
if config.delay is not None and i < len(config.transfers) - 1:
|
|
95
109
|
delay_value = mm_crypto_utils.calc_decimal_value(config.delay)
|
|
96
|
-
logger.
|
|
97
|
-
|
|
110
|
+
logger.info(f"delay {delay_value} seconds")
|
|
111
|
+
if not cmd_params.emulate:
|
|
112
|
+
time.sleep(float(delay_value))
|
|
98
113
|
logger.info(f"transfer {cmd_params.config_path}: finished at {utc_now()} UTC")
|
|
99
114
|
|
|
100
115
|
|
|
101
|
-
def _calc_value(
|
|
116
|
+
def _calc_value(transfer: Transfer, config: Config, transfer_sol_fee: int) -> int | None:
|
|
102
117
|
if config.token:
|
|
103
118
|
value_res = calcs.calc_token_value_for_address(
|
|
104
119
|
nodes=config.nodes,
|
|
105
|
-
value_expression=
|
|
106
|
-
wallet_address=
|
|
120
|
+
value_expression=transfer.value,
|
|
121
|
+
wallet_address=transfer.from_address,
|
|
107
122
|
proxies=config.proxies,
|
|
108
123
|
token_mint_address=config.token,
|
|
109
124
|
token_decimals=config.token_decimals,
|
|
@@ -111,19 +126,19 @@ def _calc_value(route: TxRoute, config: Config, transfer_sol_fee: int) -> int |
|
|
|
111
126
|
else:
|
|
112
127
|
value_res = calcs.calc_sol_value_for_address(
|
|
113
128
|
nodes=config.nodes,
|
|
114
|
-
value_expression=
|
|
115
|
-
address=
|
|
129
|
+
value_expression=transfer.value,
|
|
130
|
+
address=transfer.from_address,
|
|
116
131
|
proxies=config.proxies,
|
|
117
132
|
fee=transfer_sol_fee,
|
|
118
133
|
)
|
|
119
|
-
logger.debug(f"{
|
|
134
|
+
logger.debug(f"{transfer.log_prefix}: value={value_res.ok_or_err()}")
|
|
120
135
|
if isinstance(value_res, Err):
|
|
121
|
-
logger.info(f"{
|
|
136
|
+
logger.info(f"{transfer.log_prefix}: calc value error, {value_res.err}")
|
|
122
137
|
|
|
123
138
|
return value_res.ok
|
|
124
139
|
|
|
125
140
|
|
|
126
|
-
def _check_value_min_limit(
|
|
141
|
+
def _check_value_min_limit(transfer: Transfer, value: int, config: Config) -> bool:
|
|
127
142
|
"""Returns False if the transfer should be skipped."""
|
|
128
143
|
if config.value_min_limit:
|
|
129
144
|
if config.token:
|
|
@@ -131,7 +146,7 @@ def _check_value_min_limit(route: TxRoute, value: int, config: Config) -> bool:
|
|
|
131
146
|
else:
|
|
132
147
|
value_min_limit = calcs.calc_sol_expression(config.value_min_limit)
|
|
133
148
|
if value < value_min_limit:
|
|
134
|
-
logger.info(f"{
|
|
149
|
+
logger.info(f"{transfer.log_prefix}: value<value_min_limit, value={_value_with_suffix(value, config)}")
|
|
135
150
|
return True
|
|
136
151
|
|
|
137
152
|
|
|
@@ -141,62 +156,70 @@ def _value_with_suffix(value: int, config: Config) -> str:
|
|
|
141
156
|
return f"{lamports_to_sol(value, config.round_ndigits)}sol"
|
|
142
157
|
|
|
143
158
|
|
|
144
|
-
def _send_tx(
|
|
145
|
-
logger.debug(f"{
|
|
159
|
+
def _send_tx(transfer: Transfer, value: int, config: Config) -> Signature | None:
|
|
160
|
+
logger.debug(f"{transfer.log_prefix}: value={_value_with_suffix(value, config)}")
|
|
146
161
|
if config.token:
|
|
147
|
-
res =
|
|
162
|
+
res = transfer_token_with_retries(
|
|
148
163
|
nodes=config.nodes,
|
|
149
164
|
token_mint_address=config.token,
|
|
150
|
-
from_address=
|
|
151
|
-
private_key=config.private_keys[
|
|
152
|
-
to_address=
|
|
165
|
+
from_address=transfer.from_address,
|
|
166
|
+
private_key=config.private_keys[transfer.from_address],
|
|
167
|
+
to_address=transfer.to_address,
|
|
153
168
|
amount=value,
|
|
154
169
|
decimals=config.token_decimals,
|
|
155
170
|
proxies=config.proxies,
|
|
156
171
|
retries=3,
|
|
157
172
|
)
|
|
158
173
|
else:
|
|
159
|
-
res =
|
|
174
|
+
res = transfer_sol_with_retries(
|
|
160
175
|
nodes=config.nodes,
|
|
161
|
-
from_address=
|
|
162
|
-
private_key=config.private_keys[
|
|
163
|
-
to_address=
|
|
176
|
+
from_address=transfer.from_address,
|
|
177
|
+
private_key=config.private_keys[transfer.from_address],
|
|
178
|
+
to_address=transfer.to_address,
|
|
164
179
|
lamports=value,
|
|
165
180
|
proxies=config.proxies,
|
|
166
181
|
retries=3,
|
|
167
182
|
)
|
|
168
183
|
|
|
169
184
|
if isinstance(res, Err):
|
|
170
|
-
logger.info(f"{
|
|
185
|
+
logger.info(f"{transfer.log_prefix}: tx error {res.err}")
|
|
171
186
|
return None
|
|
172
187
|
return res.ok
|
|
173
188
|
|
|
174
189
|
|
|
175
|
-
def _transfer(
|
|
190
|
+
def _transfer(transfer: Transfer, config: Config, cmd_params: TransferCmdParams) -> None:
|
|
176
191
|
transfer_sol_fee = 5000
|
|
177
192
|
|
|
178
|
-
value = _calc_value(
|
|
193
|
+
value = _calc_value(transfer, config, transfer_sol_fee)
|
|
179
194
|
if value is None:
|
|
180
195
|
return
|
|
181
196
|
|
|
182
|
-
if not _check_value_min_limit(
|
|
197
|
+
if not _check_value_min_limit(transfer, value, config):
|
|
183
198
|
return
|
|
184
199
|
|
|
185
200
|
if cmd_params.emulate:
|
|
186
|
-
logger.info(f"{
|
|
201
|
+
logger.info(f"{transfer.log_prefix}: emulate, value={_value_with_suffix(value, config)}")
|
|
187
202
|
return
|
|
188
203
|
|
|
189
|
-
signature = _send_tx(
|
|
204
|
+
signature = _send_tx(transfer, value, config)
|
|
190
205
|
if signature is None:
|
|
191
206
|
return
|
|
192
207
|
|
|
193
208
|
status = "UNKNOWN"
|
|
194
209
|
if not cmd_params.no_confirmation:
|
|
195
|
-
logger.debug(f"{
|
|
196
|
-
if cli_utils.wait_confirmation(config.nodes, config.proxies, signature,
|
|
210
|
+
logger.debug(f"{transfer.log_prefix}: waiting for confirmation, sig={signature}")
|
|
211
|
+
if cli_utils.wait_confirmation(config.nodes, config.proxies, signature, transfer.log_prefix):
|
|
197
212
|
status = "OK"
|
|
198
213
|
|
|
199
|
-
logger.info(f"{
|
|
214
|
+
logger.info(f"{transfer.log_prefix}: sig={signature}, value={_value_with_suffix(value, config)}, status={status}")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _print_transfers(config: Config) -> None:
|
|
218
|
+
table = Table("n", "from_address", "to_address", "value", title="transfers")
|
|
219
|
+
for count, transfer in enumerate(config.transfers, start=1):
|
|
220
|
+
table.add_row(str(count), transfer.from_address, transfer.to_address, transfer.value)
|
|
221
|
+
console = Console()
|
|
222
|
+
console.print(table)
|
|
200
223
|
|
|
201
224
|
|
|
202
225
|
def _print_balances(config: Config) -> None:
|
|
@@ -206,7 +229,7 @@ def _print_balances(config: Config) -> None:
|
|
|
206
229
|
headers = ["n", "from_address", "sol", "to_address", "sol"]
|
|
207
230
|
table = Table(*headers, title="balances")
|
|
208
231
|
with Live(table, refresh_per_second=0.5):
|
|
209
|
-
for count, route in enumerate(config.
|
|
232
|
+
for count, route in enumerate(config.transfers):
|
|
210
233
|
from_sol_balance = _get_sol_balance_str(route.from_address, config)
|
|
211
234
|
to_sol_balance = _get_sol_balance_str(route.to_address, config)
|
|
212
235
|
from_t_balance = _get_token_balance_str(route.from_address, config) if config.token else ""
|
|
@@ -2,9 +2,11 @@ accounts = """
|
|
|
2
2
|
9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM # binance
|
|
3
3
|
61aq585V8cR2sZBeawJFt2NPqmN7zDi1sws4KLs5xHXV # Jupiter cold wallet
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
tokens = """
|
|
6
7
|
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v # USDC
|
|
7
8
|
JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN # JUP
|
|
8
9
|
"""
|
|
10
|
+
|
|
9
11
|
nodes = "https://api.mainnet-beta.solana.com"
|
|
10
12
|
# proxies = "env_url: MM_SOL_PROXIES_URL"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Each line is a transfer instruction, with format: from_address to_address [value]
|
|
2
|
+
# Value is optional. If value is not set, default_value will be used
|
|
3
|
+
# value is an expression that can contain variable 'balance' and 'random' function
|
|
4
|
+
transfers = """
|
|
5
|
+
# for sol transfer use 'sol' suffix, example: 1.2sol. For other tokens use 't' suffix, example: 1.2t
|
|
6
|
+
Bd8CxCTLez2ckVTqEJjuZkWjYFSRbo8fA1qYbd7yFVP9 Eaft9xXzfgbRqsHd65WspoaxTtH7pkznM9YA8tsDKGwj 1.2t
|
|
7
|
+
Fc2TRJVCpFZpRz56mFnQETctib1zwFnwHcS7HoQSgUzZ EVJctTWikt29rUXBf49tyQdK87x837HtvpCwqeSjp1Ur 0.6balance-random(1t,2.50t)-100
|
|
8
|
+
6TW4WswDgGmEB5HELBtEdwC1tQJq9Xa1msDjPw94sgai GGb7gb5EzW8GZZWX552eiC9r1SY4Pqtgbqf9UMrBrEzy # default_value will be used
|
|
9
|
+
file: /path/to/other/transfers.txt # transfers from this file will be added
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
token = "6VBTMLgv256c7scudNf8T5GoTJcEE8WfgcJhxbGYPQ8G" # if token is not specified, then SOL is used
|
|
13
|
+
|
|
14
|
+
private_keys = """
|
|
15
|
+
5VTfgpKKkckrsK33vcw6cEgv8SjLiwaorU8sd2ftjo2sx4tCV6N44dF4P9VigLaKNT2vpX3VuiFAiNpEBnMq3CiB
|
|
16
|
+
DE9poAKvs6tENFbADZ25W1zfKeiCbuDnFbafkBgo4rT28ZGkemqnF1zAqX9WGvBKUXSRVhXgX1RHe3qn11xfjR8
|
|
17
|
+
file: ./path/to/privates.txt
|
|
18
|
+
# Extra keys are not a problem, nor is their order.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# default_value is used if transfer.value is not set in transfers. It's optional.
|
|
22
|
+
default_value = "0.2balance+random(1t,2.50t)-100" # If transferring SOL, the suffix ‘sol’ is used. For any other tokens, the suffix ‘t’ is used.
|
|
23
|
+
|
|
24
|
+
delay = "random(10, 100)" # seconds, optional
|
|
25
|
+
|
|
26
|
+
proxies = """
|
|
27
|
+
http://usr:pass@123.123.123.123:1234
|
|
28
|
+
env_url: MM_SOL_PROXIES_URL
|
|
29
|
+
url: https://site.com/api/proxies
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
nodes = """
|
|
33
|
+
https://api.devnet.solana.com
|
|
34
|
+
http://localhost:8899
|
|
35
|
+
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Callable
|
|
2
2
|
|
|
3
|
-
from mm_crypto_utils import AddressToPrivate, ConfigValidators,
|
|
3
|
+
from mm_crypto_utils import AddressToPrivate, ConfigValidators, Transfer
|
|
4
4
|
|
|
5
5
|
from mm_sol.account import get_public_key, is_address
|
|
6
6
|
from mm_sol.constants import SUFFIX_DECIMALS
|
|
@@ -16,8 +16,8 @@ class Validators(ConfigValidators):
|
|
|
16
16
|
return ConfigValidators.addresses(unique, is_address=is_address)
|
|
17
17
|
|
|
18
18
|
@staticmethod
|
|
19
|
-
def
|
|
20
|
-
return ConfigValidators.
|
|
19
|
+
def sol_transfers() -> Callable[[str], list[Transfer]]:
|
|
20
|
+
return ConfigValidators.transfers(is_address)
|
|
21
21
|
|
|
22
22
|
@staticmethod
|
|
23
23
|
def sol_private_keys() -> Callable[[str], AddressToPrivate]:
|
|
@@ -298,19 +298,6 @@ wheels = [
|
|
|
298
298
|
{ url = "https://files.pythonhosted.org/packages/d5/34/e8b383f35b77c402d28563d2b8f83159319b509bc5f760b15d60b0abf165/hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c", size = 32611 },
|
|
299
299
|
]
|
|
300
300
|
|
|
301
|
-
[[package]]
|
|
302
|
-
name = "html5lib"
|
|
303
|
-
version = "1.1"
|
|
304
|
-
source = { registry = "https://pypi.org/simple" }
|
|
305
|
-
dependencies = [
|
|
306
|
-
{ name = "six" },
|
|
307
|
-
{ name = "webencodings" },
|
|
308
|
-
]
|
|
309
|
-
sdist = { url = "https://files.pythonhosted.org/packages/ac/b6/b55c3f49042f1df3dcd422b7f224f939892ee94f22abcf503a9b7339eaf2/html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f", size = 272215 }
|
|
310
|
-
wheels = [
|
|
311
|
-
{ url = "https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", size = 112173 },
|
|
312
|
-
]
|
|
313
|
-
|
|
314
301
|
[[package]]
|
|
315
302
|
name = "httpcore"
|
|
316
303
|
version = "1.0.7"
|
|
@@ -481,19 +468,19 @@ wheels = [
|
|
|
481
468
|
|
|
482
469
|
[[package]]
|
|
483
470
|
name = "mm-crypto-utils"
|
|
484
|
-
version = "0.
|
|
471
|
+
version = "0.2.3"
|
|
485
472
|
source = { registry = "https://pypi.org/simple" }
|
|
486
473
|
dependencies = [
|
|
487
474
|
{ name = "loguru" },
|
|
488
475
|
{ name = "mm-std" },
|
|
489
476
|
]
|
|
490
477
|
wheels = [
|
|
491
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
478
|
+
{ url = "https://files.pythonhosted.org/packages/78/dd/3cb0ddc4ab14a78a0e828fd1f7ca97298be8eff67b53b6198853e2013976/mm_crypto_utils-0.2.3-py3-none-any.whl", hash = "sha256:33ca42ef22c847c6f92973d7c799460926ee5c5bd7c872d3c7d19f31377e8833", size = 8257 },
|
|
492
479
|
]
|
|
493
480
|
|
|
494
481
|
[[package]]
|
|
495
482
|
name = "mm-sol"
|
|
496
|
-
version = "0.
|
|
483
|
+
version = "0.5.0"
|
|
497
484
|
source = { editable = "." }
|
|
498
485
|
dependencies = [
|
|
499
486
|
{ name = "base58" },
|
|
@@ -518,9 +505,9 @@ dev = [
|
|
|
518
505
|
requires-dist = [
|
|
519
506
|
{ name = "base58", specifier = "~=2.1.1" },
|
|
520
507
|
{ name = "jinja2", specifier = ">=3.1.5" },
|
|
521
|
-
{ name = "mm-crypto-utils", specifier = ">=0.
|
|
508
|
+
{ name = "mm-crypto-utils", specifier = ">=0.2.3" },
|
|
522
509
|
{ name = "mnemonic", specifier = "==0.21" },
|
|
523
|
-
{ name = "solana", specifier = "~=0.36.
|
|
510
|
+
{ name = "solana", specifier = "~=0.36.5" },
|
|
524
511
|
{ name = "typer", specifier = ">=0.15.1" },
|
|
525
512
|
]
|
|
526
513
|
|
|
@@ -528,10 +515,10 @@ requires-dist = [
|
|
|
528
515
|
dev = [
|
|
529
516
|
{ name = "bandit", specifier = "~=1.8.2" },
|
|
530
517
|
{ name = "mypy", specifier = "~=1.15.0" },
|
|
531
|
-
{ name = "pip-audit", specifier = "~=2.
|
|
518
|
+
{ name = "pip-audit", specifier = "~=2.8.0" },
|
|
532
519
|
{ name = "pytest", specifier = "~=8.3.4" },
|
|
533
520
|
{ name = "pytest-xdist", specifier = "~=3.6.1" },
|
|
534
|
-
{ name = "ruff", specifier = "~=0.9.
|
|
521
|
+
{ name = "ruff", specifier = "~=0.9.6" },
|
|
535
522
|
]
|
|
536
523
|
|
|
537
524
|
[[package]]
|
|
@@ -674,22 +661,22 @@ wheels = [
|
|
|
674
661
|
|
|
675
662
|
[[package]]
|
|
676
663
|
name = "pip-audit"
|
|
677
|
-
version = "2.
|
|
664
|
+
version = "2.8.0"
|
|
678
665
|
source = { registry = "https://pypi.org/simple" }
|
|
679
666
|
dependencies = [
|
|
680
667
|
{ name = "cachecontrol", extra = ["filecache"] },
|
|
681
668
|
{ name = "cyclonedx-python-lib" },
|
|
682
|
-
{ name = "html5lib" },
|
|
683
669
|
{ name = "packaging" },
|
|
684
670
|
{ name = "pip-api" },
|
|
685
671
|
{ name = "pip-requirements-parser" },
|
|
672
|
+
{ name = "platformdirs" },
|
|
686
673
|
{ name = "requests" },
|
|
687
674
|
{ name = "rich" },
|
|
688
675
|
{ name = "toml" },
|
|
689
676
|
]
|
|
690
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
677
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e8/c8/44ccea85bd2024f1ebe55eb6cdaf1f2183359176689eed3c0b01926c24ad/pip_audit-2.8.0.tar.gz", hash = "sha256:9816cbd94de6f618a8965c117433006b3d565a708dc05d5a7be47ab65b66fa05", size = 51073 }
|
|
691
678
|
wheels = [
|
|
692
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
679
|
+
{ url = "https://files.pythonhosted.org/packages/11/0c/be5c42643284b2cfc5d9d36b576b7465268a163bd7df481a3979a3d87a0b/pip_audit-2.8.0-py3-none-any.whl", hash = "sha256:200f50d56cb6fba3a9189c20d53250354f72f161d63b6ef77ae5de2b53044566", size = 57002 },
|
|
693
680
|
]
|
|
694
681
|
|
|
695
682
|
[[package]]
|
|
@@ -705,6 +692,15 @@ wheels = [
|
|
|
705
692
|
{ url = "https://files.pythonhosted.org/packages/54/d0/d04f1d1e064ac901439699ee097f58688caadea42498ec9c4b4ad2ef84ab/pip_requirements_parser-32.0.1-py3-none-any.whl", hash = "sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526", size = 35648 },
|
|
706
693
|
]
|
|
707
694
|
|
|
695
|
+
[[package]]
|
|
696
|
+
name = "platformdirs"
|
|
697
|
+
version = "4.3.6"
|
|
698
|
+
source = { registry = "https://pypi.org/simple" }
|
|
699
|
+
sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 }
|
|
700
|
+
wheels = [
|
|
701
|
+
{ url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 },
|
|
702
|
+
]
|
|
703
|
+
|
|
708
704
|
[[package]]
|
|
709
705
|
name = "pluggy"
|
|
710
706
|
version = "1.5.0"
|
|
@@ -911,27 +907,27 @@ wheels = [
|
|
|
911
907
|
|
|
912
908
|
[[package]]
|
|
913
909
|
name = "ruff"
|
|
914
|
-
version = "0.9.
|
|
915
|
-
source = { registry = "https://pypi.org/simple" }
|
|
916
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
917
|
-
wheels = [
|
|
918
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
919
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
920
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
921
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
922
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
923
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
924
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
925
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
926
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
927
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
928
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
929
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
930
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
931
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
932
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
933
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
934
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
910
|
+
version = "0.9.6"
|
|
911
|
+
source = { registry = "https://pypi.org/simple" }
|
|
912
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2a/e1/e265aba384343dd8ddd3083f5e33536cd17e1566c41453a5517b5dd443be/ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9", size = 3639454 }
|
|
913
|
+
wheels = [
|
|
914
|
+
{ url = "https://files.pythonhosted.org/packages/76/e3/3d2c022e687e18cf5d93d6bfa2722d46afc64eaa438c7fbbdd603b3597be/ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba", size = 11714128 },
|
|
915
|
+
{ url = "https://files.pythonhosted.org/packages/e1/22/aff073b70f95c052e5c58153cba735748c9e70107a77d03420d7850710a0/ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504", size = 11682539 },
|
|
916
|
+
{ url = "https://files.pythonhosted.org/packages/75/a7/f5b7390afd98a7918582a3d256cd3e78ba0a26165a467c1820084587cbf9/ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83", size = 11132512 },
|
|
917
|
+
{ url = "https://files.pythonhosted.org/packages/a6/e3/45de13ef65047fea2e33f7e573d848206e15c715e5cd56095589a7733d04/ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc", size = 11929275 },
|
|
918
|
+
{ url = "https://files.pythonhosted.org/packages/7d/f2/23d04cd6c43b2e641ab961ade8d0b5edb212ecebd112506188c91f2a6e6c/ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b", size = 11466502 },
|
|
919
|
+
{ url = "https://files.pythonhosted.org/packages/b5/6f/3a8cf166f2d7f1627dd2201e6cbc4cb81f8b7d58099348f0c1ff7b733792/ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e", size = 12676364 },
|
|
920
|
+
{ url = "https://files.pythonhosted.org/packages/f5/c4/db52e2189983c70114ff2b7e3997e48c8318af44fe83e1ce9517570a50c6/ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666", size = 13335518 },
|
|
921
|
+
{ url = "https://files.pythonhosted.org/packages/66/44/545f8a4d136830f08f4d24324e7db957c5374bf3a3f7a6c0bc7be4623a37/ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5", size = 12823287 },
|
|
922
|
+
{ url = "https://files.pythonhosted.org/packages/c5/26/8208ef9ee7431032c143649a9967c3ae1aae4257d95e6f8519f07309aa66/ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5", size = 14592374 },
|
|
923
|
+
{ url = "https://files.pythonhosted.org/packages/31/70/e917781e55ff39c5b5208bda384fd397ffd76605e68544d71a7e40944945/ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217", size = 12500173 },
|
|
924
|
+
{ url = "https://files.pythonhosted.org/packages/84/f5/e4ddee07660f5a9622a9c2b639afd8f3104988dc4f6ba0b73ffacffa9a8c/ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6", size = 11906555 },
|
|
925
|
+
{ url = "https://files.pythonhosted.org/packages/f1/2b/6ff2fe383667075eef8656b9892e73dd9b119b5e3add51298628b87f6429/ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897", size = 11538958 },
|
|
926
|
+
{ url = "https://files.pythonhosted.org/packages/3c/db/98e59e90de45d1eb46649151c10a062d5707b5b7f76f64eb1e29edf6ebb1/ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08", size = 12117247 },
|
|
927
|
+
{ url = "https://files.pythonhosted.org/packages/ec/bc/54e38f6d219013a9204a5a2015c09e7a8c36cedcd50a4b01ac69a550b9d9/ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656", size = 12554647 },
|
|
928
|
+
{ url = "https://files.pythonhosted.org/packages/a5/7d/7b461ab0e2404293c0627125bb70ac642c2e8d55bf590f6fce85f508f1b2/ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d", size = 9949214 },
|
|
929
|
+
{ url = "https://files.pythonhosted.org/packages/ee/30/c3cee10f915ed75a5c29c1e57311282d1a15855551a64795c1b2bbe5cf37/ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa", size = 10999914 },
|
|
930
|
+
{ url = "https://files.pythonhosted.org/packages/e8/a8/d71f44b93e3aa86ae232af1f2126ca7b95c0f515ec135462b3e1f351441c/ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a", size = 10177499 },
|
|
935
931
|
]
|
|
936
932
|
|
|
937
933
|
[[package]]
|
|
@@ -943,15 +939,6 @@ wheels = [
|
|
|
943
939
|
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
|
|
944
940
|
]
|
|
945
941
|
|
|
946
|
-
[[package]]
|
|
947
|
-
name = "six"
|
|
948
|
-
version = "1.16.0"
|
|
949
|
-
source = { registry = "https://pypi.org/simple" }
|
|
950
|
-
sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 }
|
|
951
|
-
wheels = [
|
|
952
|
-
{ url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 },
|
|
953
|
-
]
|
|
954
|
-
|
|
955
942
|
[[package]]
|
|
956
943
|
name = "sniffio"
|
|
957
944
|
version = "1.3.1"
|
|
@@ -972,7 +959,7 @@ wheels = [
|
|
|
972
959
|
|
|
973
960
|
[[package]]
|
|
974
961
|
name = "solana"
|
|
975
|
-
version = "0.36.
|
|
962
|
+
version = "0.36.5"
|
|
976
963
|
source = { registry = "https://pypi.org/simple" }
|
|
977
964
|
dependencies = [
|
|
978
965
|
{ name = "construct-typing" },
|
|
@@ -981,9 +968,9 @@ dependencies = [
|
|
|
981
968
|
{ name = "typing-extensions" },
|
|
982
969
|
{ name = "websockets" },
|
|
983
970
|
]
|
|
984
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
971
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c8/e7/18ffc3d25e8f772f6b20d8dfd27a0d275576403e4d52def0a94021741506/solana-0.36.5.tar.gz", hash = "sha256:8c81de111903d01b3b5659130840ee1711092ab02982cf5e1ea851ed9ddcb011", size = 52108 }
|
|
985
972
|
wheels = [
|
|
986
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
973
|
+
{ url = "https://files.pythonhosted.org/packages/f4/3f/9c6a8bff32b7b622ac1566c52bde16239290b9d1e042c1164bdba22fef8b/solana-0.36.5-py3-none-any.whl", hash = "sha256:6b2023ba8623841ccac96e73e374a9d0e0d450436d368178fdd0537ed308d04c", size = 62217 },
|
|
987
974
|
]
|
|
988
975
|
|
|
989
976
|
[[package]]
|
|
@@ -1069,15 +1056,6 @@ wheels = [
|
|
|
1069
1056
|
{ url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 },
|
|
1070
1057
|
]
|
|
1071
1058
|
|
|
1072
|
-
[[package]]
|
|
1073
|
-
name = "webencodings"
|
|
1074
|
-
version = "0.5.1"
|
|
1075
|
-
source = { registry = "https://pypi.org/simple" }
|
|
1076
|
-
sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721 }
|
|
1077
|
-
wheels = [
|
|
1078
|
-
{ url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774 },
|
|
1079
|
-
]
|
|
1080
|
-
|
|
1081
1059
|
[[package]]
|
|
1082
1060
|
name = "websockets"
|
|
1083
1061
|
version = "11.0.3"
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
routes = """
|
|
2
|
-
Bd8CxCTLez2ckVTqEJjuZkWjYFSRbo8fA1qYbd7yFVP9 Eaft9xXzfgbRqsHd65WspoaxTtH7pkznM9YA8tsDKGwj # comments are allowed
|
|
3
|
-
Fc2TRJVCpFZpRz56mFnQETctib1zwFnwHcS7HoQSgUzZ EVJctTWikt29rUXBf49tyQdK87x837HtvpCwqeSjp1Ur
|
|
4
|
-
file: /from/addresses.txt /to/addresses.txt
|
|
5
|
-
"""
|
|
6
|
-
token = "6VBTMLgv256c7scudNf8T5GoTJcEE8WfgcJhxbGYPQ8G" # if token is not specified, then SOL is used
|
|
7
|
-
private_keys = """
|
|
8
|
-
5VTfgpKKkckrsK33vcw6cEgv8SjLiwaorU8sd2ftjo2sx4tCV6N44dF4P9VigLaKNT2vpX3VuiFAiNpEBnMq3CiB
|
|
9
|
-
DE9poAKvs6tENFbADZ25W1zfKeiCbuDnFbafkBgo4rT28ZGkemqnF1zAqX9WGvBKUXSRVhXgX1RHe3qn11xfjR8
|
|
10
|
-
file: ./path/to/privates.txt
|
|
11
|
-
# Extra keys are not a problem, nor is their order.
|
|
12
|
-
"""
|
|
13
|
-
value = "0.2balance + random(1t, 2.50t) - 100" # If transferring SOL, the suffix ‘sol’ is used. For any other tokens, the suffix ‘t’ is used.
|
|
14
|
-
delay = "random(10, 100)" # seconds, optional
|
|
15
|
-
proxies = """
|
|
16
|
-
http://usr:pass@123.123.123.123:1234
|
|
17
|
-
env_url: MM_SOL_PROXIES_URL
|
|
18
|
-
url: https://site.com/api/proxies
|
|
19
|
-
"""
|
|
20
|
-
nodes = """
|
|
21
|
-
https://api.devnet.solana.com
|
|
22
|
-
http://localhost:8899
|
|
23
|
-
"""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|