mcm-cli 1.4.0__py3-none-any.whl → 1.4.2__py3-none-any.whl

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.
@@ -0,0 +1,317 @@
1
+ # Copyright 2023 Moloco, Inc
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from mcmcli.command.auth import AuthCommand, AuthHeaderName, AuthHeaderValue
15
+ from mcmcli.data.campaign import Campaign, CampaignList
16
+ from mcmcli.data.error import Error
17
+ from mcmcli.data.item import Item, ItemList
18
+ from mcmcli.requests import CurlString, api_request
19
+
20
+ import json
21
+ import mcmcli.command.auth
22
+ import mcmcli.command.config
23
+ import mcmcli.logging
24
+ import sys
25
+ import typer
26
+
27
+ MAX_NUM_ITEMS_PER_PAGE = 5000
28
+
29
+ app = typer.Typer(add_completion=False)
30
+
31
+ def _create_campaign_command(profile):
32
+ auth = AuthCommand(profile)
33
+ return CampaignCommand(profile, auth)
34
+
35
+ @app.command()
36
+ def list_campaigns(
37
+ account_id: str = typer.Option(help="Ad account ID"),
38
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
39
+ to_json: bool = typer.Option(False, help="Print raw output in json"),
40
+ profile: str = "default",
41
+ ):
42
+ """
43
+ List all the campaigns of an ad account.
44
+ """
45
+ c = _create_campaign_command(profile)
46
+ if c is None:
47
+ return
48
+ curl, error, campaigns = c.list_campaigns(account_id, to_curl)
49
+
50
+ if to_curl:
51
+ print(curl)
52
+ return
53
+ if error:
54
+ print(f"ERROR: {error.message}")
55
+ return
56
+ if to_json:
57
+ json_dumps = [x.model_dump_json() for x in campaigns]
58
+ print(f"[{','.join(json_dumps)}]")
59
+ return
60
+
61
+ print("Ad Account ID, Campaign ID, Ad Type, Starts At, Ends At, Is Enabled, Is Active, Campaign Title")
62
+ for c in campaigns:
63
+ print(f"{c.ad_account_id}, {c.id}, {c.ad_type}, {c.schedule.start}, {c.schedule.end}, {c.enabling_state}, {c.state}, {c.title}")
64
+
65
+ return
66
+
67
+ @app.command()
68
+ def read_campaign(
69
+ account_id: str = typer.Option(help="Ad account ID"),
70
+ campaign_id: str = typer.Option(help="Campaign ID"),
71
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
72
+ to_json: bool = typer.Option(False, help="Print raw output in json"),
73
+ profile: str = "default",
74
+ ):
75
+ """
76
+ Read the campaign information
77
+ """
78
+ command = _create_campaign_command(profile)
79
+ if command is None:
80
+ return
81
+ curl, error, c = command.read_campaign(account_id, campaign_id, to_curl)
82
+
83
+ if to_curl:
84
+ print(curl)
85
+ return
86
+ if error:
87
+ print(f"ERROR: {error.message}")
88
+ return
89
+ if to_json:
90
+ json_dumps = c.model_dump_json()
91
+ print(json_dumps)
92
+ return
93
+
94
+ print(f"Ad Account ID = {c.ad_account_id}")
95
+ print(f"Campaign ID = {c.id}")
96
+ print(f"Campaign title = {c.title}")
97
+ print(f"Ad Type = {c.ad_type}")
98
+ print(f"Campaign begins at {c.schedule.start}")
99
+ print(f"Campaign ends at {c.schedule.end}")
100
+ print(f"Budget = {int(c.budget.amount.amount_micro) / 1000000} {c.budget.amount.currency} {c.budget.period}")
101
+ print(f"Goal = {c.goal.model_dump()}")
102
+ print(f"Registered items = {c.catalog_item_ids}")
103
+
104
+ return
105
+
106
+ @app.command()
107
+ def list_campaign_items(
108
+ account_id: str = typer.Option(help="Ad account ID"),
109
+ campaign_id: str = typer.Option(help="Campaign ID"),
110
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
111
+ to_json: bool = typer.Option(False, help="Print raw output in json"),
112
+ profile: str = "default",
113
+ ):
114
+ """
115
+ List all the items of a given campaign.
116
+ """
117
+ c = _create_campaign_command(profile)
118
+ if c is None:
119
+ return
120
+
121
+
122
+ curl, error, items = c.list_campaign_items(account_id, campaign_id, to_curl)
123
+ if to_curl:
124
+ print(curl)
125
+ return
126
+ if error:
127
+ print(f"ERROR: {error.message}")
128
+ return
129
+ if to_json:
130
+ json_dumps = [x.model_dump_json() for x in items]
131
+ print(f"[{','.join(json_dumps)}]")
132
+ return
133
+
134
+ print("Ad Account Id, Campaign ID, Item ID, Is Listed In Campaign, Created At, Item Title")
135
+ for i in items:
136
+ listing_status = "Listed" if i.is_active else "Not Listed"
137
+ print(f'{account_id}, {campaign_id}, {i.id}, {listing_status}, {i.created_timestamp}, "{i.title}"')
138
+
139
+ return
140
+
141
+ @app.command()
142
+ def add_items_to_campaign(
143
+ account_id: str = typer.Option(help="Ad account ID"),
144
+ campaign_id: str = typer.Option(help="Campaign ID"),
145
+ item_ids: str = typer.Option(help="Item IDs to add separated by comma(,) like 'p123,p456"),
146
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
147
+ to_json: bool = typer.Option(False, help="Print raw output in json"),
148
+ profile: str = "default",
149
+ ):
150
+ """
151
+ Add the item IDs to the given campaign of the account
152
+ """
153
+ c = _create_campaign_command(profile)
154
+ if c is None:
155
+ return
156
+
157
+ _, error, campaign = c.read_campaign(account_id, campaign_id)
158
+ if error:
159
+ print(f"ERROR: {error.message}")
160
+ return
161
+
162
+ #
163
+ # Add the item ID to the campaign
164
+ #
165
+ x = set(campaign.catalog_item_ids) | set(item_ids.split(','))
166
+ campaign.catalog_item_ids = list(x)
167
+
168
+ #
169
+ # Update the campaign
170
+ #
171
+ curl, error, campaign = c.update_campaign(campaign, to_curl)
172
+ if to_curl:
173
+ print(curl)
174
+ return
175
+ if error:
176
+ print(f"ERROR: {error.message}")
177
+ return
178
+ if to_json:
179
+ print(campaign.model_dump_json())
180
+ return
181
+
182
+ print(f"Added the item IDs ({item_ids}) to the campaign.")
183
+ return
184
+
185
+ class CampaignCommand:
186
+ def __init__(self, profile, auth_command):
187
+ self.config = mcmcli.command.config.get_config(profile)
188
+ if (self.config is None):
189
+ print(f"ERROR: Failed to load the CLI profile", file=sys.stderr, flush=True)
190
+ sys.exit()
191
+
192
+ self.profile = profile
193
+ self.auth_command = auth_command
194
+ self.api_base_url = f"{self.config['management_api_hostname']}/rmp/mgmt/v1/platforms/{self.config['platform_id']}"
195
+ self.headers = {
196
+ "accept": "application/json",
197
+ "content-type": "application/json"
198
+ }
199
+
200
+ self.refresh_token()
201
+
202
+
203
+ def refresh_token(
204
+ self,
205
+ ) -> None:
206
+ error, auth_header_name, auth_header_value = self.auth_command.get_auth_credential()
207
+ if error:
208
+ print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
209
+ sys.exit()
210
+
211
+ self.headers[auth_header_name] = auth_header_value
212
+
213
+
214
+ def read_campaign(self, account_id, campaign_id, to_curl=False) -> tuple[CurlString, Error, Campaign]:
215
+ _api_url = f"{self.api_base_url}/ad-accounts/{account_id}/campaigns/{campaign_id}"
216
+ curl, error, json_obj = api_request('GET', to_curl, _api_url, self.headers)
217
+ if curl:
218
+ return curl, None, None
219
+ if error:
220
+ return None, error, None
221
+
222
+ campaign = Campaign(**json_obj['campaign'])
223
+ return None, None, campaign
224
+
225
+ def update_campaign(self, campaign: Campaign, to_curl=False) -> tuple[CurlString, Error, Campaign]:
226
+ if campaign is None:
227
+ return Error(code=0, message="invalid campaign info"), None
228
+
229
+ _api_url = f"{self.api_base_url}/ad-accounts/{campaign.ad_account_id}/campaigns/{campaign.id}"
230
+ _payload = {
231
+ "campaign": campaign.model_dump()
232
+ }
233
+ curl, error, json_obj = api_request('PUT', to_curl, _api_url, self.headers, _payload)
234
+ if curl:
235
+ return curl, None, None
236
+ if error:
237
+ return None, error, None
238
+
239
+ c = Campaign(**json_obj['campaign'])
240
+ return None, None, c
241
+
242
+ def list_campaigns(self, account_id, to_curl=False) -> tuple[CurlString, Error, list[Campaign]]:
243
+ _api_url = f"{self.api_base_url}/ad-accounts/{account_id}/campaigns"
244
+
245
+ curl, error, json_obj = api_request('GET', to_curl, _api_url, self.headers)
246
+ if curl:
247
+ return curl, None, None
248
+ if error:
249
+ return None, error, None
250
+
251
+ campaigns = CampaignList(**json_obj)
252
+ return None, None, campaigns.campaigns
253
+
254
+ def list_campaign_items(self, account_id, campaign_id, to_curl=False) -> tuple[CurlString, Error, list[Item]]:
255
+ _api_url = f"{self.api_base_url}/ad-accounts/{account_id}/campaigns/{campaign_id}/items"
256
+ _payload = {
257
+ "ad_account_id": account_id,
258
+ "campaign_id": campaign_id,
259
+ "search_keyword":[],
260
+ "order_by": [{
261
+ "column": "ID",
262
+ "direction": "ASC"
263
+ }],
264
+ "filter": [
265
+ {
266
+ "column": "IS_ACTIVE",
267
+ "filter_operator": "EQ",
268
+ "value": "true",
269
+ }
270
+ ],
271
+ "page_index": 1,
272
+ "page_size": MAX_NUM_ITEMS_PER_PAGE,
273
+ }
274
+
275
+ #
276
+ # Get active items
277
+ #
278
+ curl, error, active_items = self.list_campaign_items_(to_curl, _api_url, self.headers, _payload, _is_active=True)
279
+ if curl:
280
+ return curl, None, None
281
+ if error:
282
+ return None, error, None
283
+
284
+ #
285
+ # Get inactive items
286
+ #
287
+ _, error, inactive_items = self.list_campaign_items_(to_curl, _api_url, self.headers, _payload, _is_active=False)
288
+ if error:
289
+ return None, error, None
290
+
291
+ return None, None, active_items + inactive_items
292
+
293
+
294
+ def list_campaign_items_(self, to_curl, _api_url, _headers, _payload, _is_active) -> tuple[CurlString, Error, list[Item]]:
295
+ items = []
296
+ num_items = 0
297
+ page_index = 1
298
+ while True:
299
+ _payload["page_index"] = page_index
300
+ _payload["filter"][0]["value"] = "true" if _is_active else "false"
301
+
302
+ curl, error, json_obj = api_request('POST', to_curl, _api_url, _headers, _payload)
303
+ if curl:
304
+ return curl, None, None
305
+ if error:
306
+ return None, error, None
307
+
308
+ item_group = ItemList(**json_obj)
309
+ items += item_group.rows
310
+ num_items += len(item_group.rows)
311
+
312
+ if num_items >= item_group.num_counts:
313
+ break
314
+ page_index += 1
315
+
316
+ return None, None, items
317
+
mcmcli/command/config.py CHANGED
@@ -88,6 +88,8 @@ def init(profile: str = "default"):
88
88
  "decision_api_key_name": typer.prompt("Friendly name of the decision API key", default="unknown"),
89
89
  "event_api_key": typer.prompt("Event API key", default="unknown"),
90
90
  "event_api_key_name": typer.prompt("Friendly name of the event API key", default="unknown"),
91
+ "management_api_key": typer.prompt("Management API key", default="unknown"),
92
+ "management_api_key_name": typer.prompt("Friendly name of the management API key", default="unknown"),
91
93
  }
92
94
  print(f"The profile [{profile}] has been created.")
93
95
 
@@ -123,6 +123,10 @@ class DecisionCommand:
123
123
  if (self.config is None):
124
124
  print(f"ERROR: Failed to load the CLI profile", file=sys.stderr, flush=True)
125
125
  sys.exit()
126
+
127
+ if 'decision_api_key' not in self.config or self.config['decision_api_key'] is None or self.config['decision_api_key'] == "":
128
+ print(f"ERROR: Decision API key is not set in the profile [{profile}]", file=sys.stderr, flush=True)
129
+ sys.exit()
126
130
 
127
131
  self.profile = profile
128
132
  self.api_base_url = f"{self.config['decision_api_hostname']}/rmp/decision/v1/platforms/{self.config['platform_id']}"
@@ -0,0 +1,150 @@
1
+ # Copyright 2023 Moloco, Inc
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from mcmcli.command.auth import AuthCommand, AuthHeaderName, AuthHeaderValue
15
+ from mcmcli.data.error import Error
16
+ from mcmcli.data.report import Report, ReportList
17
+ from mcmcli.requests import CurlString, api_request
18
+
19
+ import json
20
+ import mcmcli.command.auth
21
+ import mcmcli.command.config
22
+ import mcmcli.logging
23
+ import mcmcli.requests
24
+ import shortuuid
25
+ import sys
26
+ import typer
27
+
28
+ app = typer.Typer(add_completion=False)
29
+
30
+ def _create_report_command(profile):
31
+ auth = AuthCommand(profile)
32
+ return ReportCommand(profile, auth)
33
+
34
+ @app.command()
35
+ def platform_summary(
36
+ start_date: str = typer.Option(help="Start date of the report window (YYYY-MM-DD)."),
37
+ end_date: str = typer.Option(help="End date of the report window (YYYY-MM-DD)."),
38
+ group_by: str = typer.Option(False, help="Group it by DATE, AD_ACCOUNT, or CAMPAIGN"),
39
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
40
+ profile: str = "default",
41
+ ):
42
+ """
43
+ Retrive the Platform-wide summary report.
44
+ """
45
+ c = _create_report_command(profile)
46
+ if c is None:
47
+ return
48
+
49
+ curl, error, ReportList = c.report_platform_summary(start_date, end_date, group_by, to_curl)
50
+ if error:
51
+ print(f"ERROR: {error.message}")
52
+ return
53
+ if to_curl:
54
+ print(curl)
55
+ return
56
+
57
+ print(ReportList.model_dump_json(indent=4))
58
+ return
59
+
60
+ @app.command()
61
+ def account_summary(
62
+ account_id: str = typer.Option(help="Ad account ID"),
63
+ start_date: str = typer.Option(help="Start date of the report window."),
64
+ end_date: str = typer.Option(help="End date of the report window."),
65
+ group_by: str = typer.Option(False, help="Group it by DATE, AD_ACCOUNT, or CAMPAIGN"),
66
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
67
+ profile: str = "default",
68
+ ):
69
+ """
70
+ Retrive the ad account summary report.
71
+ """
72
+ c = _create_report_command(profile)
73
+ if c is None:
74
+ return
75
+
76
+ curl, error, ReportList = c.report_account_summary(account_id, start_date, end_date, group_by, to_curl)
77
+ if to_curl:
78
+ print(curl)
79
+ return
80
+ if error:
81
+ print(f"ERROR: {error.message}")
82
+ return
83
+
84
+ print(ReportList.model_dump_json(indent=4))
85
+ return
86
+
87
+ class ReportCommand:
88
+ def __init__(self, profile, auth_command):
89
+ self.config = mcmcli.command.config.get_config(profile)
90
+ if (self.config is None):
91
+ print(f"ERROR: Failed to load the CLI profile", file=sys.stderr, flush=True)
92
+ sys.exit()
93
+
94
+ self.profile = profile
95
+ self.auth_command = auth_command
96
+ self.api_base_url = f"{self.config['management_api_hostname']}/rmp/mgmt/v1/platforms/{self.config['platform_id']}"
97
+ self.headers = {
98
+ "accept": "application/json",
99
+ "content-type": "application/json",
100
+ }
101
+
102
+ self.refresh_token()
103
+
104
+ def refresh_token(
105
+ self,
106
+ ) -> None:
107
+ error, auth_header_name, auth_header_value = self.auth_command.get_auth_credential()
108
+ if error:
109
+ print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
110
+ sys.exit()
111
+
112
+ self.headers[auth_header_name] = auth_header_value
113
+
114
+
115
+ def report_platform_summary(self, start_date, end_date, group_by, to_curl) -> tuple[CurlString, Error, ReportList]:
116
+ _api_url = f"{self.api_base_url}/report"
117
+ return self._report_summary(_api_url, start_date, end_date, group_by, to_curl)
118
+
119
+ def report_account_summary(self, account_id, start_date, end_date, group_by, to_curl) -> tuple[CurlString, Error, ReportList]:
120
+ _api_url = f"{self.api_base_url}/ad-accounts/{account_id}/report"
121
+ return self._report_summary(_api_url, start_date, end_date, group_by, to_curl)
122
+
123
+ def _report_summary(self, url, start_date, end_date, group_by, to_curl) -> tuple[CurlString, Error, ReportList]:
124
+ if group_by and group_by != 'DATE' and group_by != 'AD_ACCOUNT' and group_by != 'CAMPAIGN':
125
+ error = Error(code=0, message="Invalid --group-by value. It should be 'DATE', 'AD_ACCOUNT', or 'CAMPAIGN'")
126
+ return None, error, None
127
+
128
+ _payload = {
129
+ "timezone": self.config['timezone'],
130
+ "date_start": start_date,
131
+ "date_end": end_date
132
+ }
133
+ if group_by:
134
+ _payload['group_by'] = [
135
+ group_by
136
+ ]
137
+
138
+ curl, error, json_obj = api_request('POST', to_curl, url, self.headers, _payload)
139
+ if curl:
140
+ return curl, None, None
141
+ if error:
142
+ return None, error, None
143
+
144
+ report_list = ReportList(**json_obj)
145
+ if not report_list.rows:
146
+ return None, Error(code=0, message="No reports generated"), None
147
+
148
+ return None, None, report_list
149
+
150
+
mcmcli/command/wallet.py CHANGED
@@ -11,8 +11,8 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
- from datetime import datetime
14
+ from mcmcli.command.auth import AuthCommand, AuthHeaderName, AuthHeaderValue
15
+ from datetime import datetime, UTC
16
16
  from enum import Enum
17
17
  from mcmcli.data.error import Error
18
18
  from mcmcli.data.wallet import Wallet, WalletsWrapper, PlatformWalletsWrapper
@@ -48,6 +48,9 @@ def _get_wallet_balance(wallet: Wallet):
48
48
 
49
49
  return (credit_balance, prepaid_balance)
50
50
 
51
+ def _create_wallet_command(profile):
52
+ auth = AuthCommand(profile)
53
+ return WalletCommand(profile, auth)
51
54
 
52
55
  @app.command()
53
56
  def platform_balance(
@@ -57,17 +60,11 @@ def platform_balance(
57
60
  """
58
61
  Get the current balances of all ad accounts in CSV format.
59
62
  """
60
- auth = mcmcli.command.auth.AuthCommand(profile)
61
- curl, error, token = auth.get_token()
62
- if error:
63
- print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
63
+ c = _create_wallet_command(profile)
64
+ if c is None:
64
65
  return
65
66
 
66
- # Get current UTC timestamp and format it as an ISO 8601 string with microseconds
67
- current_timestamp = datetime.utcnow().isoformat(timespec='microseconds') + "Z"
68
-
69
- wc = WalletCommand(profile, auth, token.token)
70
- curl, error, platform_wallets = wc.get_platform_balance(to_curl)
67
+ curl, error, platform_wallets = c.get_platform_balance(to_curl)
71
68
  if to_curl:
72
69
  print(curl)
73
70
  return
@@ -78,6 +75,9 @@ def platform_balance(
78
75
  print(f"ERROR: Cannot find the wallets", file=sys.stderr, flush=True)
79
76
  return
80
77
 
78
+ # Get current UTC timestamp and format it as an ISO 8601 string with microseconds
79
+ current_timestamp = datetime.now(UTC).isoformat(timespec='microseconds') + "Z"
80
+
81
81
  print("ad_account_id,credit_balance,prepaid_balance,got_balance_info_at_utc")
82
82
  for account_id, account_data in platform_wallets.items():
83
83
  wallet = account_data.wallets[0]
@@ -95,14 +95,11 @@ def balance(
95
95
  """
96
96
  Retrive the current balance of the given ad account's wallet.
97
97
  """
98
- auth = mcmcli.command.auth.AuthCommand(profile)
99
- curl, error, token = auth.get_token()
100
- if error:
101
- print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
98
+ c = _create_wallet_command(profile)
99
+ if c is None:
102
100
  return
103
101
 
104
- wc = WalletCommand(profile, auth, token.token)
105
- curl, error, wallet = wc.get_balance(account_id, to_curl)
102
+ curl, error, wallet = c.get_balance(account_id, to_curl)
106
103
  if to_curl:
107
104
  print(curl)
108
105
  return
@@ -136,16 +133,12 @@ def deposit(
136
133
  """
137
134
  Add or top up the money amount to the current balance of the given ad account's wallet.
138
135
  """
139
- auth = mcmcli.command.auth.AuthCommand(profile)
140
- curl, error, token = auth.get_token()
141
- if error:
142
- print(f"ERROR: {error.message}")
136
+ c = _create_wallet_command(profile)
137
+ if c is None:
143
138
  return
144
139
 
145
- wc = WalletCommand(profile, auth, token.token)
146
-
147
140
  # Check the wallet first
148
- curl, error, wallet = wc.get_balance(account_id, to_curl=False)
141
+ curl, error, wallet = c.get_balance(account_id, to_curl=False)
149
142
  if curl:
150
143
  print(curl)
151
144
  return
@@ -154,7 +147,7 @@ def deposit(
154
147
  return
155
148
 
156
149
  # Deposit funds
157
- curl, error, wallet = wc.update_balance(OperationType.DEPOSIT, account_id, wallet.id, fund_type, fund_amount, to_curl)
150
+ curl, error, wallet = c.update_balance(OperationType.DEPOSIT, account_id, wallet.id, fund_type, fund_amount, to_curl)
158
151
  if curl:
159
152
  print(curl)
160
153
  return
@@ -187,16 +180,12 @@ def withdraw(
187
180
  """
188
181
  Withdraws the money amount from the current balance of the given ad account's wallet.
189
182
  """
190
- auth = mcmcli.command.auth.AuthCommand(profile)
191
- curl, error, token = auth.get_token()
192
- if error:
193
- print(f"ERROR: {error.message}")
183
+ c = _create_wallet_command(profile)
184
+ if c is None:
194
185
  return
195
186
 
196
- wc = WalletCommand(profile, auth, token.token)
197
-
198
187
  # Check the wallet first
199
- curl, error, wallet = wc.get_balance(account_id, to_curl=False)
188
+ curl, error, wallet = c.get_balance(account_id, to_curl=False)
200
189
  if to_curl:
201
190
  print(curl)
202
191
  return
@@ -205,7 +194,7 @@ def withdraw(
205
194
  return
206
195
 
207
196
  # Withdraw funds
208
- curl, error, wallet = wc.update_balance(OperationType.WITHDRAW, account_id, wallet.id, fund_type, fund_amount, to_curl)
197
+ curl, error, wallet = c.update_balance(OperationType.WITHDRAW, account_id, wallet.id, fund_type, fund_amount, to_curl)
209
198
  if to_curl:
210
199
  print(curl)
211
200
  return
@@ -230,8 +219,7 @@ class WalletCommand:
230
219
  def __init__(
231
220
  self,
232
221
  profile,
233
- auth_command: mcmcli.command.auth.AuthCommand,
234
- token
222
+ auth_command: AuthCommand,
235
223
  ):
236
224
  self.config = mcmcli.command.config.get_config(profile)
237
225
  if (self.config is None):
@@ -244,9 +232,22 @@ class WalletCommand:
244
232
  self.headers = {
245
233
  "accept": "application/json",
246
234
  "content-type": "application/json",
247
- "Authorization": f"Bearer {token}"
248
235
  }
249
236
 
237
+ self.refresh_token()
238
+
239
+
240
+ def refresh_token(
241
+ self,
242
+ ) -> None:
243
+ error, auth_header_name, auth_header_value = self.auth_command.get_auth_credential()
244
+ if error:
245
+ print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
246
+ sys.exit()
247
+
248
+ self.headers[auth_header_name] = auth_header_value
249
+
250
+
250
251
  def get_platform_balance(
251
252
  self,
252
253
  to_curl: bool,