@monygroupcorp/micro-web3 1.2.4 → 1.3.0

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.
@@ -1,72 +1,39 @@
1
- import { Component } from '@monygroupcorp/microact';
1
+ import { Component, h } from '@monygroupcorp/microact';
2
2
  import { MessagePopup } from '../Util/MessagePopup.js';
3
3
 
4
4
  export class ApprovalModal extends Component {
5
5
  constructor(props) {
6
6
  super(props);
7
7
  console.log('[DEBUG] ApproveModal constructor called with amount:', props.amount, 'and address:', props.userAddress);
8
-
8
+
9
9
  this.blockchainService = props.blockchainService;
10
10
  this.eventBus = props.eventBus;
11
11
  this.amount = props.amount;
12
12
  this.userAddress = props.userAddress;
13
13
 
14
14
  this.messagePopup = new MessagePopup('approve-status');
15
- this.handleApprove = this.handleApprove.bind(this);
16
- this.handleClose = this.handleClose.bind(this);
17
15
  this.isClosing = false;
18
16
  this.modalId = Math.random().toString(36).substring(2, 9);
17
+
18
+ this.state = {
19
+ status: 'idle', // idle, pending, success, error
20
+ statusMessage: ''
21
+ };
22
+
19
23
  console.log(`[DEBUG] ApproveModal instance created with ID: ${this.modalId}`);
20
24
  }
21
25
 
22
- onMount() {
26
+ didMount() {
23
27
  console.log(`[DEBUG-${this.modalId}] ApproveModal mounted to DOM`);
24
- super.onMount();
25
- this.setupEventListeners();
26
- }
27
-
28
- setupEventListeners() {
29
- const approveButton = this.element.querySelector('.approve-button');
30
- const closeButton = this.element.querySelector('.approve-modal-close');
31
- const overlay = this.element.querySelector('.approve-modal-overlay');
32
-
33
- approveButton?.addEventListener('click', this.handleApprove);
34
- closeButton?.addEventListener('click', this.handleClose);
35
- overlay?.addEventListener('click', (e) => {
36
- if (e.target === overlay) this.handleClose();
37
- });
38
28
  }
39
29
 
40
30
  async handleApprove() {
41
31
  console.log(`[DEBUG-${this.modalId}] Approve button clicked`);
42
32
  try {
43
- // Disable the button immediately to prevent multiple clicks
44
- const approveButton = this.element.querySelector('.approve-button');
45
- if (!approveButton) {
46
- console.error(`[DEBUG-${this.modalId}] Approve button not found in the modal`);
47
- return;
48
- }
49
-
50
- console.log(`[DEBUG-${this.modalId}] Approve button found, disabling and updating text`);
51
- const statusMessage = this.element.querySelector('.status-message') ||
52
- document.createElement('div');
53
-
54
- if (!statusMessage.classList.contains('status-message')) {
55
- statusMessage.className = 'status-message';
56
- const modalContent = this.element.querySelector('.approve-modal-content');
57
- if (modalContent) {
58
- console.log(`[DEBUG-${this.modalId}] Adding status message to modal content`);
59
- modalContent.appendChild(statusMessage);
60
- } else {
61
- console.error(`[DEBUG-${this.modalId}] Modal content not found`);
62
- }
63
- }
64
-
65
- statusMessage.textContent = 'Waiting for wallet confirmation...';
66
- statusMessage.className = 'status-message pending';
67
-
68
- approveButton.disabled = true;
69
- approveButton.textContent = 'Approving...';
33
+ this.setState({
34
+ status: 'pending',
35
+ statusMessage: 'Waiting for wallet confirmation...'
36
+ });
70
37
 
71
38
  // Get user address if not provided
72
39
  if (!this.userAddress) {
@@ -91,16 +58,16 @@ export class ApprovalModal extends Component {
91
58
  console.log(`[DEBUG-${this.modalId}] Parsing amount: ${this.amount}`);
92
59
  const parsedAmount = this.blockchainService.parseExec(this.amount);
93
60
  console.log(`[DEBUG-${this.modalId}] Parsed amount: ${parsedAmount}`);
94
-
61
+
95
62
  // Get router address
96
63
  const routerAddress = this.blockchainService.swapRouter?.address || this.blockchainService.swapRouter;
97
64
  console.log(`[DEBUG-${this.modalId}] Router address for approval: ${routerAddress}`);
98
-
65
+
99
66
  // Call the standard setApproval method
100
67
  console.log(`[DEBUG-${this.modalId}] Approving ${this.amount} EXEC tokens from ${this.userAddress} to ${routerAddress}`);
101
-
102
- statusMessage.textContent = 'Transaction submitted, waiting for confirmation...';
103
-
68
+
69
+ this.setState({ statusMessage: 'Transaction submitted, waiting for confirmation...' });
70
+
104
71
  // Send the approval transaction
105
72
  console.log(`[DEBUG-${this.modalId}] Calling blockchainService.setApproval`);
106
73
  try {
@@ -110,58 +77,43 @@ export class ApprovalModal extends Component {
110
77
  console.error(`[DEBUG-${this.modalId}] Transaction error:`, txError);
111
78
  throw txError;
112
79
  }
113
-
80
+
114
81
  // Update status message
115
- statusMessage.textContent = 'Approval successful!';
116
- statusMessage.className = 'status-message success';
117
-
82
+ this.setState({
83
+ status: 'success',
84
+ statusMessage: 'Approval successful!'
85
+ });
86
+
118
87
  // Wait briefly to show success message
119
88
  console.log(`[DEBUG-${this.modalId}] Approval successful, waiting before emitting event`);
120
89
  await new Promise(resolve => setTimeout(resolve, 1500));
121
-
90
+
122
91
  // Emit success event
123
92
  console.log(`[DEBUG-${this.modalId}] Emitting approve:complete event`);
124
93
  this.eventBus.emit('approve:complete');
125
-
94
+
126
95
  // Close modal
127
96
  console.log(`[DEBUG-${this.modalId}] Calling handleClose after successful approval`);
128
97
  this.handleClose();
129
98
 
130
99
  } catch (error) {
131
100
  console.error(`[DEBUG-${this.modalId}] Approval failed:`, error);
132
-
101
+
133
102
  let errorMessage = error.message;
134
103
  if (errorMessage.includes('Contract call')) {
135
104
  const parts = errorMessage.split(': ');
136
105
  errorMessage = parts[parts.length - 1];
137
106
  }
138
-
139
- // Update status message in the modal
140
- const statusMessage = this.element.querySelector('.status-message') ||
141
- document.createElement('div');
142
-
143
- if (!statusMessage.classList.contains('status-message')) {
144
- statusMessage.className = 'status-message';
145
- const modalContent = this.element.querySelector('.approve-modal-content');
146
- if (modalContent) {
147
- modalContent.appendChild(statusMessage);
148
- }
149
- }
150
-
151
- statusMessage.textContent = `Error: ${errorMessage}`;
152
- statusMessage.className = 'status-message error';
153
-
107
+
108
+ this.setState({
109
+ status: 'error',
110
+ statusMessage: `Error: ${errorMessage}`
111
+ });
112
+
154
113
  this.messagePopup.error(
155
114
  `Approval Failed: ${errorMessage}`,
156
115
  'Transaction Failed'
157
116
  );
158
-
159
- // Re-enable button
160
- const approveButton = this.element.querySelector('.approve-button');
161
- if (approveButton) {
162
- approveButton.disabled = false;
163
- approveButton.textContent = 'Approve';
164
- }
165
117
  }
166
118
  }
167
119
 
@@ -173,9 +125,9 @@ export class ApprovalModal extends Component {
173
125
  return;
174
126
  }
175
127
  this.isClosing = true;
176
-
128
+
177
129
  console.log(`[DEBUG-${this.modalId}] Closing approval modal`);
178
-
130
+
179
131
  try {
180
132
  // Remove the modal from the DOM
181
133
  if (this.element && this.element.parentNode) {
@@ -184,11 +136,11 @@ export class ApprovalModal extends Component {
184
136
  } else {
185
137
  console.warn(`[DEBUG-${this.modalId}] Modal element or parent not found during close`);
186
138
  }
187
-
139
+
188
140
  // Emit a closed event
189
141
  console.log(`[DEBUG-${this.modalId}] Emitting approveModal:closed event`);
190
142
  this.eventBus.emit('approveModal:closed');
191
-
143
+
192
144
  // Clean up any resources
193
145
  console.log(`[DEBUG-${this.modalId}] Calling dispose method`);
194
146
  this.dispose();
@@ -196,19 +148,11 @@ export class ApprovalModal extends Component {
196
148
  console.error(`[DEBUG-${this.modalId}] Error closing approval modal:`, error);
197
149
  }
198
150
  }
199
-
151
+
200
152
  // Properly dispose of the component
201
153
  dispose() {
202
154
  console.log(`[DEBUG-${this.modalId}] Disposing component resources`);
203
-
204
- // Remove event listeners
205
- const approveButton = this.element?.querySelector('.approve-button');
206
- const closeButton = this.element?.querySelector('.approve-modal-close');
207
- const overlay = this.element?.querySelector('.approve-modal-overlay');
208
-
209
- approveButton?.removeEventListener('click', this.handleApprove);
210
- closeButton?.removeEventListener('click', this.handleClose);
211
-
155
+
212
156
  // Clear references
213
157
  this.isClosing = true;
214
158
  this.blockchainService = null;
@@ -219,67 +163,64 @@ export class ApprovalModal extends Component {
219
163
  show() {
220
164
  console.log(`[DEBUG-${this.modalId}] Show method called`);
221
165
  this.isClosing = false;
222
- this.element.style.display = 'block';
166
+ if (this.element) {
167
+ this.element.style.display = 'block';
168
+ }
223
169
  console.log(`[DEBUG-${this.modalId}] Modal set to display:block`);
224
170
  }
225
171
 
226
172
  hide() {
227
173
  console.log(`[DEBUG-${this.modalId}] Hide method called`);
228
- this.element.style.display = 'none';
229
- }
230
-
231
- events() {
232
- console.log(`[DEBUG-${this.modalId}] Setting up event handlers`);
233
- return {
234
- 'click .approve-button': (e) => {
235
- console.log(`[DEBUG-${this.modalId}] Approve button clicked, calling handleApprove`);
236
- this.handleApprove();
237
- },
238
- 'click .approve-modal-close': (e) => {
239
- console.log(`[DEBUG-${this.modalId}] Close button clicked, calling handleClose`);
240
- this.handleClose();
241
- },
242
- 'click .approve-modal-overlay': (e) => {
243
- console.log(`[DEBUG-${this.modalId}] Overlay clicked`, e.target, e.currentTarget);
244
- if (e.target === e.currentTarget) {
245
- console.log(`[DEBUG-${this.modalId}] Overlay direct click detected, calling handleClose`);
246
- this.handleClose();
247
- }
248
- }
249
- };
174
+ if (this.element) {
175
+ this.element.style.display = 'none';
176
+ }
250
177
  }
251
178
 
252
179
  render() {
253
180
  // Get router address directly from the blockchain service instead of the store
254
181
  const routerAddress = this.blockchainService.swapRouter?.address || this.blockchainService.swapRouter;
255
182
  const formattedAmount = parseInt(this.amount).toLocaleString();
183
+ const { status, statusMessage } = this.state;
184
+ const isApproving = status === 'pending';
256
185
 
257
- return `
258
- <div class="approve-modal-overlay">
259
- <div class="approve-modal">
260
- <button class="approve-modal-close">&times;</button>
261
- <div class="approve-modal-content">
262
- <h2>Approve Router</h2>
263
- <p>Before selling your $EXEC tokens, you need to approve the router contract to spend them.</p>
264
-
265
- <div class="approve-details">
266
- <div class="approve-info">
267
- <span class="label">Amount to Approve:</span>
268
- <span class="value">${formattedAmount} $EXEC</span>
269
- </div>
270
- <div class="approve-info">
271
- <span class="label">Router Address:</span>
272
- <span class="value">${routerAddress}</span>
273
- </div>
274
- </div>
275
-
276
- <button class="approve-button">
277
- Approve
278
- </button>
279
- </div>
280
- </div>
281
- </div>
282
- `;
186
+ return h('div', {
187
+ className: 'approve-modal-overlay',
188
+ onClick: (e) => {
189
+ if (e.target === e.currentTarget) this.handleClose();
190
+ }
191
+ },
192
+ h('div', { className: 'approve-modal' },
193
+ h('button', {
194
+ className: 'approve-modal-close',
195
+ onClick: this.bind(this.handleClose)
196
+ }, '\u00D7'),
197
+ h('div', { className: 'approve-modal-content' },
198
+ h('h2', null, 'Approve Router'),
199
+ h('p', null, 'Before selling your $EXEC tokens, you need to approve the router contract to spend them.'),
200
+
201
+ h('div', { className: 'approve-details' },
202
+ h('div', { className: 'approve-info' },
203
+ h('span', { className: 'label' }, 'Amount to Approve:'),
204
+ h('span', { className: 'value' }, `${formattedAmount} $EXEC`)
205
+ ),
206
+ h('div', { className: 'approve-info' },
207
+ h('span', { className: 'label' }, 'Router Address:'),
208
+ h('span', { className: 'value' }, routerAddress)
209
+ )
210
+ ),
211
+
212
+ statusMessage && h('div', {
213
+ className: `status-message ${status}`
214
+ }, statusMessage),
215
+
216
+ h('button', {
217
+ className: 'approve-button',
218
+ disabled: isApproving,
219
+ onClick: this.bind(this.handleApprove)
220
+ }, isApproving ? 'Approving...' : 'Approve')
221
+ )
222
+ )
223
+ );
283
224
  }
284
225
 
285
226
  static get styles() {
@@ -370,7 +311,7 @@ export class ApprovalModal extends Component {
370
311
  .approve-button:hover:not(:disabled) {
371
312
  background-color: #0056b3;
372
313
  }
373
-
314
+
374
315
  .status-message {
375
316
  margin-top: 12px;
376
317
  padding: 10px;
@@ -378,21 +319,23 @@ export class ApprovalModal extends Component {
378
319
  text-align: center;
379
320
  font-size: 14px;
380
321
  }
381
-
322
+
382
323
  .status-message.pending {
383
324
  background-color: #2c3e50;
384
325
  color: #f1c40f;
385
326
  }
386
-
327
+
387
328
  .status-message.success {
388
329
  background-color: #27ae60;
389
330
  color: white;
390
331
  }
391
-
332
+
392
333
  .status-message.error {
393
334
  background-color: #c0392b;
394
335
  color: white;
395
336
  }
396
337
  `;
397
338
  }
398
- }export default ApprovalModal;
339
+ }
340
+
341
+ export default ApprovalModal;