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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,