322 lines
12 KiB
JavaScript
322 lines
12 KiB
JavaScript
import { Controller } from "@hotwired/stimulus"
|
|
|
|
export default class extends Controller {
|
|
static targets = ["walletType", "walletAddress", "connectBtn", "signature", "modal", "modalTitle", "modalBody"]
|
|
static values = {
|
|
signMessage: String,
|
|
csrfToken: String
|
|
}
|
|
|
|
connect() {
|
|
console.log('Wallet Connect Controller connected');
|
|
this.selectedWallet = null;
|
|
this.walletAddress = null;
|
|
this.signature = null;
|
|
}
|
|
|
|
async onWalletTypeChange(event) {
|
|
this.selectedWallet = event.target.value;
|
|
console.log('Selected wallet type:', this.selectedWallet);
|
|
|
|
if (this.selectedWallet) {
|
|
this.connectBtnTarget.disabled = false;
|
|
this.connectBtnTarget.textContent = 'اتصال کیف پول';
|
|
} else {
|
|
this.connectBtnTarget.disabled = true;
|
|
this.connectBtnTarget.textContent = 'نوع کیف پول را انتخاب کنید';
|
|
}
|
|
}
|
|
|
|
async connectWallet() {
|
|
if (!this.selectedWallet) {
|
|
this.showMessage('لطفاً نوع کیف پول را انتخاب کنید', 'error');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
this.connectBtnTarget.disabled = true;
|
|
this.connectBtnTarget.textContent = 'در حال اتصال...';
|
|
|
|
// Check if Web3 is available
|
|
if (!window.ethereum) {
|
|
this.showMessage('کیف پول Web3 یافت نشد. لطفاً MetaMask یا Trust Wallet را نصب کنید.', 'error');
|
|
return;
|
|
}
|
|
|
|
// Connect to wallet
|
|
const accounts = await window.ethereum.request({
|
|
method: 'eth_requestAccounts'
|
|
});
|
|
|
|
if (accounts.length === 0) {
|
|
this.showMessage('هیچ حساب کیف پولی یافت نشد', 'error');
|
|
return;
|
|
}
|
|
|
|
this.walletAddress = accounts[0];
|
|
console.log('Connected wallet address:', this.walletAddress);
|
|
|
|
// Get sign message
|
|
const signMessage = this.signMessageValue || 'Please sign this message to connect your wallet';
|
|
|
|
// Sign message
|
|
this.signature = await this.signMessage(signMessage);
|
|
if (!this.signature) {
|
|
return;
|
|
}
|
|
|
|
// Submit to server
|
|
await this.submitWalletConnection();
|
|
|
|
} catch (error) {
|
|
console.error('Error connecting wallet:', error);
|
|
this.showMessage('خطا در اتصال کیف پول: ' + error.message, 'error');
|
|
} finally {
|
|
this.connectBtnTarget.disabled = false;
|
|
this.connectBtnTarget.textContent = 'اتصال کیف پول';
|
|
}
|
|
}
|
|
|
|
async signMessage(message) {
|
|
try {
|
|
const signature = await window.ethereum.request({
|
|
method: 'personal_sign',
|
|
params: [message, this.walletAddress]
|
|
});
|
|
return signature;
|
|
} catch (error) {
|
|
console.error('Error signing message:', error);
|
|
this.showMessage('خطا در امضای پیام: ' + error.message, 'error');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async submitWalletConnection() {
|
|
try {
|
|
const formData = {
|
|
walletAddress: this.walletAddress,
|
|
walletType: this.selectedWallet,
|
|
signature: this.signature
|
|
};
|
|
|
|
console.log('Submitting wallet connection:', formData);
|
|
|
|
const response = await fetch('/api/wallet/connect', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-Token': this.csrfTokenValue || ''
|
|
},
|
|
body: JSON.stringify(formData)
|
|
});
|
|
|
|
console.log('Response status:', response.status);
|
|
const data = await response.json();
|
|
console.log('Response data:', data);
|
|
|
|
if (data.success) {
|
|
this.showMessage(data.message, 'success');
|
|
// Reload page to show updated wallet list
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
this.showMessage(data.message, 'error');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error submitting wallet connection:', error);
|
|
this.showMessage('خطا در ارسال اطلاعات: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async setPrimaryWallet(walletId) {
|
|
if (!confirm('آیا میخواهید این کیف پول را به عنوان اصلی تنظیم کنید؟')) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`/api/wallet/${walletId}/set-primary`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-Token': this.csrfTokenValue || ''
|
|
}
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
this.showMessage(data.message, 'success');
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
this.showMessage(data.message, 'error');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error setting primary wallet:', error);
|
|
this.showMessage('خطا در تنظیم کیف پول اصلی: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async toggleWalletStatus(walletId) {
|
|
try {
|
|
const response = await fetch(`/api/wallet/${walletId}/toggle-status`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-Token': this.csrfTokenValue || ''
|
|
}
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
this.showMessage(data.message, 'success');
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
this.showMessage(data.message, 'error');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error toggling wallet status:', error);
|
|
this.showMessage('خطا در تغییر وضعیت کیف پول: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
async deleteWallet(walletId) {
|
|
if (!confirm('آیا مطمئن هستید که میخواهید این کیف پول را حذف کنید؟')) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(`/api/wallet/${walletId}`, {
|
|
method: 'DELETE',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-Token': this.csrfTokenValue || ''
|
|
}
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
this.showMessage(data.message, 'success');
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 1500);
|
|
} else {
|
|
this.showMessage(data.message, 'error');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('Error deleting wallet:', error);
|
|
this.showMessage('خطا در حذف کیف پول: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
showMessage(message, type = 'info') {
|
|
// Create modal if it doesn't exist
|
|
if (!this.hasModalTarget) {
|
|
this.createModal();
|
|
}
|
|
|
|
// Get modal elements directly from DOM
|
|
const modalTitle = document.querySelector('#walletModal .modal-title');
|
|
const modalBody = document.querySelector('#walletModal .modal-body');
|
|
const modalElement = document.querySelector('#walletModal');
|
|
|
|
if (!modalTitle || !modalBody || !modalElement) {
|
|
console.error('Modal elements not found');
|
|
return;
|
|
}
|
|
|
|
// Set modal content
|
|
modalTitle.textContent = type === 'success' ? 'موفقیت' :
|
|
type === 'error' ? 'خطا' : 'اطلاعات';
|
|
|
|
modalBody.innerHTML = `
|
|
<div class="alert alert-${type === 'success' ? 'success' : type === 'error' ? 'danger' : 'info'}">
|
|
${message}
|
|
</div>
|
|
`;
|
|
|
|
// Show modal
|
|
if (window.bootstrap && window.bootstrap.Modal) {
|
|
const modal = new window.bootstrap.Modal(modalElement);
|
|
modal.show();
|
|
} else {
|
|
// Fallback: show modal using basic CSS
|
|
modalElement.style.display = 'block';
|
|
modalElement.classList.add('show');
|
|
document.body.classList.add('modal-open');
|
|
|
|
// Add backdrop
|
|
const backdrop = document.createElement('div');
|
|
backdrop.className = 'modal-backdrop fade show';
|
|
backdrop.id = 'walletModalBackdrop';
|
|
document.body.appendChild(backdrop);
|
|
|
|
// Close modal when clicking backdrop
|
|
backdrop.addEventListener('click', () => {
|
|
this.hideModal();
|
|
});
|
|
|
|
// Close modal when clicking close button
|
|
const closeBtn = modalElement.querySelector('[data-bs-dismiss="modal"]');
|
|
if (closeBtn) {
|
|
closeBtn.addEventListener('click', () => {
|
|
this.hideModal();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
createModal() {
|
|
// Check if modal already exists
|
|
if (document.querySelector('#walletModal')) {
|
|
return;
|
|
}
|
|
|
|
const modalHtml = `
|
|
<div class="modal fade" id="walletModal" tabindex="-1" style="direction: rtl; text-align: right;">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content" style="font-family: 'Yekan Bakh FaNum', 'Tahoma', 'Arial', sans-serif;">
|
|
<div class="modal-header" style="direction: rtl; text-align: right;">
|
|
<h5 class="modal-title" style="direction: rtl; text-align: right; font-family: 'Yekan Bakh FaNum', 'Tahoma', 'Arial', sans-serif;">اطلاعات</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" style="margin-left: 0; margin-right: auto;"></button>
|
|
</div>
|
|
<div class="modal-body" style="direction: rtl; text-align: right; font-family: 'Yekan Bakh FaNum', 'Tahoma', 'Arial', sans-serif;">
|
|
</div>
|
|
<div class="modal-footer" style="direction: rtl; text-align: right;">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" style="font-family: 'Yekan Bakh FaNum', 'Tahoma', 'Arial', sans-serif;">بستن</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
|
}
|
|
|
|
hideModal() {
|
|
const modalElement = document.querySelector('#walletModal');
|
|
const backdrop = document.querySelector('#walletModalBackdrop');
|
|
|
|
if (modalElement) {
|
|
modalElement.style.display = 'none';
|
|
modalElement.classList.remove('show');
|
|
}
|
|
|
|
if (backdrop) {
|
|
backdrop.remove();
|
|
}
|
|
|
|
document.body.classList.remove('modal-open');
|
|
}
|
|
}
|